Как шаговик крутить обратно?

Putnic
Offline
Зарегистрирован: 15.05.2015

Привет друзья. Написал скетч, который, при получении символа "w" крутит шаговик против часовой стрелки на 360 градусов, т.е. полный оборот. Никак не получается сделать так, чтобы при получении символа "s" крутило в обратную сторону, по часовой. Как это осуществить, помогите пожалуйста.

Вот сам скетч:

#include <Stepper.h>
#include <SPI.h>

char info = 0; //храним данные с буфера
float stepper = 0;
byte input1 = 3;
byte input2 = 4;
byte input3 = 5;
byte input4 = 6;



void setup() {
  Serial.begin(9600); 
  pinMode (input1, OUTPUT);
  pinMode (input2, OUTPUT);
  pinMode (input3, OUTPUT);
  pinMode (input4, OUTPUT);
}


void loop () {

  if (Serial.available()>0){ // читаем, есть ли что-то в буфере
      info = Serial.read();// если есть, то это значение присваиваем переменной info
    } //if

      
  switch (info){ // разноусловная конструкция
    case 'w':    
      while (stepper<50){
        
        digitalWrite(input1, HIGH);
        digitalWrite(input2, LOW);
        digitalWrite(input3, LOW);
        digitalWrite(input4, HIGH);
        delayMicroseconds(800);
        
        digitalWrite(input1, LOW);
        digitalWrite(input2, HIGH);
        digitalWrite(input3, LOW);
        digitalWrite(input4, HIGH);
        delayMicroseconds(800);

        digitalWrite(input1, LOW);
        digitalWrite(input2, HIGH);
        digitalWrite(input3, HIGH);
        digitalWrite(input4, LOW);  
        delayMicroseconds(800);

        digitalWrite(input1, HIGH);
        digitalWrite(input2, LOW);
        digitalWrite(input3, HIGH);
        digitalWrite(input4, LOW);
        delayMicroseconds(800);

        stepper++;
      } //while
      
      if (stepper==50){
        digitalWrite(input1, LOW);
        digitalWrite(input2, LOW);
        digitalWrite(input3, LOW);
        digitalWrite(input4, LOW);
        break;
      } //if
      //while (Serial.available()) Serial.read();
      break;
    
    case 's':
    break;
    
    case 'a':
    break;
    
    case 'd':
    break;
  } //switch
  
  info=0;
  stepper=0;
} //void loop

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

По идее надо просто инвертировать значения - вместо LOW сделать HIGH и наоборот.

Ну и избавиться от повторяющихся кусков кода.

#define CLOCKWISE     1     // имя для направления "по часовой"
#define ANTICLOCKWISE 0     // имя для направления "против часовой"

const byte motorPin[4] = {3, 4, 5, 6};  // пины для подключения шаговика
const int motorSpeed = 800;

// Последовательность ногодрыганья в зависимости от направления:
const byte rotateFWD = 0b10101001; // Один шаг по часовой стрелке
const byte rotateBWD = 0b10010101; // Один шаг против часовой стрелки
/* Пояснение: портянку для 'w' можно кратко записать в виде таблицы:
 M1 M2 M3 M4
 1  0  0  1
 0  1  0  1
 0  1  1  0
 1  0  1  0
 Видно, что можно ужать до верхней половины, т.к. строки 3 и 4 просто инверсны 1 и 2 строкам.
 И записать 1 и 2 строку в 8 бит: 10010101, но запись должна быть справа налево, поэтому 10101001.
 */

int stepper = 0;


void setup() 
{
  Serial.begin(9600); 
  for (byte pin = 0; pin < 4; pin++) pinMode (motorPin[pin], OUTPUT);
}


void loop () 
{
  char info; //храним данные с буфера
  if (Serial.available() > 0)
  { // читаем, есть ли что-то в буфере
    info = Serial.read();// если есть, то это значение присваиваем переменной info
  } //if

  switch (info)
  { // разноусловная конструкция
  case 'w':      // крутим против часовой
    while (stepper<50)
    {
      motorOneStep(ANTICLOCKWISE);
      stepper++;
    } //while
    if (stepper==50) motorStop();
    break;

  case 's':    // крутим по часовой
    while (stepper<50)
    {
      motorOneStep(CLOCKWISE);
      stepper++;
    } //while
    if (stepper==50) motorStop();
    break;

  case 'a':
    break;

  case 'd':
    break;
  } //switch

  stepper = 0;
} //void loop


