Шаговики и сдвиговый регистр

sergkr1983
Offline
Зарегистрирован: 09.12.2015

Здравтвуйте. Я новичок в программировании Ардуины, так что сильно не ругайтесь если спрошу абсолютную чушь. Хотелось бы управлять двумя шаговыми двигателями (третим через ардуину напрямую) через сдвиговый регистр 74HC595N. Сколько про него смотрю примеров - везде только светодиоды зажигают. Можно ли сделать управление через него шаговиками? Вот скечт которым я управляю шаговиками:


int motorPins[3][4] = {{2, 3, 4, 5},{6, 7, 8, 9},{10, 11, 12, 13}};
int count;
int count2[3] = {0,0,0};
int delayTime;
int val = 0;
int rot=0;
int incomingByte = 0;
int sign=1;

//Процедура настройки прошивки
void setup() {
 int i;
 Serial.begin(9600);
 
 for (i=0; i<3; i++) {
  for (count = 0; count < 4; count++) {
   pinMode(motorPins[i][count], OUTPUT); //установка режима работы цифровых pin'ов Ардуино
  }
 }
 delayTime=3; //задержка между шагами 3 мс (2 мс - время реакции ШД на подачу напряжения)
}

//Поворот двигателя с номерм sm на один шаг вперёд
void moveForward(int sm) {
 if ((count2[sm] == 0) || (count2[sm] == 1)) {
  count2[sm] = 16;
 }
 count2[sm]>>=1;
 for (count = 3; count >= 0; count--) {
  digitalWrite(motorPins[sm][count], count2[sm]>>count&0x01);
 }
}

//Поворот двигателя с номерм sm на один шаг назад
void moveBackward(int sm) {
 if ((count2[sm] == 0) || (count2[sm] == 1)) {
  count2[sm] = 16;
 }
 count2[sm]>>=1;
 for (count = 3; count >= 0; count--) {
  digitalWrite(motorPins[sm][3 - count], count2[sm]>>count&0x01);
 }
}

//Одновременный поворот двигателей 0, 1, 2 на x, y, z шагов соответственно
void MoveSM(long x, long y, long z) {
  long c[3], c2[3];
  double c1[3], d[3];
  long m, i;
  boolean flg;
  
  c[0] = x;
  c[1] = y;
  c[2] = z;
  
  m = 1;
  for (i=0; i<3; i++) {
    if (m < abs(c[i])) m = abs(c[i]);
  }
  
  for (i=0; i<3; i++) {
    c1[i] = 0;
    d[i] = 1.0 * c[i] / m;
    c2[i] = 0;
  }

  flg = false;
  for (i=0; i<3; i++) {
    if (abs(c1[i]) < abs(c[i])) flg=true;
  }
  while (flg) {
    flg=false;
    for (i=0; i<3; i++) {
      if (abs(c1[i]) < abs(c[i]))
       c1[i] += d[i];
      if (abs(c1[i]) - abs(c2[i]) >= 0.5) {
       if (c[i]>0) {
        c2[i]++;
        moveForward(i);
       } else {
        c2[i]--;
        moveBackward(i);
       }
      }
      if (abs(c1[i]) < abs(c[i])) flg=true;
    }
    delay(delayTime);
  }
}

//Основной цикл
void loop() {
 if (Serial.available() > 0) { //Пришла команда
  long c[4]={0,0,0,0};
  int i;
  sign=1;
  i=0;
  incomingByte = Serial.read();
  while (incomingByte!=';') { //Читаем входящую строку, признак конца строки знак "точка с запятой"
   if (c[i]==0) {
    if (incomingByte=='-')
     sign=-1;
   }
   if (incomingByte==',') {
    c[i]*=sign;
    sign=1;
    i++;
   } else if (incomingByte>='0' && incomingByte<='9') {
    c[i]=c[i]*10+incomingByte-'0';
   }
   while (Serial.available() == 0) {
    delay(2);
   }
   incomingByte = Serial.read();
  }
  c[i]*=sign;
  MoveSM(c[0],c[1],c[2]); //Вращаем двигатели на заданное число шагов
  Serial.println("OK");  //Отправляем компьютеру сообщение "OK", значит можно высылать новую команду
 }
 else
  delay(100); //Если ничего не пришло, ждём 1/10 секуды.
}

А вот скечт сдвигового регистра (как их объединить - ума не приложу):

