Управление шаговыми двигателями 28byj-48 через Arduino mega при помощи сигналов step и dir входящих в Arduino
- Войдите на сайт для отправки комментариев
Всем доброго времени суток. Подскажите, кто знает, как запрограммировать arduino mega 2560 для управления 3мя шаговыми двигателями 28byj-48 через микросхему uln2003? Проблема в том, что управление скоростью и направлением вращения необходимо осуществить двумя проводами (сигналами) step и dir, которые будут подключаться к arduino, как входные сигналы. Входящий сигнал подается через триггер Шмитта для предотвращения "дребезжания".
Есть черновой набросок на один двигатель, но у него большие проблемы с входящим сигналом, переключение обмоток происходит далеко не с первого раза.
int pins[] = {2,3,4,5};//Задаем пины по порядку
int StPin = 13;
int DirPin = 12;
int phases = 8; // для шагового режима установить 4
int phase = 1;
uint8_t motorPhases[8][4] = { // [phase][pin]
{HIGH,HIGH,LOW,LOW},
{LOW,HIGH,LOW,LOW},
{LOW,HIGH,HIGH,LOW},
{LOW,LOW,HIGH,LOW},
{LOW,LOW,HIGH,HIGH},
{LOW,LOW,LOW,HIGH},
{HIGH,LOW,LOW,HIGH},
{HIGH,LOW,LOW,LOW}
};
void out(int ph,int pns[]){
digitalWrite(pns[0],motorPhases[ph-1][0]);
digitalWrite(pns[1],motorPhases[ph-1][1]);
digitalWrite(pns[2],motorPhases[ph-1][2]);
digitalWrite(pns[3],motorPhases[ph-1][3]);
}
void setup() {
pinMode(StPin, INPUT);
pinMode(DirPin, INPUT);
pinMode(pins[0], OUTPUT);
pinMode(pins[1], OUTPUT);
pinMode(pins[2], OUTPUT);
pinMode(pins[3], OUTPUT);
}
void loop() {
if(digitalRead(StPin)==HIGH){
if(digitalRead(DirPin)==HIGH){
phase=phase+1;
}
else{
phase=phase-1;
}
}
if(phase==9){ phase=1;}
if(phase==0){ phase=8;}
out(phase,pins);
while(1){
if(digitalRead(StPin) == LOW){
break;
}
}
}
Сигнал на step подается пока на arduino 13 pin через такую схему

Сам униполярный движок приводится в движение поочередной подачей сигналов на включение обмоток через такую схему