void motorOneStep(byte dir) // делаем один шаг в заданном направлении
{
  for (byte i = 0; i < 16; i++) 
  {  
    // в циклах 1-4 читаем биты 1-4 и дергаем пины, в циклах 5-8 читаем биты 5-8 и дергаем пины
    // в циклах 9-12 читаем инвертированные биты 1-4, в циклах 13-16 читаем инвертированные биты 5-8
    digitalWrite(motorPin[i%4], i < 8 ? bitRead(dir ? rotateFWD : rotateBWD, i%8) : !bitRead(dir ? rotateFWD : rotateBWD, i%8));
    if(i%4 == 3) delayMicroseconds(motorSpeed); // после каждого 4-го цикла пауза
  }
}


void motorStop() // останавливаем мотор
{
  for (byte pin = 0; pin < 8; pin++) digitalWrite(motorPin[pin], LOW);
}

 

Putnic
Offline
Зарегистрирован: 15.05.2015

Tomasina пишет:

По идее надо просто инвертировать значения - вместо LOW сделать HIGH и наоборот.

Ну и избавиться от повторяющихся кусков кода.

#define CLOCKWISE     1     // имя для направления "по часовой"
#define ANTICLOCKWISE 0     // имя для направления "против часовой"

const byte motorPin[4] = {3, 4, 5, 6};  // пины для подключения шаговика
const int motorSpeed = 800;

// Последовательность ногодрыганья в зависимости от направления:
const byte rotateFWD = 0b10101001; // Один шаг по часовой стрелке
const byte rotateBWD = 0b10010101; // Один шаг против часовой стрелки
/* Пояснение: портянку для 'w' можно кратко записать в виде таблицы:
 M1 M2 M3 M4
 1  0  0  1
 0  1  0  1
 0  1  1  0
 1  0  1  0
 Видно, что можно ужать до верхней половины, т.к. строки 3 и 4 просто инверсны 1 и 2 строкам.
 И записать 1 и 2 строку в 8 бит: 10010101, но запись должна быть справа налево, поэтому 10101001.
 */

int stepper = 0;


void setup() 
{
  Serial.begin(9600); 
  for (byte pin = 0; pin < 4; pin++) pinMode (motorPin[pin], OUTPUT);
}


void loop () 
{
  char info; //храним данные с буфера
  if (Serial.available() > 0)
  { // читаем, есть ли что-то в буфере
    info = Serial.read();// если есть, то это значение присваиваем переменной info
  } //if

  switch (info)
  { // разноусловная конструкция
  case 'w':      // крутим против часовой
    while (stepper<50)
    {
      motorOneStep(ANTICLOCKWISE);
      stepper++;
    } //while
    if (stepper==50) motorStop();
    break;

  case 's':    // крутим по часовой
    while (stepper<50)
    {
      motorOneStep(CLOCKWISE);
      stepper++;
    } //while
    if (stepper==50) motorStop();
    break;

  case 'a':
    break;

  case 'd':
    break;
  } //switch

  stepper = 0;
} //void loop


void motorOneStep(byte dir) // делаем один шаг в заданном направлении
{
  for (byte i = 0; i < 16; i++) 
  {  
    // в циклах 1-4 читаем биты 1-4 и дергаем пины, в циклах 5-8 читаем биты 5-8 и дергаем пины
    // в циклах 9-12 читаем инвертированные биты 1-4, в циклах 13-16 читаем инвертированные биты 5-8
    digitalWrite(motorPin[i%4], i < 8 ? bitRead(dir ? rotateFWD : rotateBWD, i%8) : !bitRead(dir ? rotateFWD : rotateBWD, i%8));
    if(i%4 == 3) delayMicroseconds(motorSpeed); // после каждого 4-го цикла пауза
  }
}


void motorStop() // останавливаем мотор
{
  for (byte pin = 0; pin < 8; pin++) digitalWrite(motorPin[pin], LOW);
}

 

Загрузил скетч. Шаговик крутит, как хочет. На символ W может крутить как по часовой, так и против. Так же и с S - крутит то в одну, то в другую сторону. Может, поможет наладить правильную работу шаговика его схема. Фото скрепил. Шаговик подключен через драйвер L298N.

 

nevkon
Offline
Зарегистрирован: 20.01.2015

А двигатель подключен правильно? А то такое бывает при неправильном подключении.

Putnic
Offline
Зарегистрирован: 15.05.2015

Вот набросок, как соединил: 

----------------------

Провода от шаговика подключил к драйверу L298N следующим образом:

Черный: int1

Зеленый: int2

Синий: int3

Красный: int4

Черный и Зеленый - пара и Синий Красный - пара.

----------------------

Далее, от драйвера L298N подключаю к ардуино:

к pin3 соединен int1 (черный)

к pin4 соединен int2 (зеленый)

к pin5 соединен int3 (синий)

к pin6 соединен int4 (красный)

----------------------

 

 

Putnic
Offline
Зарегистрирован: 15.05.2015

Ребята, что скажете насчет кода и сборки шаговика? В чем причина не стаильной работы?