5-Microstep Drive. Xilinx CPLD

boldive

Переписал код на 10 микрошагов, плюс добавил переход с микрошага в полный шаг. Размерность шага меняется только после поворота двигателя на 1.8° (полный шаг), менять в пределах шага не стал, хотя это легко реализуемо. Для перехода в микрошаг хотел вначале использовать 3 и 5 гармоники из ряда Фурье, а потом просто взял и по экспоненте вытянул синусоиду в меандр. Теперь вот думаю а как было-бы правильнее переходить из синусоиды в меандр использую все 10 шагов? Симуляция в Modelsim показывает что все красиво и работает так как надо. А когда зашиваю код в CPLD то на выходах A1, B1 неожиданно появляются какие-то непонятные импульсы с шастотой шима (20KHz). В симуляторе их нет. Ну и двигатель соответственно дергается но не крутится.

В общем, есть желающие (со знанием Verilog и Xilinx ISE+Modelsim) поучаствовать в проекте и довести код до ума?

А я пока защиту драйва от всяких замыканий и перегрузок испытаю. Сама схема простая но под нее надо новую плату делать. А это время.

7 days later
boldive

Для желающих все это дело повторить, выкладываю все необходимое для домашнего изготовления. Описания нет. Но из картинок и схемы все должно быть понятно. Там же включена и схема с платой программатора для прошивки CPLD.

Программатор прямо вставляется в LPT порт компьютера. Минимальная длинна проводов, никаких кабелей длиньше 30см. Программа для прошивки называется iMPACT. Скачивается бесплатно с сайта Xilinx (ISE Design Suite 11 Standalone Programming Tools). Чтобы его скачать отдельно следуйте инструкции. Не забудьте зарегистрироваться на сайте. Это бесплатно и ни к чему не обязывает.

Плата драйва расчитана под ЛУТ, но так делать не советую. Я использовал текстолит с уже нанесенным фоторезистом. Содержимое .pdf файла распечатывается на пленку и засвечивается через DayLight люминисцентную лампу ~10мин. Результат просто отличный. Фотографии уже спаянной платы я вроде выкладывал выше.

В архиве прошивка на 5 микрошагов (5uStep.ipf). Просто подсоединяется в iMPACT и прошивается.

Если собираетесь покупать IRF540N то попробуйте их заменить на STP30NF20. Они подороже, но работать должны получше.

Если будут стоять IRF540 то напряжение на драйв больше 70V подавать не стоит. У IRF540 max 100V, выбросы напряжения при 70В питании будут около 100В, а может и больше. В этих случаях лучше использовать STP30NF20.

После проявления фоторезиста или нанесения тонера, процарапайте дорожки в цепях затворов выходных MOSFET. Это чтобы туда потом либо перемычку впаять либо 10 Ohm - 33 Ohm сопротивление.

Все вопросы задаем в этой ветке.

Архив с файлами берем тут.

vladumur

Добрый день.
К сожалению столкнулся со сложностью регистрации на ксилинке, почемуто не завершается эта регистрация, первый раз такое вижу…ну да это мои трудности.
скачал софт алтеры “макс”, даже мне далекому от этой темы удалось “запихать” и скомпилить код выложеный под алтеру, прошу выложить полный лог компиляции под алтеру, кто уверен на все 100% что у него все правильно, т.к я неуверен. По крайней мере пины и заполнение плис такиеже как у mura…
Просто создал новый проект указал на файл с кодом, никаких ног ничего вручную не заводил, скомпилилось и пишет ошибок 0.
возможно ли в схеме выложеной здесь, заменить ксилинк на алтеру? или для алтеры нужно другую схему?

boldive

Сегодня покрутил свой мотор на Geckodrive G203V. Никакого свиста и шума. Только легкое “шуршание”. Двигатель раскрутился в три раза быстрее чем у меня получилось на текущем драйве.

Будем трудится над печатной платой и бороться с помехами.

ATLab