/* //#1 шаговый двигатель <- {2,3,4,5} (SM_pin[]) вывод STEP -> 13 (STEP_pin) если 1->0 сделать шаг шагов.двиг вывод DIR -> 12 () 1 вращать по часовой / 0 против */ const int SM_pin[] = {2, 3, 4, 5}; //Задаем пины по порядку const int STEP_pin = 13; uint8_t STEP_value = 0xFF; // состояние на пине STEP const int DIR_pin = 12; void Do_Step() { // сделать шаг шаговым двигателем const int pos_max = 8; // для шагового режима установить 4 static int pos = 0; // позиция шагов двигателя 0,..,7 static const uint8_t motorPhases[8][4] = { // [phase][pin] {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 0} }; if (digitalRead(DIR_pin)) // если 1 то поворот по часовой pos = (pos + 1) % pos_max; else pos = pos_max * (pos <= 0) + pos - 1; digitalWrite(SM_pin[0], motorPhases[pos][0]); digitalWrite(SM_pin[1], motorPhases[pos][1]); digitalWrite(SM_pin[2], motorPhases[pos][2]); digitalWrite(SM_pin[3], motorPhases[pos][3]); } void setup() { //#1 pinMode(STEP_pin, INPUT_PULLUP); pinMode(DIR_pin, INPUT_PULLUP); pinMode(SM_pin[0], OUTPUT); pinMode(SM_pin[1], OUTPUT); pinMode(SM_pin[2], OUTPUT); pinMode(SM_pin[3], OUTPUT); digitalWrite(SM_pin[0], 0); digitalWrite(SM_pin[1], 0); digitalWrite(SM_pin[2], 0); digitalWrite(SM_pin[3], 0); } void loop() { //#1 static uint32_t past_1 = 0 ; if (millis() - past_1 >= 5) { // опрос карточки идет каждые 200 миллисек past_1 = millis() ; STEP_value = STEP_value << 1 | digitalRead(DIR_pin); if ( (STEP_value & 3)==2) Do_Step(); // если только что произошел перепад (1->0)на выводе STEP } }Спасибо за отклик. Често. Попробовал залить, но переключение обмоток не происходит совсем. Светодиод на плате показывает, что сигнал на 13 пине появляется и пропадает, а движения (светодиоды на uln2003) нет.
Ну там надо импульсы подавать. А так? должно по кругу ШД работать.
/* #1 шаговый двигатель <- {2,3,4,5} (SM_pin[]) вывод STEP -> 13 (STEP_pin) если 1->0 сделать шаг шагов.двиг вывод DIR -> 12 () 1 вращать по часовой / 0 против */ //#1 const int SM_pin[] = {2, 3, 4, 5}; //Задаем пины по порядку const int STEP_pin = 13; uint8_t STEP_value = 0xFF; // состояние на пине STEP const int DIR_pin = 12; void Do_Step() { // сделать шаг шаговым двигателем const int pos_max = 8; // для шагового режима установить 4 static int pos = 0; // позиция шагов двигателя 0,..,7 static const uint8_t motorPhases[8][4] = { // [phase][pin] {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 0} }; if (digitalRead(DIR_pin)) // если 1 то поворот по часовой pos = (pos + 1) % pos_max; else pos = pos_max * (pos <= 0) + pos - 1; digitalWrite(SM_pin[0], motorPhases[pos][0]); digitalWrite(SM_pin[1], motorPhases[pos][1]); digitalWrite(SM_pin[2], motorPhases[pos][2]); digitalWrite(SM_pin[3], motorPhases[pos][3]); } void setup() { //#1 pinMode(STEP_pin, INPUT_PULLUP); pinMode(DIR_pin, INPUT_PULLUP); pinMode(SM_pin[0], OUTPUT); pinMode(SM_pin[1], OUTPUT); pinMode(SM_pin[2], OUTPUT); pinMode(SM_pin[3], OUTPUT); digitalWrite(SM_pin[0], 0); digitalWrite(SM_pin[1], 0); digitalWrite(SM_pin[2], 0); digitalWrite(SM_pin[3], 0); } void loop() { //#1 static uint32_t past_1 = 0 ; if (millis() - past_1 >= 10) { // опрос карточки идет каждые 200 миллисек past_1 = millis() ; Do_Step(); // если только что произошел перепад (1->0)на выводе STEP } }Так да. Крутит постоянно. Меняется вращение при изменении сигнала DIR.
Мне посоветовали пока поизучать
http://www.customelectronics.ru/arduino-vneshnie-preryivaniya-podklyuche...
и еще это
http://greenoakst.blogspot.ru/2012/06/arduino-bounce.html
Вот пока что пытаюсь выкраить на это время между работой и буднями))).
я ошибся в своем коде #1
/* //#1 шаговый двигатель <- {2,3,4,5} (SM_pin[]) вывод STEP -> 13 (STEP_pin) если 1->0 сделать шаг шагов.двиг вывод DIR -> 12 () 1 вращать по часовой / 0 против */ const int SM_pin[] = {2, 3, 4, 5}; //Задаем пины по порядку const int STEP_pin = 13; uint8_t STEP_value = 0xFF; // состояние на пине STEP const int DIR_pin = 12; void Do_Step() { // сделать шаг шаговым двигателем const int pos_max = 8; // для шагового режима установить 4 static int pos = 0; // позиция шагов двигателя 0,..,7 static const uint8_t motorPhases[8][4] = { // [phase][pin] {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 0} }; if (digitalRead(DIR_pin)) // если 1 то поворот по часовой pos = (pos + 1) % pos_max; else pos = pos_max * (pos <= 0) + pos - 1; digitalWrite(SM_pin[0], motorPhases[pos][0]); digitalWrite(SM_pin[1], motorPhases[pos][1]); digitalWrite(SM_pin[2], motorPhases[pos][2]); digitalWrite(SM_pin[3], motorPhases[pos][3]); } void setup() { //#1 pinMode(STEP_pin, INPUT_PULLUP); pinMode(DIR_pin, INPUT_PULLUP); pinMode(SM_pin[0], OUTPUT); pinMode(SM_pin[1], OUTPUT); pinMode(SM_pin[2], OUTPUT); pinMode(SM_pin[3], OUTPUT); digitalWrite(SM_pin[0], 0); digitalWrite(SM_pin[1], 0); digitalWrite(SM_pin[2], 0); digitalWrite(SM_pin[3], 0); } void loop() { //#1 static uint32_t past_1 = 0 ; if (millis() - past_1 >= 5) { // опрос карточки идет каждые 200 миллисек past_1 = millis() ; STEP_value = STEP_value << 1 | digitalRead(STEP_pin); // !!! надо было STEP_pin вместо DIR_pin if ( (STEP_value & 3)==2) Do_Step(); // если только что произошел перепад (1->0)на выводе STEP } }ЭВРИКА!!! Я, конечно, пока слабо понимаю что ты сделал, но РАБОТАЕТ!!! По крайней мере при ручной подаче сигнала STEP через LPT порт!!! Спасибо ОГРОМНОЕ!!! Теперь буду разбираться, что же ты интересного привнес.
/* #1 шаговый двигатель <- {2,3,4,5} (SM_pin[]) вывод STEP -> 13 (STEP_pin) если 1->0 сделать шаг шагов.двиг вывод DIR -> 12 () 1 вращать по часовой / 0 против */ //#1 const int SM_pin[] = {2, 3, 4, 5}; //Задаем пины по порядку const int STEP_pin = 13; uint8_t STEP_value; // состояние на пине STEP uint8_t STEP_value_old; // старое состояние на пине STEP const int DIR_pin = 12; void Do_Step() { // сделать шаг шаговым двигателем const int pos_max = 8; // для шагового режима установить 4 static int pos = 0; // позиция шагов двигателя 0,..,7 static const uint8_t motorPhases[8][4] = { // [phase][pin] {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 0} }; if (digitalRead(DIR_pin)) // если 1 то поворот по часовой pos = (pos + 1) % pos_max; else pos = pos_max * (pos <= 0) + pos - 1; digitalWrite(SM_pin[0], motorPhases[pos][0]); digitalWrite(SM_pin[1], motorPhases[pos][1]); digitalWrite(SM_pin[2], motorPhases[pos][2]); digitalWrite(SM_pin[3], motorPhases[pos][3]); } void setup() { //#1 pinMode(STEP_pin, INPUT_PULLUP); STEP_value = digitalRead(STEP_pin); pinMode(DIR_pin, INPUT_PULLUP); pinMode(SM_pin[0], OUTPUT); pinMode(SM_pin[1], OUTPUT); pinMode(SM_pin[2], OUTPUT); pinMode(SM_pin[3], OUTPUT); Do_Step(); } void loop() { //#1 static uint32_t past_1 = 0 ; if (millis() - past_1 >= 5) { // опрос карточки идет каждые 200 миллисек past_1 = millis() ; STEP_value_old = STEP_value; STEP_value = digitalRead(STEP_pin); if ( STEP_value_old == 1 && STEP_value == 0 ) Do_Step(); // если только что произошел перепад (1->0)на выводе STEP } }Приветствую. Этот вариант, тоже работатет, но есть проблемы с пропусканием шагов при более быстрой подаче сигнала step. Движок, даже, при незначительном ускорении начинает пропускать шаги. Есть ли возможность сделать таким образом, чтобы потом можно было подключить еще 2 движка и он справлялсяс ними? Но, как всегда, проблема с написанием. В примере http://arduino.ru/Reference/AttachInterrupt attachInterrupt(0, blink, CHANGE); спокойно обращается к функии
voidblink(), а у меня опять ему не нравится
int pins[] = {2,3,4,5};//Задаем пины по порядку int StPin = 13; int DirPin1 = 12; int phases = 8; // для шагового режима установить 4 int phase = 1; int state = LOW; volatile int state1 = LOW; uint8_t motorPhases[8][4] = { // [phase][pin] {HIGH,HIGH,LOW,LOW}, {LOW,HIGH,LOW,LOW}, {LOW,HIGH,HIGH,LOW}, {LOW,LOW,HIGH,LOW}, {LOW,LOW,HIGH,HIGH}, {LOW,LOW,LOW,HIGH}, {HIGH,LOW,LOW,HIGH}, {HIGH,LOW,LOW,LOW} }; void out(int ph,int pns[]){ digitalWrite(pns[0],motorPhases[ph-1][0]); digitalWrite(pns[1],motorPhases[ph-1][1]); digitalWrite(pns[2],motorPhases[ph-1][2]); digitalWrite(pns[3],motorPhases[ph-1][3]); } void setup() { attachInterrupt(1, button1, CHANGE); pinMode(StPin, INPUT); pinMode(DirPin1, INPUT_PULLUP); pinMode(pins[0], OUTPUT); pinMode(pins[1], OUTPUT); pinMode(pins[2], OUTPUT); pinMode(pins[3], OUTPUT); } void button1 (){ state1 = !state1; } void loop() { if(state != state1){ if(digitalRead(DirPin1) == HIGH){ phase = phase+1; state = state1; } else{ phase = phase-1; state = state1; } } if(phase==9){ phase=1;} if(phase==0){ phase=8;} out(phase,pins); }Если ШД пропускает шаги, то это не из-за программы. Надо мощнее цеплять драйвер ШД и повышать напряжение. А тот что у вас , он маломощный. Конечно можно подлючать несколько ШД и все могут работать одновременно. Главное не запутаться самому в коде и не запутать других.
Драйвер и движок справляются с поставленными задачами 100%, так как пробовал делать это на программе turbo cnc. Но проблема в том, что она работает только под операционной DOS, что крайне не удобно. Почему turbo cnc? Потому что только она, из известных мне, позволяет переключать обмотки двигателя четырьмя управляющими пинами подключенными к драйверу uln2003 через lpt порт. http://homecnc.ru/electro/10-cnc-controller