Плавный пуск и остановка биполярного шагового двигателя. Спец драйвер на Digispark Attiny85.

Здравствуйте!

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


Уникальность этого проекта в том, что благодаря связи платы Arduino с платой Digispark по шине I2C, всего по двум проводам, одной платой Arduino можно выполнять управление до 125 шаговых двигателей.


На фото которое ниже показано подключение двух шаговых двигателей к плате Arduino Nano. В принципе это могут быть и другие платы, например: Arduino Uno, Arduino Mega, Arduino Pro Mini, Arduino Pro Micro, да практически любая плата из линейки Arduino.

Плавный пуск и остановка шагового двигателя на Digispark и Arduino

В этом проекте плата Arduino является мастером, то есть главным устройством в шине I2C, поэтому пример кода который ниже следует загрузить в нее! Данный код позволяет управлять двумя униполярными шаговыми двигателями по I2C адресам 7 и 8.



Пример кода для Arduino (Master), для управления каждым шаговым двигателем по отдельности.


//Начало скетча

#include <Wire.h>
void send_to_I2C(int int_x, int ADDR_to_Slave);
byte masiv[2];
void setup() {
  delay(6000);
  Wire.begin(1);            // i2c адрес платы Arduino будет #1
}
void loop() {
      send_to_I2C(119, 8);  //Mitsumi установка значения ускорения
      send_to_I2C(100, 8);  //Mitsumi разгон до 100%
      send_to_I2C(100, 7);  //Nema17  разгон до 100%
      delay(15000);
      send_to_I2C(0, 8);    //Mitsumi полная остановка
      send_to_I2C(30, 7);   //Nema17  снижение скорости до 30%
      delay(15000);
      send_to_I2C(110, 8);  //Mitsumi установка значения ускорения
      send_to_I2C(103, 8);  //Mitsumi изменение направления вращения
      send_to_I2C(100, 8);  //Mitsumi разгон до 100%
      delay(15000);
      send_to_I2C(101, 8);  //Mitsumi мгновенная остановка
      send_to_I2C(102, 8);  //Mitsumi изменение направления вращения
      delay(5000);    
}//void loop()

void send_to_I2C(int int_x, int ADDR_to_Slave){
  Wire.beginTransmission(ADDR_to_Slave);// Начать передачу данных
  masiv[0] = (int_x >> 8);
  masiv[1] = (int_x & 0xff);
  Wire.write(masiv[0]);                 // Отправка байта
  Wire.write(masiv[1]);                 // Отправка байта
  Wire.endTransmission();               // Прекратить передачу
}

//Конец скетча




Еще один пример кода для Arduino (Master), но он уже для управления одновременно всеми шаговыми двигателями одной командой.


//Начало скетча

#include <Wire.h>
void send_to_I2C(int int_x, int ADDR_to_Slave);
byte masiv[2];
void setup() {
  delay(6000);
  Wire.begin(1);            // i2c адрес платы Arduino будет #1
}
void loop() {
      send_to_I2C(100, 0);  //разгон до 100% всех шаговых двигателей
      delay(5000);
      send_to_I2C(0, 0);    //полная остановка всех шаговых двигателей
      delay(5000);    
}//void loop()

void send_to_I2C(int int_x, int ADDR_to_Slave){
  Wire.beginTransmission(ADDR_to_Slave);// Начать передачу данных
  masiv[0] = (int_x >> 8);
  masiv[1] = (int_x & 0xff);
  Wire.write(masiv[0]);                 // Отправка байта
  Wire.write(masiv[1]);                 // Отправка байта
  Wire.endTransmission();               // Прекратить передачу
}


//Конец скетча




Так как для платы Arduino был задан I2C адрес 1, и для отправки команд используются адреса 7 и 8, то для плат Digispark следует указать также адреса 7 и 8.

Информацию о том как прошить плату Digispark по этой ссылке



Код программы для Digispark (Slave)


//Начало скетча

#include <USIWire.h>
const int SLAVE_ADDR = 0x8; // i2c адрес этого устройства