Интересно. А можно снять осциллограммы с небольшого резистора, включенного последовательно с какой-нибудь обмоткой (осциллограмму тока в обмотке) на скорости 500-600 полных шагов в сек., потом на 1500-2000 и на максимально возможной скорости?

boldive
ATLab:

Интересно. А можно снять осциллограммы с небольшого резистора, включенного последовательно с какой-нибудь обмоткой (осциллограмму тока в обмотке) на скорости 500-600 полных шагов в сек., потом на 1500-2000 и на максимально возможной скорости?

no problem😁

boldive

Резистор 0.075 Ohm включен последовательно с обмоткой. Напряжения сняты с этого резистора. Двигатель SY85STH80-4208B. Ссылку на его параметры я вроде как в начале этой ветки давал. Управляющая программа Mach3. Сам драйв G203V на 10 микрошагов. Шаг винта 5мм, соответственно 400 пульсов Step на 1мм. На 500 полных шагов в секунду будет 750mm/min перемещение.

На осциллограмме 2В/дел 1ms

1500 полных шагов в секунду будет 2250мм/мин
Те же 2В/дел 1ms

2В/дел 0.5ms и та-же скорость 2250мм/мин

Увеличиваем скорость до 3000мм/мин. 2В/дел 0.5ms
При скорости больше чем 2950мм/мин загорается желтый светодиод. Значит уже недостаточно напряжения питания дря нарастания тока (torque падает).

Идем дальше до 3750мм/мин (дальше Mach не пускает) 2В/дел 0.5ms

Если нужны макро-фотки печатной платы драйва, то могу на мыло выслать или через рапиду в личке. Фотографии на форуме выкладывать не буду.

P.S. За неделю 26 “коллекционеров” скачало файлы. Кто-нибудь будет делать?

arisov77
boldive:

…P.S. За неделю 26 “коллекционеров” скачало файлы. Кто-нибудь будет делать?

Олег, на мой взгляд, повторять вряд ли кто нибудь будет, пока Вы не добьётесь хорошей работы драйвера (тем более после того как Вы написали, что оригинальный Геко лучше работает) и не выложите все доказательства на всеобщее обозрение. Я с подобным столкнулся при усовершенствовании Ченовского rcopen.com/forum/f110/topic40981/361 , тоже думал выложу информацию, кто-то повторит, улучшит, добавит и выложит инфу на всеобщее обозрение. Но, к сожалению своими наработками делятся только на «буржуйском» форуме www.cnczone.com/forums/showthread.php?t=69640, но “там” мне тяжело общаться из-за незнания англицкого. А наши … – в личке мне писали, задавали вопросы. Потом у них спрашиваю – работает? Пишут – да всё работает, далее прошу выложить хоть какие нибудь результаты на всеобщее обозрение – в ответ тишина… Или нет результатов или что то ещё. И так было с несколькими соотечественниками. Так что не обращайте на это внимание (то что никто не повторяет конструкцию) и доводите драйвер «до ума» в одиночку. Это дело нужное!
Успехов Вам!

ATLab
boldive:

Резистор 0.075 Ohm включен последовательно с обмоткой. Напряжения сняты с этого резистора. Двигатель SY85STH80-4208B. Ссылку на его параметры я вроде как в начале этой ветки давал. Управляющая программа Mach3. Сам драйв G203V на 10 микрошагов…

😒😒
Вообще то я имел ввиду осциллограммы работы Вашего драйвера. На Гековские красивые картинки насмотрелся на cnczone.com 😁
Хотя и эти тоже будут к месту: можно наглядно сравнить и поискать разницу.
Снимите осциллограммы еще со своего, а?

arisov77:

Олег, на мой взгляд, повторять вряд ли кто нибудь будет, пока Вы не добьётесь хорошей работы драйвера (тем более после того как Вы написали, что оригинальный Геко лучше работает) и не выложите все доказательства на всеобщее обозрение… Так что не обращайте на это внимание (то что никто не повторяет конструкцию) и доводите драйвер «до ума» в одиночку. Это дело нужное!

