Контроллер шагового двигателя на микроконтроллере. Реферат
![]()
|
Разработка схемы велась в программе Altium v13. Эта программа предоставляет широкие возможности для разработчика, кроме функционала, предназначенного непосредственно для разработки схем, обладает мощными средствами для визуализации, позволяет подготовить готовую плату к размещению на производстве. Блок управления шаговым двигателем состоит из драйвера и пассивных компонентов. Полученная принципиальная схема представлена на рисунке 15. Рис.15. Блок управления шаговым двигателем Микросхема DRV8834 является универсальным драйвером для электрических двигателей, позволяет управлять как двигателями постоянного тока, так и 30 шаговыми двигателями. В ходе разработки данного блока и изучения документации сначала был выбран наиболее подходящий режим работы драйвера, который позволяет реализовать поставленную задачу. В последствии была представлена схема для выбранного режима работы. Связи элементов и цепей этого функционального блока со всеми остальными обозначены с помощью функции NetLabel программы Altium, что позволяет значительно упростить схему. Данная схемотехническая реализация позволяет использовать DRV8834 в режиме счетчика. У микросхемы есть два состояния – спящее и активное. Определяются они логическим уровнем на выводе nSLEEP, соответствующем 1 pin , высокий логический уровень – микросхема в активном статусе, низкий – в спящем. Ток через обмотки шагового двигателя регулируется с помощью напряжения на выводах AVREF и BVREF, которое на данной схеме задается посредством вывода VREF, а также токоограничивающих резисторов на выводах AISEN и BISEN. Формула расчета максимального тока на обмотке : ∗ (1) Для того, чтобы драйвер работал в режиме счетчика, следует подать высокий логический уровень на вывод CONFIG, соответствующий 15 pin. Логический уровень сигнала на выводе 10 pin nENBL/AENBL, задает активное/неактивное состояние выводов обмоток шагового двигателя AOUT и BOUT. В случае режима счетчика для активного состояния следует подать логический 0 на вывод nENBL/AENBL. В режиме счетчика шаг двигателя будет осуществляться по нарастающему фронту сигнала на выводе 11 pin STEP/BENBL. Направление вращения ротора задается с помощью сигнала на выводе 12 pin DIR/BPHASE. Уровень 31 дробления шага, то есть количество микрошагов, задается посредством нескольких комбинаций логических уровней на выводах 13 pin M0/APHASE и 14 pin M1. Предусмотрена функция отчета об ошибках, которая реализована с помощью вывода nFAULT 16 pin . В случае превышения безопасных температурных режимов, перегрузки по току или просадки по напряжению на выводе nFAULT должен возникать низкий логический уровень. С помощью вывода 20 pin VINT может обеспечиваться высокий логический уровень на других выводах, но в данной схеме не используется. Питание двигателя и микросхемы осуществляется от общего источника питания 5 В через выводы 17 pin VCP, 18,19 pin VM. 32 Подключение самого двигателя осуществлялось с помощью 4-pin разъема JST. Схема подключения выводов обмоток приведена на рисунке 16, расположенном ниже. Рис. 16. Схема подключения шагового двигателя Обмотки шагового двигателя условно разделены на обмотку A, имеющую два вывода AOUT1 и AOUT2, и обмотку B, имеющую также 2 вывода BOUT1 и BOUT2. 33 Подключение программатора к плате будет происходить через 8-pin разъем PLD-80-PGM, при этом одна ножка остается незадействованной. Схема подключения показана на рисунке 17. Рис.17. Разъем для программатора 34 Управление платой будет организовано через интерфейс RS-232 с помощью микросхемы SP232EEN-L. Связь с компьютером может быть организована посредством COM-порта. Схема подключения интерфейса представлена на рисунке 18. Рис. 18. Интерфейс RS-232 для управления работой платы 35 Соединение непосредственно с COM-портом компьютера осуществляется с помощью разъема JST 3-pin по схеме, показанной на рисунке 19. Рис. 19. Схема соединения COM-порта с платой 36 Контроль за работой платы будет осуществляться с помощью 8-битного микроконтроллера ATMega 8. Микроконтроллер выполнен на основе AVR RISC архитектуры, изготовлен по кмоп-технологии. ATMega обладает следующими возможностями: - Встроенная программируемая flash память объемом 8кбайт с возможностью одновременного чтения/записи - 512 байт EEPROM - 1 кбайт SRAM - 23 линии ввода/вывода общего назначения - 32 регистра общего назначения - 3 гибких таймера/счетчика с режимами сравнения - Внутренние и внешние прерывания - Поддержка USART - 6 канальный ADC (8-канальный для TQFP и QFN/MLF корпусов) с 10- битной точностью - Низкое энергопотребление - Производительность порядка 1MIPS(million instructions per second) на 1 Mhz - Максимальная рабочая частота 16 Mhz 37 Схема подключения микроконтроллера показана на рисунке 20. Рис. 20. Схема подключения микроконтроллера Питание микроконтроллера осуществляется от общего источника питания с напряжением 5 В. Подключение ножек микроконтроллера к остальным элементам схемы показано с помощью функции NetLabel в программе Altium. Выбор порта для каждого конкретного элемента схемы продиктован соображениями оптимизации дизайна печатной платы, за исключением зарезервированных ранее линий на системном уровне. 38 Для индикации работы платы используется сд, подключенный по схеме, показанной на рисунке 21. Рис. 21. Схема подключения светодиода Кварцевый резонатор ECS-73-18-4XEN подключается таким образом, как показано на рисунке 22. Рис. 22. Схема подключения кварцевого резонатора 39 Питание от общего источника к плате подводится через разъем JST 2-pin по схеме, изображенной на рисунке 23. Рис. 23. Схема подключения питания к плате 40 2.5. Разводка печатной платы Разводка печатной платы выполнялась в программном комплексе Altium. Плата имеет двухслойный дизайн. Разводка верхнего слоя представлена на рисунке 24. Рис. 24. Разводка верхнего слоя печатной платы в Altium Двухслойный дизайн позволяет значительно сократить размеры ПП. Размеры ПП составляют 60х35мм. 41 Разводка нижнего слоя представлена далее на рисунке 25. Рис. 25. Разводка нижнего слоя печатной платы в Altium Земля на плате соединяется с помощью переходных отверстий. В случае разводки ПП в одном слое ее размеры выросли бы очень значительно, а разводка была бы далека от оптимальной. 42 С помощью Altium можно получить 3-d макет печатной платы. Он изображен на рисунке 26. Рис. 26. Макет печатной платы в 3-d 43 3. Разработка программного кода для устройства 3.1 Описание разработанного программного кода Разработанный программный код представляет собой проект, выполненный в компиляторе IAR. Проект состоит из файлов с расширением « .c », в которых содержится основной программный код, и файлов с расширением « .h », которые являются заголовочными файлами. В данном проекте присутствуют следующие файлы: 1) Файл step_motor_main является главным файлом проекта, в котором осуществляется соединение всех составляющих программного кода и их последующее объединение в единую программу. 2) Файлы DRV8834.c и DRV8834.h – в данных файлах содержится код для конфигурирования портов микроконтроллера ATMega 8. 3) Файлы timer1.c и timer1.h - в этих файлах содержится программный код, который отвечает за использование возможностей таймера, встроенного в микроконтроллер. 4) Файлы uart0c и uart0.h служат для осуществления обмена данными с микроконтроллером через интерфейс RS-232. Целесообразно подробно описать все составляющие по отдельности. Для более наглядного описания следует начать с файлов, отвечающих за конкретный функционал, а после этого, показать, как эти файлы объединяются в общий программный код в главном файле проекта. 44 Следует начать с описания программного кода в файлах DRV8834.c и DRV8834.h. Программный код DRV8834.c приведен ниже: #include "DRV8834.h" void DRV8834_init() { //_SEI(); //Включение прерываний DDRB&=(1< PORTB&=(1< /*if (PINB0!=1) Статус nfault DRV8834 потом написать { }*/ DDRB|=(1< DDRC|=(1< 45 //PORTC&=(1< PORTC&=(1< //PORTC|=(1< документацией PORTC|=(1< DDRC|=(1< PORTC&=(1< DDRD|=(1< В данном файле осуществлена конфигурация портов, которые требуются для управления драйвером шагового двигателя DRV8834. В файле DRV8834.h содержится следующее: #ifndef _DRV8834_H_ #define _DRV8834_H_ #include "../config.h" void DRV8834_init(); #endif 46 В данном заголовочном файле объявляется основная функция инициализации DRV8834_init() и подключается файл с системными обозначениями config.h . Перейдем к описанию файлов timer1.c и timer1.h. В файле timer1.c описан основной функционал, связанный с работой встроенного таймера. Программный код представлен далее: #include "config.h" #include "timer1.h" static unsigned short tcnt1_val; short impulscount=0; short impuls_quantityHigh=60; short impuls_quantityLow=120; short impuls_quantity_rule=60; short start_permission=1; short logiclev=0; short logiclevD5=0; short step_quantity=0; short rotate_mode=0; //short end_rotate=0; short step_lev2=0;//нужна для режима фиксированных шагов 47 В приведенном выше участке кода описаны основные переменные, используемые в программе. void timer1_init(void) { //Процессор: ATMega8 //Частота процессора = 7.373 МГц // Таймер1 - настройка // Период = 100мкс // Предделитель = 1 // 1 такт процессора = 135.634нс // Требуемое количество тактов = 737.28 // Действительное число тиков = 737 // Действительный период = 99.962мкс // Отклонение периода = -0.037978% // Частота = 10.004 кГц //Разрешение прерывания TIMSK |= (1 << TOIE1); // TCCR1A: // выход A: выход отключен; COM1A = 0x0 // выход B: выход отключен; COM1B = 0x0 // регистр в исходном состоянии // TCCR1B: 48 // набор бит предделителя: коэффициент деления 1; CS1 = 0x1 TCCR1B |= (1 << CS10); //Установка периода = 50.049мкс TCNT1 = tcnt1_val = 0xfe8f; DDRC|=(1< Функция timer1_init используется для первоначального конфигурирования таймера, разрешаются прерывания, устанавливается период таймера. void tcnt_set(short waitspeed) { impuls_quantityHigh = 100; //impuls_quantityLow = (waitspeed*3); //impuls_quantityLow = 10000; impuls_quantityLow=waitspeed; if (impuls_quantity_rule!=impuls_quantityHigh) //Таким образом обнуляем импульс при каждом //изменении уровня { impulscount=0; impuls_quantity_rule=impuls_quantityHigh; } 49 } В приведенной выше функции tcnt_set устанавливается длина импульса и ширина паузы, подаваемые на 3-й бит порта C. Следующая функция служит для запуска двигателя, контроля статуса вращения, распознавания требуемого угла поворота. void start_control(short check_start, short angle_lev1, short rotate_status_lev) //Третий аргумент нужен для распознавания режима, //и чтобы не конфликтовало с angle_check() { if ((check_start==0)&&(angle_lev1==0)&&(rotate_status_lev==0)) { start_permission=0; if (PINC3==0) {logiclev=0;} if (PINC3==1) {logiclev=1;} impulscount=0; // end_rotate=0; step_quantity=0; 50 } if ((check_start==1)&&(angle_lev1==0)&&(rotate_status_lev==0)) { start_permission=1; // end_rotate=0; step_quantity=0; } } В приведенной выше функции start_control происходит определение режима вращения. Если угол вращения не задан, то есть требуется непрерывное движение ротора шагового двигателя, то дается разрешение на запуск. Если подана управляющая команда, задающая режим с заданным углом, то данная функция будет выполняться как пустая, и происходит переход к следующей функции, отвечающей за обработку вращения в режиме фиксированного угла. Эта функция приведена далее. void angle_check(short angle_lev2) { if (angle_lev2!=0) { step_lev2=angle_lev2; } if ((step_lev2!=0)&&(step_quantity 51 start_permission=1; rotate_mode=1; } if ((step_lev2!=0)&&(step_quantity==step_lev2)) { step_lev2=0; start_permission=0; step_quantity=0; rotate_mode=0; //end_rotate=1; } } В описанной выше функции angle_check происходит определение значения заданного угла. Если значение угла не задано, то есть равно нулю, то функция выполняется как пустая, а параметры вращения определяются в ходе работы предыдущей функции. Также в этой функции происходит контроль за ходом вращения. В тот момент, когда двигатель прошагает на заданный угол, функция снимет разрешение на запуск двигателя. Важное значение имеют прерывания по таймеру. С помощью данных прерываний по таймеру происходит регулировка времени импульсов и пауз, отвечающих за скорость вращения двигателя. Содержимое обработчика прерываний представлено далее. 52 #pragma vector = TIMER1_OVF_vect __interrupt void int_OVF1(void) { TCNT1 = tcnt1_val; if (logiclevD5==0) { PORTD|=(1< logiclevD5=1; } if (logiclevD5==1) { PORTD&=(1< logiclevD5=0; } if ((impulscount //PORTC&=(1< impulscount=(impulscount+1); } 53 if ((impulscount //PORTC&=(1< impulscount=(impulscount+1); } /* if ((impulscount==impuls_quantity)&&(logiclev==0)&&(start_permission==1)&&(r otate_mode==1)&&(end_rotate!=1)) { step_quantity=step_quantity+1; }*/ if ((impulscount==impuls_quantityLow)&&(logiclev==0)&&(start_permission==1)/ *&&(rotate_mode==0)*/) { impulscount=0; logiclev=1; PORTC|=(1< } if ((impulscount==impuls_quantityHigh)&&(logiclev==1)&&(start_permission==1)/ *&&(rotate_mode==0)*/) { 54 impulscount=0; logiclev=0; PORTC&=(1< if (rotate_mode==1) { step_quantity=step_quantity+1; } } /* if ((impulscount==impuls_quantityLow)&&(logiclev==0)&&(start_permission==1) &&(rotate_mode==1)&&(end_rotate!=1)) { impulscount=0; logiclev=1; PORTC|=(1< } if ((impulscount==impuls_quantityHigh)&&(logiclev==1)&&(start_permission==1) &&(rotate_mode==1)&&(end_rotate!=1)) { impulscount=0; logiclev=0; PORTC&=(1< 55 step_quantity++; } */ } В приведенном коде происходит подсчет количества прерываний по таймеру. Когда произошло заданное в предыдущих функциях количество прерываний, происходит смена логического уровня на 3-бите порта C. В этом месте заканчивается программный код timer1.c. Перейдем к описанию содержимого файла timer1.h. Оно представлено далее. #ifndef _TIMER_1_H_ #define _TIMER_1_H_ void timer1_init(void); void tcnt_set(short waitspeed); //void start_control(char check_start); void start_control(short check_start, short angle_lev1, short rotate_status_lev); void angle_check(short angle_lev2); #endif В данном файле описаны основные функции, необходимые для работоспособности кода, отвечающего за таймер. 56 Теперь целесообразно привести код из файлов uart0.c и uart0.h, необходимых для организации управления через интерфейс RS-232. Начать следует с файла uart0.c, его содержимое приведено ниже. #include "../config.h" #include "uart0.h" short speed=0; short start=1; short stop=0; short angle_set_mark=0; short angle_mark=0; //char angle_step_check=0; char speedswitch=0; char destination=0; char movement=0; char activecommand=1;//чтобы сначала обрабатывалась комманда, а потом было прерывание short setspeed=120; short idle_wait=0; short button_check=2; 57 short rotate_status_mark=0;//чтобы было видно, какой режим шага, бесконечный или фиксированный char rx_length = 5; //длина команды char rx_counter = 7; //счетчик байтов char rx_buf[10] = {0x6F, 0x6B, 0,0,0,0,0,0,0,0};//массив для считывания char rx_end_flag = 0;//флаг по завершению приема //char tx_start_flag = 0; char tx_ident = 0; char output_ident = 0;//порядок вывода чисел по прерыванию //unsigned short setspeed=0xffdb; Представленный выше отрывок кода служит для объявления используемых переменных. Далее расположен участок кода, отвечающего за обработку команды пользователя. void commandprocess (void) { if (rx_end_flag==1) { speedswitch=rx_buf[3]; destination=rx_buf[4]; 58 movement=rx_buf[5]; switch(speedswitch) { case 0x31: //speed = 5000; speed = 1; break; case 0x32: speed = 100; break; case 0x33: speed = 100; break; case 0x34: speed = 250; break; case 0x35: speed = 500; 59 break; default: break; } switch(destination) { case 0x71: PORTC|=(1< break; case 0x65: PORTC&=(1< break; default: break; } switch(movement) 60 { case 0x73: { //PORTB&=(1< stop=1; start=0; button_check=1; angle_mark=0; rotate_status_mark=0; } break; case 0x64: { //PORTB|=(1< start=1; stop=0; button_check=1; angle_mark=0; rotate_status_mark=0; } break; 61 case 0x7A: { //PORTB|=(1< start=1; stop=0; button_check=0; angle_mark=20; rotate_status_mark=1; } break; case 0x78: { //PORTB|=(1< start=1; stop=0; button_check=0; angle_mark=1; rotate_status_mark=1; } break; default: break; 62 } activecommand=2; } } В приведенном выше участке кода происходит обработка команды пользователя. Команда пользователя состоит из пакета байтов – в данном конкретном случае предусмотрена обработка 3 байт команды. Далее приведена функция, служащая для обработки приема команды. void transmitwait(void) { if ((rx_end_flag==1)&&(activecommand==2)) { // tx_start_flag=1; activecommand=1; rx_end_flag=0; tx_ident = 0; UDR=rx_buf[tx_ident++]; UCSRB |= (1 << UDRIE); // tx_ident=tx_ident+1; } } 63 Функция transmitwait ожидает конца приема данных с терминала изапускает процесс передачи ответа – отчета о получении. Следующий фрагмент кода отвечает за обработку полученного значения скорости. short findspeed(void) { if (speed!=0) { setspeed = speed; speed=0; } return(setspeed); } Далее приведена функция stopwait, которая отвечает за то, двигается ли двигатель, или стоит. short stopwait(void) { if (stop==1) { idle_wait=0; } 64 if (start==1) { idle_wait=1; } return(idle_wait); } Следующая функция отвечает за статус вращения – с заданным углом и без него. short rotate_status(void) { if (rotate_status_mark==1) { return(1); } else { return(0); } } Функция angleset проверяет значение заданного угла. short angleset(void) { 65 if(angle_mark==0) { angle_set_mark=0; } if ((angle_mark!=0)&&(button_check==0)) { angle_set_mark=angle_mark; angle_mark=0; } if (button_check==1) { angle_set_mark=0; } /* if ((button_check==0)&&(idle_wait==1)) { stop=1; start=0; button_check=1; angle_mark=0; } */ 66 return(angle_set_mark); } Далее приведен участок кода, отвечающий за настройку интерфейса. void uart0_init(void) { //Процессор: ATMega8 //Частота процессора = 7.373 МГц // UCSRA: // Удвоенная скорость - вкл. UCSRA |= (1 << U2X); // UCSRB: // Передача - вкл. // Прерывание Tx - выкл. // Прерывание UDR - вкл. // Приём - вкл. // Прерывание Rx - вкл. // 8ой бит - выкл. UCSRB |= (1 << TXEN)/*|(1 << UDRIE)*/|(1 << RXEN)|(1 << RXCIE); 67 // Настройка скорости передачи // заданная скорость передачи = 9600 // заданное значение UBRR = 95 (0x5f) // действительное значение UBRR = 95 (0x5f) // действительная скорость передачи = 9600 бит/с // длительность одного бита = 104.167мкс // Отклонение скорости передачи = 0% UBRRL = 0x5f; // UCSRC: // Чётность - off // Двойной стоп бит - выкл. // К-во бит данных - 8 // регистр в исходном состоянии //DDRC|=(1< В описанном выше участке кода происходит настройка интерфейса uart с помощью встроенных регистров. 68 В следующем далее участке кода описан обработчик прерывания по завершению приема данных с терминала. #pragma vector = USART_RXC_vect//Прерывание по завершению приема __interrupt void int_RXC(void) { char cmd = UDR; //получение данных char data=cmd; // // char cmd_check=(cmd&0x80); if ((cmd/*_check*/&0x80)/*&&(tx_start_flag!=1)*/) rx_counter = 2; if (rx_counter<=rx_length+2) rx_buf[rx_counter++]=data; // rx_counter++; if (rx_counter==rx_length+2) { rx_end_flag=1; } } 69 Описанное выше прерывание срабатывает после того, как будет принят 1-ый байт, и срабатывает до тех пор, пока последовательно не будут приняты все оставшиеся байты команды. Далее приведен участок кода, отвечающий за прерывание, срабатывающие по завершению передачи ответного байта на терминал. #pragma vector=USART_UDRE_vect //Прерывание по очистке UDE __interrupt void ext_udre(void) { //if (tx_start_flag==1) // { UDR=rx_buf[tx_ident++]; // tx_ident=tx_ident+1; // } if (tx_ident==7) { //tx_start_flag=0; tx_ident=0; UCSRB &= ((1 << UDRIE)); } } После того, как будет передан последний ответный байт, прерывание снова запрещается. 70 Данная часть кода являются завершающей для файла uart0.c. В заголовочном файле uart0.h содержится следующее: #ifndef _UART_0_H_ #define _UART_0_H_ short findspeed(void); void uart0_init(void); short stopwait(void); short angleset(void); void transmitwait(void); void commandprocess (void); short rotate_status(void); #endif Участок кода, приведенный выше, содержит описание функций, используемых в программе. После того, как было описано содержимое всех дополнительных файлов проекта, следует перейти к описанию основного файла проекта step_motor_main.c, в котором происходит объединение всех составляющих кода в единую программу. 71 #include "config.h" #include "hardware.h" #include "timer1.h" #include "PC_Communication/uart0.h" #include "DRV8834/DRV8834.h" //#define F_CPU 7372800UL __C_task void main(void) { //Процессор: ATMega8 //Частота процессора = 7.373 МГц //Секция инициализации // ------------ Разместите свой код ниже ------------ Test_LED_output(); Test_LED_hi(); uart0_init(); DRV8834_init(); 72 timer1_init(); _SEI(); // -------------------------------------------------- while(1) { commandprocess(); tcnt_set(findspeed()); angle_check(angleset()); start_control(stopwait(), angleset(), rotate_status() ); // angle_check(angleset()); transmitwait(); } } В приведенном выше участке кода происходит запуск всех функций инициализации: - uart0_init() - DRV8834_init() - timer1_init() Задано общее разрешение прерываний с помощью _SEI(). В вечном цикле while(1) происходит выполнение всех функций, которые использовались во вспомогательных файлах проекта. Описание проекта программного кода в компиляторе IAR завершено. |