//Пин подключен к ST_CP входу 74HC595
int latchPin = 8;
//Пин подключен к SH_CP входу 74HC595
int clockPin = 12;
//Пин подключен к DS входу 74HC595
int dataPin = 11;
 
 
 
void setup() {
  //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}
 
void loop() {
  // отсчитываем от 0 до 255  и отображаем значение на светодиоде
  for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) {
    // устанавливаем синхронизацию "защелки" на LOW
    digitalWrite(latchPin, LOW);
    // передаем последовательно на dataPin
    shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay); 
 
    //"защелкиваем" регистр, тем самым устанавливая значения на выходах
    digitalWrite(latchPin, HIGH);
    // пауза перед следующей итерацией
    delay(500);
  }
}

 

vvadim
Offline
Зарегистрирован: 23.05.2012

одни используют бензин для авто, в Бразилии на спирту
а вам типа на помидорах захотелось ездить....

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

Общая идея работы с внешними выходными регистрами такова. Вы формируете свои сигналы не на физических пинах МК, а как состояние битов в специально заведенных для этого переменных, лучше байтовых. Как только все биты установили, то вызываете драйвер, который "пропихивает" эти переменные в сдвиговый регистр. Для контроля того, что Вы сформировали, на этапе отладки рекомендую выводить переменные в последовательный порт в двоичном формате, а состояние выводов регистров контролировать с помощью светодиодов.

sergkr1983
Offline
Зарегистрирован: 09.12.2015

vvadim - вы про что? курите что-то?

В общем подправил код. Со светодиодами отлично работает. А как бы мне движки привязать? Могу послать команду в сериал "3636" и светодиоды по очереди работают. А движки (как я понимаю) тоже по такому принципу работают? Только что за принцип? 

sergkr1983
Offline
Зарегистрирован: 09.12.2015
//Пин подключен к ST_CP входу 74HC595
int latchPin = 8;
//Пин подключен к SH_CP входу 74HC595
int clockPin = 12;
//Пин подключен к DS входу 74HC595
int dataPin = 11;
 
void setup() {
  //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("reset");
}
 
void loop() {
  if (Serial.available() > 0) {
    // Символы от '0' до '9'
    // представлены в ASCII таблице значения от 48 до 57.
    int bitToSet = Serial.read() - 48;
 
    // Записываем HIGH в позицию соответствующую bitToSet
    registerWrite(bitToSet, HIGH);
  }
}
 
// Этот метот записывает байт в регистр
void registerWrite(int whichPin, int whichState) {
// инициализируем и обнуляем байт
  byte bitsToSend = 0;
 
  //Отключаем вывод на регистре
  digitalWrite(latchPin, LOW);
 
  // устанавливаем HIGH в соответствующем бите
  bitWrite(bitsToSend, whichPin, whichState);
 
  // проталкиваем байт в регистр
  shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend);
 
    // "защелкиваем" регистр, чтобы байт появился на его выходах
  digitalWrite(latchPin, HIGH);
}

 

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

sergkr1983 пишет:

А движки (как я понимаю) тоже по такому принципу работают? Только что за принцип? 

Насколько я понимаю, Вы хотите использовать шаговые двигатели. Их существует несколько видов. К каждому из них нужен свой аппаратный драйвер. Просто так, как светодиоды, двигатели подключить к выходу регистра (как и самой Ардуины) нельзя. ИМС погорит. Способов управления шаговыми двигателями тоже несколько. Различаются они по типу двигателя и по величине шага, хотя все они базируются на коммутации обмоток в определеннй последовательности. Об этом много написано и на форуме, и в интернете. Чтобы начать, посмотрите, какие двигатели у Вас в наличии, какие к ним нужны аппаратные драйверы, каков самый простой алгоритм управления. Попробуйте сначала управиться с одним двигателем без регистров. Как все станет самому понятно, что откуда, переходите на регистры.

sergkr1983
Offline
Зарегистрирован: 09.12.2015

Я использую двигатели 28BYG-4 с драйверами ULN2003APG. Думаю самые распространённые у начинающих, т.к. все наборы с ними продают. Без сдвиговых регистров у меня всё работает, но UNO R3 оказалось слишком маленькой. Нужно было MEGA брать. Сейчас уже подумал не об управлением двигателей через сдвиговый регистр (пусть уже на цифровых пинах сидят). У меня остаётся 3 аналоговых пина. Вот думаю через них сдвиговый регистр подключить и лампочки туда навешать.

PS. А будет ли работать?