Imho, вообще мало кто сможет повторить такой драйвер:
купить и запрограммировать ПЛИС не каждый сможет, плата сложная, монтаж тоже, на коленке без приборов не настроить. Не зря Марисс собирался выпустить минимальный набор для желающих.
В основном ведь за “драйверный самострой” берутся из желания сэкономить, и пока не дошло, что купить проще и быстрее.
Успехов!

Аэробус
ATLab:

В основном ведь за “драйверный самострой” берутся из желания сэкономить

Анатолий, не всегда:). Иногда из азарту там или из интересу… А вдруг заработает. 😒. Но, лучше опереться на опыт специалистов.😉

boldive
ATLab:

😒😒
Вообще то я имел ввиду осциллограммы работы Вашего драйвера.

Imho, вообще мало кто сможет повторить такой драйвер:
купить и запрограммировать ПЛИС не каждый сможет, плата сложная, монтаж тоже, на коленке без приборов не настроить.

Как только переделаю плату, так сразу выложу осциллограммы. Это будет скоро. У меня основная проблемма помехи по step and dir. Это лечится только модернизацией схемы и платы.

Этот драйвер хорошо паяется на коленке с помощью Hot Air Gun. У меня
Aoyue 968 SMD Digital Hot Air Rework Station. За первый вечер вытравил платы, за второй просверлил дырки, а за третий спаял 4 платы. Реально можно и в один выходной уложиться. Если в монтаже ошибок нет то там и настраивать нечего. Все упирается в элементарную аккуратность. Программатор CPLD проще не бывает. Если есть интернет то скачать 560мег programming tool с сайта Xilinx не проблемма. Все бесплатно. Проблемма только одна, купить все это разношерстье SMD компонентов. Тут очень критично к размерам. Хотя сами SMD намного дешевле старых и привычных “ножечных” вариантов. Я уже достаточно с SMD наигрался, и уходить с них не буду, уж больно все удобно и компактно получается. Да и дырок на плате почти не надо сверлить.

Жаль что в России проблеммы с почтой. Я все электронные компоненты покупаю только в трех местах:
http://avnet.com
http://futureelectronics.com
http://digikey.com
С последних двух доставка в течении 24 часов за 8$. Почти бесплатно. Зато первые самые дешевые и с самым большим ассортиментом. Но доставка уже 35$.

11 days later
Impartial

Извиняюсь и может не по теме.
А никто не пробовал такое сделать для управления станком?
www.knjn.com/FPGA-Parallel.html
Ведь преимуществ много!
Легко перенастраивается с шагового режима на серво, не требует программатора, много входов-выходов и простое подключение к LPT порту.
Исходный код открытый под GPL лицензией в ЕМС2.
При желании и знании Verilog или VHDL можно описать и запрограммировать любую конфигурацию оборудования. Но и так существует уже готовое решение и не надо заморачиваться с программированием.
И цена на FPGA типа Cyclone 1,2,3 в районе 10$.

ATLab

Imho, это не по теме. Если есть желание поговорить по этому поводу, начните новую ветку? Не хотелось бы замусоривать эту…

P.S. Не вижу никаких преимуществ у этой отладочной платки, зачем она вообще здесь?
ПЛИСок много всяких разных, и на них потенциально можно сделать черта с рогами 😃
Эта ни хуже ни лучше…

Impartial

Наверное Вы правы!
Но ведь именно на эту плату есть готовые драйвера в EMC2 для работы как сервоприводов, и не в режиме step/dir, так и шаговых двигателей.
Вроде по теме, ведь здесь попытка найти тоже решение.

mura

Я что-то исходников не нашел, можно пальцем ткнуть?

Impartial

