Управление шаговым двигателем с помощью AVR микроконтроллера ATmega8


Когда хочется чего-то более существенного чем просто помигать светодиодами, и когда усвоены основы работы с микроконтроллером можно переходить к более серьёзным проектам. Предлагаю научится управлять шаговым двигателем, той штукой, которая стоит во всех принтерах, копирах, дисководах, и многих других разнообразнейших устройствах. Шаговые двигатели делятся на два типа:
- униполярные шаговые двигатели,
- биполярные шаговые двигатели.

Отличатся немного по строению и по системе управления.
Униполярный шаговый двигатель, принципиальная схема показана на рис. 1
Униполярный шаговый двигатель
Рис. 1

У униполярного шагового двигателя есть 4-ре обмотки соединенные по схеме показанной на рис. 1
Принцип работы униполярного шагового двигателя следующий: поочередно на каждую из 4-х обмоток подается напряжение положительной полярности, в это время общий вывод соединен с отрицательным проводом питания. Получается за каждую коммутацию(подачу напряжения на одну из 4-х обмоток) ротор шагового двигателя смещается на один шаг, ширина этого шага зависит от конструкции самого шагового двигателя, для униполярного шагового двигателя показанного на рис. 2 и рис. 3 шаг составляет примерно:
22х8=176(шагов)
365/172=2,104 градуса.

Шаговый двигатель в сборе
рис. 2

Шаговый двигатель разобранный
рис. 3

Его я успешно выкурочил из древнего привода магнитных дисков размером 5,25 дюйма, кстати привод известной фирмы TEAC ))) Данный шаговый двигатель выполнял функцию перемещения магнитной головки по пазу в дискете, собственно через который и считывалась вся информация с магнитного диска.
Для управления этим шаговым двигателем при помощи микроконтроллера нам понадобится собрать силовой каскад, сам микроконтроллер просто сгорит, если подключить униполярный шаговый двигатель напрямую к его портам. В качестве силового каскада можно успешно применить 4 пары полевых транзистора из уже известной сборки IRF7105(схема показана на рис. 5),
выходной каскад на IRF7105
Рис. 5
или четыре мощных биполярных транзистора или если у вас есть лишние деньги, можно воспользоваться драйвером мощной нагрузки, таким как микросхема L293 или L293DNE что практически одно и то же. Я пользовался именно драйвером L293DNE.

Принципиальная схема включения шагового двигателя через драйвер L293DNE:
схема включения шагового двигателя на L293DNE

Алгоритм управления униполярным шаговым двигателем очень простой, необходимо выполнять поочередную коммутацию четырех обмоток двигателя. То есть выдавать на четыре бита порта микроконтроллера последовательность типа:
1000
0100
0010
0001

Соответственно крутим поочередно обмотки A, B, C, D:
1000 - обмотка A
0100 - обмотка B
0010 - обмотка C
0001 - обмотка D

Данный вид коммутации называется "полношаговым режимом", то есть за каждую коммутацию происходит смещение ротора шагового двигателя на один целый шаг. Так же существует "полушаговый режим", коммутация обмоток при полушаговом режиме следующая:
1000 - 1-е пол шага обмотки А
1100 - 2-е пол шага обмотки А
0100 - 1-е пол шага обмотки B
0110 - 2-е пол шага обмотки B
0010 - ..............
0011 - ..............
0001 - ..............
1001 - 2-е пол шага обмотки D

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

Программа подходит для любого микроконтроллера AVR Attiny2313, Atmega8, Atmega16.
Итак, вот и сама программа (программа для полношагового режима):

  1. #include <avr/io.h>//Подключаем библиотеку ввода/вывода
  2.  
  3. #define nop() {asm("nop");}//подключаем функция для формирваония задержки
  4.  
  5. void right (void);//Прототип функции поворота ротора ШД вправо
  6. void left (void);//Прототип поворота влево
  7.  
  8. int x, j, m=100; //переменные
  9.  
  10. //Функция задержки
  11. void delay(int t)
  12. {
  13. for (x=0; x<t ;x++)
  14. nop ();
  15.  
  16. }
  17.  
  18. //Функция длинной задержки
  19. void long_delay(int p)
  20. {
  21. for (j=0; j<p; j++)
  22. {
  23. delay(300);
  24. }
  25. }
  26.  
  27. //Функция поворота ротора вправо
  28. void right (void)
  29. {
  30. PORTD = 0b10001000;//обмотка A
  31. long_delay(m);
  32.  
  33. PORTD = 0b01000100;//обмотка B
  34. long_delay(m);
  35.  
  36. PORTD = 0b00100010;//обмотка C
  37. long_delay(m);
  38.  
  39. PORTD = 0b00010001;//обмотка D
  40. long_delay(m);
  41. }
  42.  
  43. //Функция поворота ротора влево
  44. void left(void)
  45. {
  46. PORTD = 0b00010001;
  47. long_delay(m);
  48.  
  49. PORTD = 0b00100010;
  50. long_delay(m);
  51.  
  52. PORTD = 0b01000100;
  53. long_delay(m);
  54.  
  55. PORTD = 0b10001000;
  56. long_delay(m);
  57. }
  58.  
  59. //Главная функция
  60. int main(void)
  61. {
  62. DDRD = 0xFF;//Конфигурирования порта на выход
  63. PORTD = 0x00;//Отключаем подтягивающие резисторы порта
  64.  
  65. while(1)//вечный цикл
  66. {
  67. left();
  68. .....//тут ставим столько раз функцию,
  69. .....//чтобы ротор шагового двигателя
  70. .....//провернулся на достаточный угол
  71. left();
  72.  
  73. right();
  74. .....//тут ставим столько раз функцию,
  75. .....//чтобы ротор шагового двигателя
  76. .....//провернулся на достаточный угол
  77. right();
  78. }
  79. }
  80.  
  81. Раде эксперимента, советую попробовать поставить следующий код в самом конце программы:
  82. m=m+1; //Добавить единицу к переменной
  83. if(m==350)//Если переменная достигла значения 350
  84. {m=1;}//установить переменную равную "1"
  85.  
  86. right();
  87. ///////////////////////////////////////////////
  88. m=m+1; //Добавить единицу к переменной
  89. if(m==350)//Если переменная достигла значения 350
  90. {m=1;}//установить переменную равную "1"
  91. ///////////////////////////////////////////////
  92. }
  93. }

Таким образом скорость вращения шагового двигателя будет замедлятся или ускорятся в зависимости от того, будут вы увеличивать (m=m+1;) или уменьшать (m=m-1;) время задержки между командами.

Хочу сказать что униполярные шаговые двигатели не очень мощные, то есть использовать их для перемещения предмета весом больше 40-80 грамм нет смысла, он просто не потянет. Тем более в полушаговом режиме. Для таких целей лучше всего применять шаговые двигатели из принтеров, те которые перемещают каретку с печатной головкой принтера.
Для экономичного управления униполярным шаговым двигателем необходимо отключать напряжение на обмотках во время простоя, то есть не давать обмотке шагового двигателя все время находится под напряжением, так как это приводит к нагреву самого шагового двигателя и соответственно к большой потере энергии (хотя конечно если преследуете цель обогрева помещения при помощи ШД тогда да :-) ). Максимальная скорость вращения ротора униполярного шагового двигателя не столь велика, её можно определить при помощи небольшого кусочка, который я разместил в самом низу программы. То есть для устройств требующих больших скоростей вращения униполярные шаговые двигатели не годятся.