const int STEP = 1;   //Контакт STEP подключается к контакту 1
const int DIR = 3;    //Контакт DIR подключается к контакту 3

int z = 35; //Ускорение по умолчанию 35 миллисекунд

//Ускорение, задается командами от 110 до 120
//Команды   110 111 112 113 114 115 116 117 118 119 120          
int z_[] = {1,  5,  10, 15, 25, 35, 45, 60, 75, 95, 120};

//100 скоростей 0   1     2     3     4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   24   28   29   30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94 95 96 97 98 99 100
int speed_[] = {0,30000,15000,10000,7500,6000,5000,4286,3751,3335,3002,2729,2501,2308,2143,2000,1875,1764,1666,1578,1499,1427,1362,1305,1250,1200,1153,1104,1064,1027,991,956,922,889,857,826,796,766,737,708,680,652,625,598,572,547,523,500,478,457,437,418,400,383,366,350,335,321,308,296,285,275,266,258,251,245,240,235,230,225,220,215,210,205,200,195,190,185,180,175,170,165,160,155,150,145,140,135,130,125,120,115,110,105,100,95,90,85,70,75,60};                  

int i = 0, i2 = 0, x = 0, index, x_speed;
boolean flag = 1, State = LOW;
long timing = 0, timing1 = 0;

void read_I2C(int how_many);

void setup()
{ 
  Wire.begin(SLAVE_ADDR);
  Wire.onReceive(read_I2C);
  pinMode(STEP, OUTPUT);
  pinMode(DIR, OUTPUT); digitalWrite(DIR, LOW);
}

void loop()
{ 
     if(x >= 0 && x <= 100){x_speed = x;}
     if(x == 101){i2 = 0;}                    //Резкая остановка шагового двигателя
     if(x == 102){digitalWrite(DIR, LOW);}    //Задать направление вращения влево
     if(x == 103){digitalWrite(DIR, HIGH);}   //Задать направление вращения вправо
     if(x >= 110 && x <=120){index = x - 110; z = z_[index];}//Задать ускорение
     
//Следующие 5 сток выполняют ускорение, или замедление вращения шагового двигателя
    if (millis() - timing1 > z && i2 != x_speed && (x >= 0 && x <= 100)){ 
      timing1 = millis();         
      if(i2 < x_speed){i2++; if(i2 > 100){i2 = 100;}} //Если i2 меньше x, то увеличить скорость 
      if(i2 > x_speed){i2--; if(i2 < 0){i2 = 0;}}     //Если i2 больше x, то уменьшить скорость
    }

//Здесь формируются импульсы для STEP сигнала
  if (micros() - timing > speed_[i2] && (x >= 0 && x <= 100)){
    timing = micros();

    if(i2 != 0){
      if (State == LOW) {    //Изменить состояние переменной State
        State = HIGH;
      } else { State = LOW;
      }
       /*Задать соответствующее состояние на выходе для контакта STEP 
       согласно переменной State*/
      digitalWrite(STEP, State);
    }
  }
}

void read_I2C(int how_many) {
  int i=0;
  while (Wire.available()){ 
    byte c = Wire.read(); // Получить байт как символ, и поместить в переменную c
    if (i==0) x = ((c & 0xff) << 8);
      else x = x | c; i++;// Объединить полученные байты
  }
}

//Конец скетча




После загрузки скетчей в платы можно собирать все по этой схеме.

Схема подключения униполярного шагового двигателя к Arduino Nano через Digispark Attiny85

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



Команды для управления шаговыми двигателями по шине I2C.

1-100Команды для вращения
0Команда для плавной остановки
101Команда для резкой остановки
102Команда задать вращение вправо
103Команда задать вращение влево
110-120Команды для выбора ускорения

Подробное видео “Плавный пуск и остановка биполярного шагового двигателя. Спец драйвер на Digispark Attiny85”


Видео Плавный пуск и остановка биполярного шагового двигателя на Digispark Attiny85 и Arduino Nano