Если вопрос ко мне, то здесь “src/hal/drivers/pluto_servo_firmware/”
там же и на шаговики, но с выходом step/dir.
Для полного управления надо подключить модуль, аналогичный рассматриваемому в этом посте.
Речь идет о UBUNTU.
Однако там изначально нет этих исходников.
Необходимо их скачать штатными средствами UBUNTU.
Если интересно, опишу подробнее.

mura

Конечно интересно, а схема данного девайса имеется?

Impartial

Схему сейчас разрабатываю на EP1K30TC144 потому что много в наличии.
Программирование по PPA. Штатное по PS.
Разводка поддерживает и то и другое.
Занимаюсь сервоприводом.
Вам какой исходник?
Вот штатный на сервопривод.
Тут три модуля
1 Servo
2 Quad
3 WDT
Компилится в Квартусе без проблем.
На отладчике тоже вроде все ОК.
На железе еще не пробовал.

// This is a component of pluto_servo, a PWM servo driver and quadrature
// counter for emc2
// Copyright 2006 Jeff Epler <jepler@unpythonic.net>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

module pluto_servo(clk, led, nConfig, epp_nReset, pport_data, nWrite, nWait, nDataStr,
nAddrStr, dout, din, quadA, quadB, quadZ, up, down);
parameter QW=14;
input clk;
output led, nConfig;
inout [7:0] pport_data;
input nWrite;
output nWait;
input nDataStr, nAddrStr, epp_nReset;
wire do_tristate;
reg[9:0] real_dout; output [9:0] dout = do_tristate ? 10’bZZZZZZZZZZ : real_dout;
input [7:0] din;
input [3:0] quadA;
input [3:0] quadB;
input [3:0] quadZ;
wire[3:0] real_up; output [3:0] up = do_tristate ? 4’bZZZZ : real_up;
wire[3:0] real_down; output [3:0] down = do_tristate ? 4’bZZZZ : real_down;
reg Zpolarity;

wire [2*QW:0] quad0, quad1, quad2, quad3;

wire do_enable_wdt;
wire pwm_at_top;
wdt w(clk, do_enable_wdt, pwm_at_top, do_tristate);

// PWM stuff
// PWM clock is about 20kHz for clk @ 40MHz, 11-bit cnt
reg [10:0] pwmcnt;
wire [10:0] top = 11’d2046;
assign pwm_at_top = (pwmcnt == top);
reg [15:0] pwm0, pwm1, pwm2, pwm3;
always @(posedge clk) begin
if(pwm_at_top) pwmcnt <= 0;
else pwmcnt <= pwmcnt + 11’d1;
end

wire [10:0] pwmrev = {
pwmcnt[4], pwmcnt[5], pwmcnt[6], pwmcnt[7], pwmcnt[8], pwmcnt[9],
pwmcnt[10], pwmcnt[3:0]};
wire [10:0] pwmcmp0 = pwm0[14] ? pwmrev : pwmcnt;
// wire [10:0] pwmcmp1 = pwm1[14] ? pwmrev : pwmcnt;
// wire [10:0] pwmcmp2 = pwm2[14] ? pwmrev : pwmcnt;
// wire [10:0] pwmcmp3 = pwm3[14] ? pwmrev : pwmcnt;
wire pwmact0 = pwm0[10:0] > pwmcmp0;
wire pwmact1 = pwm1[10:0] > pwmcmp0;
wire pwmact2 = pwm2[10:0] > pwmcmp0;
wire pwmact3 = pwm3[10:0] > pwmcmp0;
assign real_up[0] = pwm0[12] ^ (pwm0[15] ? 1’d0 : pwmact0);
assign real_up[1] = pwm1[12] ^ (pwm1[15] ? 1’d0 : pwmact1);
assign real_up[2] = pwm2[12] ^ (pwm2[15] ? 1’d0 : pwmact2);
assign real_up[3] = pwm3[12] ^ (pwm3[15] ? 1’d0 : pwmact3);
assign real_down[0] = pwm0[13] ^ (~pwm0[15] ? 1’d0 : pwmact0);
assign real_down[1] = pwm1[13] ^ (~pwm1[15] ? 1’d0 : pwmact1);
assign real_down[2] = pwm2[13] ^ (~pwm2[15] ? 1’d0 : pwmact2);
assign real_down[3] = pwm3[13] ^ (~pwm3[15] ? 1’d0 : pwmact3);

