Подключение униполярного шагового двигателя к микроконтроллерам AVR
Подробную теоретическую информацию о шаговых двигателях можно найти на просторах интернета, а здесь займемся практическим решением. Униполярный двигатель имеет одну обмотку в каждой фазе, от середины обмотки сделан отвод. Это позволяет изменять направление магнитного поля, создаваемого обмоткой, простым переключением половинок обмотки. При этом существенно упрощается схема драйвера. Драйвер должен иметь только 4 простых ключа. Средние выводы обмоток могут быть объединены внутри двигателя, поэтому такой двигатель может иметь 5 или 6 выводов. Иногда униполярные двигатели имеют раздельные 4 обмотки, по этой причине их ошибочно называют 4-х фазными двигателями. Каждая обмотка имеет отдельные выводы, поэтому всего выводов 8. Из-за простоты подключения и управления униполярного двигателя в этой статье рассмотрим именно этот тип шагового двигателя.
Для управления 6-выводным униполярным шаговым двигателем нужно 4 независимых управляющих элемента - транзистора VT1 - VT4. Транзисторы желательно использовать составные типа КТ829, КТ973 или импортные аналоги. Можно взять отдельные транзисторы, можно использовать специальную микросхему ULN2003A, которая содержит целых семь транзисторов, и кроме того, там есть еще 7 защитных диодов, которые пропускают через себя ток самоиндукции при отключении электромагнитов.
Управляющий контроллер Atmega8, тактируется от внутреннего генератора частотой 8МГц. В программе используем два внешних прерывания и прерывание по переполнению таймера Т0. Все прерывания определяем и настраиваем в главной функции, также настраиваем порты ввода/вывода микроконтроллера.
Для запуска двигателя в ту или иную сторону необходимо подать на его обмотки последовательность импульсов сдвинутых по фазе. Эти последовательности импульсов определим в массивах cw_dir[] и ccw_dir[], соответственно по часовой стрелке и против часовой стрелки. Указатель направления вращения status меняет свое состояние с лог.0 на лог.1 и наоборот при нажатии на одну из кнопок SB1 и SB2. Если status == 1 двигатель вращается против часовой, если status == 0 двигатель вращается по часовой стрелке. Переменная status меняет свое значение при наступлении внешних прерываний на входах INT0 и INT1. Чтобы происходило внешнее прерывание подтягиваем входы INT0 и INT1 через резисторы к плюсу питания.
Сигналы управления обмотками двигателя формируются на портах PB3 – PB0 программно. Формирование импульсных последовательностей выполняется в обработчике прерывания таймера 0. Переключение фаз происходит только при переполнении программного таймера. Переменная ovftimes определяет величину задержки между чередованиями импульсов. Ее значение связано со значением АЦП, чем больше значение АЦП тем медленнее вращается вал двигателя и наоборот. Регулировка скорости вращения осуществляется переменным резистором R8, средний вывод которого подключен к каналу ADC0. Ниже представлен код управляющей программы с подробными комментариями.
01.// Подключение униполярного шагового двигателя к AVR02.#include <avr/io.h>03.#include <util/delay.h>04.#include <avr/interrupt.h>05.06.// Полношаговый режим 2 фазы07.// Направление вращения по часовой стрелке08.unsignedcharcw_dir[4]=09.{10.0b00000001,11.0b00000010,12.0b00000100,13.0b0000100014.};15.16.// Направление вращения против часовой стрелки17.unsignedcharccw_dir[4]=18.{19.0b00001000,20.0b00000100,21.0b00000010,22.0b0000000123.};24.25.volatileunsignedcharstep_index;26.volatileunsignedintovftimes;27.volatileunsignedcharstatus;28.29.// Прерывание по переполнению Т030.ISR(TIMER0_OVF_vect)31.{32.staticunsignedintcount = 1;33.count++;34.if(count >= ovftimes)// Применяем задержку35.{36.cli();// Запрещаем прерывания37.38.if(status)// если status == 1 крутим против часовой39.PORTB = ccw_dir[step_index++];40.else// иначе крутим по часовой41.PORTB = cw_dir[step_index++];42.43.if(step_index >= 4)44.step_index=0;45.46.count = 0;// Сброс счетчика47.TCNT0 = 0;// Старт счетчика с нуля48.sei();// Глобально разрешаем прерывания49.}50.}51.52.// прерывание по вектору INT053.ISR(INT0_vect)54.{55.status = 0;// по часовой56.}57.58.// прерывание по вектору INT159.ISR(INT1_vect)60.{61.status = 1;// против часовой62.}63.64.intmain(void)65.{66.DDRB = 0b00001111;// PB0, PB1, PB2, PB3 - выходы67.PORTB = 0x00;// Лог. нули на выходе68.69.ADCSRA = (1 << ADEN)// разрешение АЦП70.| (1 << ADPS2)// предделитель на 64 (частота АЦП 125kHz)71.| (1 << ADPS1);72.ADMUX = 0x00;// ADC0 - вход, внешний ИОН 5 Вольт73.74.GICR |= (1 << INT1)|(1 << INT0);// Разрешаем внешние прерывания75.MCUCR |= (1 << ISC11)// Прерывание по заднему фронту INT176.|(1 << ISC01);// Прерывание по заднему фронту INT077.78.TCCR0 |= (1 << CS01);// Предделитель на 879.TCNT0 = 0;// Старт счетчика с нуля80.TIMSK |= (1 << TOIE0);// Разрешаем прерывания по переполнению Т081.82.step_index = 0;83.ovftimes = 10;// первоначальная задержка84.status = 0;// при включении вращение по часовой85.86.sei();// Глобально разрешаем прерывания87.88.while(1)89.{90.ADCSRA |= (1 << ADSC);// Начинаем преобразование91.while(ADCSRA & (1 << ADSC));// Ждем пока завершится преобразование92.ovftimes = ADCW;// Значение временной задержки93.}94.}

Источник: http://radioparty.ru/index.php/prog-avr/program-c/404-lesson-stepmotor