//Пин подключен к ST_CP входу 74HC595
int latchPin = A1;
//Пин подключен к SH_CP входу 74HC595
int clockPin = A2;
//Пин подключен к DS входу 74HC595
int dataPin = A3;

 

bwn
Offline
Зарегистрирован: 25.08.2014

Как вариант, по I2C PCF8574 для лампочек, кнопок и подобного.

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

sergkr1983 пишет:

У меня остаётся 3 аналоговых пина. Вот думаю через них сдвиговый регистр подключить и лампочки туда навешать.

Должно работать. Только нужно в явном виде правильно сконфигурировать выводы.

ALEXHEX
Offline
Зарегистрирован: 12.12.2013

ЧПУ станок делаете?
Тогда не отступайте от схемы, выложенной автором. У него всё чётко отработано, я повторил схему, теперь люфты убираю, программа работает нормально.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

"PS. А будет ли работать?" Скорей всего так

//Пин подключен к ST_CP входу 74HC595
int latchPin = 15;// A1;
//Пин подключен к SH_CP входу 74HC595
int clockPin = 16;// A2;
//Пин подключен к DS входу 74HC595
int dataPin = 17;// A3;

 

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

А какая разница? в pins_arduino.h А1..А..Аn дефайнами к цыфиркам прикручены.

sergkr1983
Offline
Зарегистрирован: 09.12.2015

ALEXHEX пишет:

ЧПУ станок делаете?
Тогда не отступайте от схемы, выложенной автором. У него всё чётко отработано, я повторил схему, теперь люфты убираю, программа работает нормально.

Да. Только я ещё на компьютере под этот станок свою программу делаю. И к станку предложенному добавил экран и датчик температуры (на фрезер поставлю мониторить нагрев). 

Вот только думаю, что сам фрезер дороговат и поставить простую дрель. Но потянут ли движки (полтора килограммовую дрель)?

А по поводу пинов. Сейчас праздник (ВСЕХ С НОВЫМ ГОДОМ). Потом попробую.

ALEXHEX
Offline
Зарегистрирован: 12.12.2013

Движки очень маленькие, не потянут вообще, нужно хотя бы такие --- 42BYGH47-401A
Да и в целом, попробуй повторить конструкцию, что автор выдал, отрепетируй и потом усложняй.
Самое первое что требуется - люфты погасить, пару недель работы и .... я сейчас на железе собирать буду станину и всё прочее.

sergkr1983
Offline
Зарегистрирован: 09.12.2015

ALEXHEX пишет:

Движки очень маленькие, не потянут вообще, нужно хотя бы такие --- 42BYGH47-401A
Да и в целом, попробуй повторить конструкцию, что автор выдал, отрепетируй и потом усложняй.
Самое первое что требуется - люфты погасить, пару недель работы и .... я сейчас на железе собирать буду станину и всё прочее.

Подскажите начинающему... Эти двигатели можно к драйверам от старых подключить и работа программы вообще не измениться?

sergkr1983
Offline
Зарегистрирован: 09.12.2015

Вот наконец-то опять добрался до своего станка. За праздники подзабыл уже кое-что и прищлось повозиться со сдвиговым регистром. Но проверил и всё отлично работает и на аналоговых выходах. Скетч такой:

//Пин подключен к ST_CP входу 74HC595
int latchPin = A3;
//Пин подключен к SH_CP входу 74HC595
int clockPin = A1;
//Пин подключен к DS входу 74HC595
int dataPin = A2;
 
void setup() {
  //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("reset");
}
 
void loop() {
  
 digitalWrite(latchPin, LOW);
 shiftOut(dataPin, clockPin,  MSBFIRST, 0b00100100);
 digitalWrite(latchPin, HIGH);
  }

Единственное что не понял. Можно ли через него ещё и тройку кнопок слушать? Может подскажите?

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

sergkr1983 пишет:

Единственное что не понял. Можно ли через него ещё и тройку кнопок слушать? Может подскажите?

Регистры 74НС595 могут работать только на выдачу сигнала. Чтобы расширять входы нужны регистры 74НС165 или их аналоги.

 

sergkr1983
Offline
Зарегистрирован: 09.12.2015

Спасибо. Буду знать на будущее..

PS. Новичок. Знал бы - взял бы сразу Mega. Но теперь довольствуюсь чем есть. И то что вообще получается - меня радует. Вот теперь переходнички и проводки с китая дождусь, куплю направляющие и станок почти готов. Скечт - точно....