// Quadrature stuff
// Quadrature is digitized at 40MHz into 14-bit counters
// Read up to 2^13 pulses / polling period = 8MHz for 1kHz servo period
reg qtest;
wire qr0, qr1, qr2, qr3;
quad q0(clk, qtest ? real_dout[0] : quadA[0], qtest ? real_dout[1] : quadB[0], qtest ? real_dout[2] : quadZ[0]^Zpolarity, qr0, quad0);
quad q1(clk, quadA[1], quadB[1], quadZ[1]^Zpolarity, qr1, quad1);
quad q2(clk, quadA[2], quadB[2], quadZ[2]^Zpolarity, qr2, quad2);
quad q3(clk, quadA[3], quadB[3], quadZ[3]^Zpolarity, qr3, quad3);

// EPP stuff
wire EPP_write = ~nWrite;
wire EPP_read = nWrite;
wire EPP_addr_strobe = ~nAddrStr;
wire EPP_data_strobe = ~nDataStr;
wire EPP_strobe = EPP_data_strobe | EPP_addr_strobe;

wire EPP_wait; assign nWait = ~EPP_wait;
wire [7:0] EPP_datain = pport_data;
wire [7:0] EPP_dataout; assign pport_data = EPP_dataout;

reg [4:0] EPP_strobe_reg;
always @(posedge clk) EPP_strobe_reg <= {EPP_strobe_reg[3:0], EPP_strobe};
wire EPP_strobe_edge1 = (EPP_strobe_reg[2:1]==2’b01);

// reg led;

assign EPP_wait = EPP_strobe_reg[4];
reg[4:0] addr_reg;
reg[7:0] lowbyte;

always @(posedge clk)
if(EPP_strobe_edge1 & EPP_write & EPP_addr_strobe) begin
addr_reg <= EPP_datain[4:0];
end
else if(EPP_strobe_edge1 & !EPP_addr_strobe) addr_reg <= addr_reg + 4’d1;
always @(posedge clk) begin
if(EPP_strobe_edge1 & EPP_write & EPP_data_strobe) begin
if(addr_reg[3:0] == 4’d1) pwm0 <= { EPP_datain, lowbyte };
else if(addr_reg[3:0] == 4’d3) pwm1 <= { EPP_datain, lowbyte };
else if(addr_reg[3:0] == 4’d5) pwm2 <= { EPP_datain, lowbyte };
else if(addr_reg[3:0] == 4’d7) pwm3 <= { EPP_datain, lowbyte };
else if(addr_reg[3:0] == 4’d9) begin
real_dout <= { EPP_datain[1:0], lowbyte };
Zpolarity <= EPP_datain[7];
qtest <= EPP_datain[5];
end
else lowbyte <= EPP_datain;
end
end

reg [31:0] data_buf;

always @(posedge clk) begin
if(EPP_strobe_edge1 & EPP_read && addr_reg[1:0] == 2’d0) begin
if(addr_reg[4:2] == 3’d0) data_buf <= quad0;
else if(addr_reg[4:2] == 3’d1) data_buf <= quad1;
else if(addr_reg[4:2] == 3’d2) data_buf <= quad2;
else if(addr_reg[4:2] == 3’d3) data_buf <= quad3;
else if(addr_reg[4:2] == 3’d4)
data_buf <= {quadA, quadB, quadZ, din};
end
end

// the addr_reg test looks funny because it is auto-incremented in an always
// block so “1” reads the low byte, "2 and “3” read middle bytes, and “0”
// reads the high byte I have a feeling that I’m doing this in the wrong way.
wire [7:0] data_reg = addr_reg[1:0] == 2’d1 ? data_buf[7:0] :
(addr_reg[1:0] == 2’d2 ? data_buf[15:8] :
(addr_reg[1:0] == 2’d3 ? data_buf[23:16] :
data_buf[31:24]));

