5-Microstep Drive. Xilinx CPLD

Аэробус
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 есть статейка «Шаговый двигатель, управляемый устройством на ПЛИС»

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

7 days later
boldive

Слепил. Пойду смотреть откуда дым повалит😲

Силовая часть сделана на связке IR2104 + STP30NF20
Две отптопары HCPL2531 (для STEP, DIR) и PS2501 (Enable) еще не запаял. Они будут с обратной стороны платы (в левом верхнем углу на картинке видны посадочные места).

13 days later
boldive

Еще немножко доработал схему и теперь все работает. Сделал какое-то подобие морфинга. Вначале было 1/10 => 1/4 => 1/2 => FullStep а потом сделал по другому. Стал синусоиду вытягивать по экспоненте (опорное напряжение стало походить на трапецию). Что-то так мне больше нравится. Более плавно. Максимальная скорость которую могу вытащить из Mach3 3750мм/мин (1/10 микрошаг, 5мм винт) и на этой скорости крутит. Драйвер и мотор греются не шибко сильно. По ходу работы из мотора слышно какое-то постукивание, не механическое, явно электрического происхождения. Примерно каждые 3-6сек слышен такой “ТУК”. Надо на станке погонять и посмотреть что там с пропуском шагов, если кончно будет. Где-то на 2300мм/мин идет резонанс. Вот с этим облом. Тут только программой не обойдешься, надо менять схемотехнику. Только непонятно откуда начинать. Можно сравнивать ток обмотки мотора (в идеале экспонента) с какой-то опорной экспонентой и в случае расхождения выдавать сигнал на CPLD (при резонансе экспонента начинает вытягиваться в синусоиду). А вот что дальше менять в алгоритме работы пока не знаю.

to ATLab. Посмотрел я на картинки тока в обмотках двигателя. Такие-же как и в G203V (это когда резонанса нет). Практически все один в один. Форму тока при резонансе надо снимать на видео, тогда будет видно как она “раздувается”.

ATLab
boldive:

… Форму тока при резонансе надо снимать на видео, тогда будет видно как она “раздувается”.

Что значит “раздувается”? Что раздувается?

boldive
ATLab:

Что значит “раздувается”? Что раздувается?

Пост №96. Последние две картинки показывают форму тока когда резонанса нет.
Перед переходом в резонанс форма тока начинает “раздуваться” и больше походить на синусоиду чем на экспоненту.

А при самом резонансе уже почти синусоида.

Ну видео как все это происходит тут:

На 53сек четко виден переход в резонанс. Весь этот “визжащий-надрывный” звук из ролика когда мотор в резонансе и вал не крутится.

13 days later
boldive

Покрутил на станке. 1/10 микрошаг. Винт 5мм. Голый мотор уходил в резонанс на скорости 2300мм/мин. Воткнул на ось Y. Теперь полоса резонанса с 2400 до 3100 мм/мин. Выше 3100мм/мин и до 3750мм/мин (Mach3 больше не дает) никаких проблемм.

Порылся в интернете и понял что тема борьбы с резонансом “засекречена”. Есть общие идеи с которых можно начинать, но как именно это реализовывать в системах контроля с open-loop под завесой тайны.

На http://cnczone.com нашел только единственную фразу проливающую свет на решение проблеммы.
The midband resonance circuit adds a derivative component (+80 degrees
phase lead) to the system phase angle to eliminate parametric
resonance. It involves sensing the rate of motor load change
(derivative of motor torque) which then phase modulates the internal
step pulse timing.

Может у кого есть еще какие-то практические мнения по этому поводу?

ATLab
  1. Самое простое - посмотреть как это делается в Gecko. Проследить по плате драйвера кусок схемы на ОУ от измерительных резисторов до компараторов и попытаться понять, что там творится.
  2. Поискать патенты.
boldive

Как сделано в геко посмотрел, даже схемку нарисовал. Там с каждого current sense резистора через сопротивление в 10К (оба этих резистора соединены вместе) снимается сигнал (получается суммарный сигнал) и идет на ОУ который является фильтром низких частот, а с него на компаратор. С компаратора на CPLD. Что дальше происходит в программе пока непонятно. Причем опорное напряжение для компаратора тоже формируется от CPLD.

Патенты искал. Пока ничего путного не нашел.

mura
boldive:

Там с каждого current sense резистора через сопротивление в 10К (оба этих резистора соединены вместе) снимается сигнал (получается суммарный сигнал)

Может это для защиты цепь?
Или для поддержания “среднего” тока?

boldive

Защита там по другому выполнена и к CPLD не имеет отношения. “Защелка” на двух элементах НЕ. На входе сигнал от терминала “Enable”. На выходе сигнал SD для IR2104. Плюс, туда еще приходит сигнал с токового резистора стоящего в цепи общего питания драйвера (собственно защита).