Управление шаговыми двигателями 28byj-48 через Arduino mega при помощи сигналов step и dir входящих в Arduino

Ivan_2.12.2016
Offline
Зарегистрирован: 03.12.2016

Всем доброго времени суток. Подскажите, кто знает, как запрограммировать 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 через такую схему

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/*
//#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
  }
}

 

Ivan_2.12.2016
Offline
Зарегистрирован: 03.12.2016

Спасибо за отклик. Често. Попробовал залить, но переключение обмоток не происходит совсем. Светодиод на плате показывает, что сигнал на 13 пине появляется и пропадает, а движения (светодиоды на uln2003) нет.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну там надо импульсы подавать. А так?  должно по кругу ШД работать.

/*
#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
  }
}

 

 

Ivan_2.12.2016
Offline
Зарегистрирован: 03.12.2016

Так да. Крутит постоянно. Меняется вращение при изменении сигнала DIR.

Мне посоветовали пока поизучать

http://www.customelectronics.ru/arduino-vneshnie-preryivaniya-podklyuche...

и еще это

http://greenoakst.blogspot.ru/2012/06/arduino-bounce.html

Вот пока что пытаюсь выкраить на это время между работой и буднями))).

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

я ошибся в своем коде #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
  }
}

 

Ivan_2.12.2016
Offline
Зарегистрирован: 03.12.2016

ЭВРИКА!!! Я, конечно, пока слабо понимаю что ты сделал, но РАБОТАЕТ!!! По крайней мере при ручной подаче сигнала STEP через LPT порт!!! Спасибо ОГРОМНОЕ!!! Теперь буду разбираться, что же ты интересного привнес.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

/*
#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
  }
}
Ivan_2.12.2016
Offline
Зарегистрирован: 03.12.2016

Приветствую. Этот вариант, тоже работатет, но есть проблемы с пропусканием шагов при более быстрой подаче сигнала step. Движок, даже, при незначительном ускорении начинает пропускать шаги. Есть ли возможность сделать таким образом, чтобы потом можно было подключить еще 2 движка и он справлялсяс ними? Но, как всегда, проблема с написанием. В примере  http://arduino.ru/Reference/AttachInterrupt  attachInterrupt(0, blink, CHANGE); спокойно обращается к функии void blink(), а у меня опять ему не нравится


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);
 
}
 
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Если ШД пропускает шаги, то это не из-за программы. Надо мощнее цеплять драйвер ШД и повышать напряжение. А тот что у вас , он маломощный.  Конечно можно подлючать несколько ШД и все могут работать одновременно. Главное не запутаться самому в коде и не запутать других.

Ivan_2.12.2016
Offline
Зарегистрирован: 03.12.2016

Драйвер и движок справляются с поставленными задачами 100%, так как пробовал делать это на программе turbo cnc. Но проблема в том, что она работает только под операционной DOS, что крайне не удобно. Почему turbo cnc? Потому что только она, из известных мне, позволяет переключать обмотки двигателя четырьмя управляющими пинами подключенными к драйверу uln2003 через lpt порт. http://homecnc.ru/electro/10-cnc-controller