wire [7:0] EPP_data_mux = data_reg;
assign EPP_dataout = (EPP_read & EPP_wait) ? EPP_data_mux : 8’hZZ;
assign do_enable_wdt = EPP_strobe_edge1 & EPP_write & EPP_data_strobe & (addr_reg[3:0] == 4’d9) & EPP_datain[6];
assign qr0 = EPP_strobe_edge1 & EPP_read & EPP_data_strobe & (addr_reg[4:2] == 3’d0);
assign qr1 = EPP_strobe_edge1 & EPP_read & EPP_data_strobe & (addr_reg[4:2] == 3’d1);
assign qr2 = EPP_strobe_edge1 & EPP_read & EPP_data_strobe & (addr_reg[4:2] == 3’d2);
assign qr3 = EPP_strobe_edge1 & EPP_read & EPP_data_strobe & (addr_reg[4:2] == 3’d3);
assign led = do_tristate ? 1’BZ : (real_up[0] ^ real_down[0]);
assign nConfig = epp_nReset; // 1’b1;
endmodule

// This is a component of pluto_servo, a PWM servo driver and quadrature
// counter for emc2
// Copyright 2006 Jeff Epler <jepler@unpythonic.net>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1507 USA

module quad(clk, A, B, Z, zr, out);
parameter W=14;
input clk, A, B, Z, zr;
reg [(W-1):0] c, i; reg zl;
output [2*W:0] out = { zl, i, c };
// reg [(W-1):0] c, i; reg zl;

reg [2:0] Ad, Bd;
reg [2:0] Zc;
always @(posedge clk) Ad <= {Ad[1:0], A};
always @(posedge clk) Bd <= {Bd[1:0], B};

wire good_one = &Zc;
wire good_zero = ~|Zc;
reg last_good;

wire index_pulse = good_one && ! last_good;

wire count_enable = Ad[1] ^ Ad[2] ^ Bd[1] ^ Bd[2];
wire count_direction = Ad[1] ^ Bd[2];

always @(posedge clk)
begin
if(Z && !good_one) Zc <= Zc + 2’b1;
else if(!good_zero) Zc <= Zc - 2’b1;
if(good_one) last_good <= 1;
else if(good_zero) last_good <= 0;
if(count_enable)
begin
if(count_direction) c <= c + 1’d1;
else c <= c - 1’d1;
end
if(index_pulse) begin
i <= c;
zl <= 1;
end else if(zr) begin
zl <= 0;
end
end
endmodule

// This is a component of pluto_servo, a PWM servo driver and quadrature
// counter for emc2
// Copyright 2006 Jeff Epler <jepler@unpythonic.net>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

module wdt(clk, ena, cnt, out);
input clk, ena, cnt;
output out;
reg [6:0] timer;
wire timer_top = (timer == 7’d127);
reg internal_enable;
wire out = internal_enable && timer_top;

always @(posedge clk) begin
if(ena) begin
internal_enable <= 1;
timer <= 0;
end else if(cnt && !timer_top) timer <= timer + 7’d1;
end
endmodule

ATLab

Может, все же в новую ветку, а? Это же не трудно!
Как ни интересно, но это не имеет отношения к 5-Microstep Drive.

********

11 days later
arisov77

Может кому пригодиться, вот здесь soel.ru/cms/f/?/364218.pdf есть статейка «Шаговый двигатель, управляемый устройством на ПЛИС»

mura
arisov77:

Может кому пригодиться, вот здесь soel.ru/cms/f/?/364218.pdf есть статейка «Шаговый двигатель, управляемый устройством на ПЛИС»

Автор в реале с ПЛИС не работал, даже начинающий ПЛДшник такого себе не позволит.