Digitrode
цифровая электроника вычислительная техника встраиваемые системы
Как управлять двигателем постоянного тока с помощью микроконтроллера AVR ATmega
Двигатели постоянного тока являются наиболее широко используемыми электродвигателями. Эти моторы можно найти практически везде, от небольших проектов до продвинутой робототехники.
Сегодня мы научимся управлять двигателем постоянного тока с помощью микроконтроллера AVR Atmega16. Но прежде чем идти дальше, давайте узнаем больше о двигателе постоянного тока.
Двигатель постоянного тока – это устройство, которое преобразует электрическую энергию в механическую. В частности, двигатель постоянного тока использует постоянный ток для преобразования электрической энергии в механическую энергию. Основным принципом двигателя является взаимодействие между магнитным полем и током для создания силы внутри двигателя, которая помогает двигателю вращаться. Поэтому, когда электрический ток проходит через катушку в магнитном поле, генерируется магнитная сила, которая создает крутящий момент, приводящий к движению двигателя. Направление двигателя контролируется путем изменения направления тока. Также его скорость можно варьировать, изменяя подаваемое напряжение. Поскольку микроконтроллеры имеют выводы ШИМ, это можно использовать для управления скоростью двигателя.
В этом проекте работа двигателя постоянного тока будет продемонстрирована с помощью микроконтроллера Atmega16. Драйвер двигателя L293D будет использоваться для изменения направления тока и направления движения. Драйвер двигателя L293D использует конфигурацию цепи H-мост, которая выводит необходимый ток на двигатель. Две кнопки используются для выбора направления двигателя. Одна кнопка используется для выбора вращения по часовой стрелке, а другая – для выбора режима против часовой стрелки.
Схема подключения микроконтроллера ATmega, драйвера L293D и двигателя постоянного тока следующая.
Теперь перейдем к программированию микроконтроллера. В данном случае Atmega16 программировался с использованием USBASP и Atmel Studio7.0.
Двигатель постоянного тока подключается через драйвер двигателя L293D. Двигатель постоянного тока будет вращаться в двух направлениях при нажатии соответствующей кнопки. Одна кнопка будет использоваться для вращения двигателя постоянного тока в направлении по часовой стрелке, а другая кнопка будет использоваться для вращения двигателя постоянного тока в направлении против часовой стрелки. В данном случае у нас используются две библиотеки io.h и delay.h.
Полный код программы приводится далее, просто загрузите программу в Atmega16 и используйте две кнопки для вращения двигателя постоянного тока по часовой стрелке и против часовой стрелки.
При желании вы можете подключить контакты двигателя к любому контакту GPIO в зависимости от используемых GPIO. Также важно использовать драйвер двигателя для снижения нагрузки на микроконтроллер, так как микроконтроллеры не способны обеспечить необходимый ток для работы двигателей постоянного тока.
Управление двигателем постоянного тока
Приведенная здесь разработка была создана в целях демонстрации возможностей микроконтроллеров. Интересно было узнать, что можно сделать с маленькой микросхемкой имеющей всего 8 выводов.
Микросхема ATtiny13 является самой простейшей и самой дешевой из всего семейства 8 разрядных микроконтроллеров Atmel AVR. Тем не менее, в своем арсенале он имеет набор самых разнообразных современных периферийных устройств. В том числе два 8-разрядных таймера с возможностью работы в режиме источника сигнала с ШИМ (PWM). А так же 4 канальный 10-разрядный АЦП. Не смотря на то, что объем памяти у данной микросхемы не велик (1K памяти программ и всего 64 байта SRAM и 64 байта EEPROM), однако она прекрасно подходит для большинства задач требующих применения генератора ШИМ и АЦП. Если же для ваших задач потребуется больше памяти, вы можете легко заменить данную микросхему на другую из семейства AVR. Ниже приведена таблица, в которой перечислены микроконтроллеры, более мощные, но совместимые по всем выводам с микроконтроллером ATiny13.
Для того чтобы продемонстрировать возможности микроконтроллера ATtiny13, используя ШИМ и АЦП, я решил использовать его для управления скоростью двигателя. Я начал искать подходящий двигатель для этого проекта. В конце концов я решил, что для этого лучше всего подходит мотор-вентилятор от моего старого компьютера, используемый там для охлаждения Процессора. Я думаю, что это идеальный двигатель для данного проекта. Подключив его через ключевой каскад на транзисторе TIP120 к выходу OC0A микроконтроллера ATtiny13, мы могли бы легко управлять скоростью вентилятора, используя ШИМ. Ниже приводится полная схема для этого проекта:
Переменный резистор R4 (10K) используется в качестве источника управляющего напряжения, подаваемого на вход АЦП (вход ADC1 ATtiny13 — PIN 7). Для того, чтобы сделать схему интереснее я добавил переключатель (S1), которая служит для включения / выключения вентилятора и светодиодный индикатор (LED1), который своим миганием индицирует работу программы. Частота мигания светодиода соответствует изменениям сигнала ШИМ. Если вентилятор вращаться быстрее индикатор мигает медленно. Когда вентилятор вращаться медленнее частота мигания индикатора увеличивается. Скорость вращения вентилятора регулируется переменным резистором R4 который включен как делитель напряжения. Перемещая движок этого резистора можно изменять уровень напряжения на входе АЦП микроконтроллера.
Ниже приводится список радиоэлементов, оборудования и программ, которые я использовал в этом проекте:
- 4 резистора: 2,7К, 10K (2 шт), 300 Ом
- 1 переменный резистор: 10K
- 2 Конденсатора 100нФ, 1 конденсатор: 10нФ
- 1 диод: 1N4001
- 1 светодиод (любой маломощный)
- микроконтроллер ATtiny13
- транзистор: пара Дарлингтона TIP120
- Источник постоянного тока 12 Вольт
- Отладочная плата AVRJazz с микроконтроллером Tiny2313 на борту
- Программатор OvrOspII разработки Микки Хеннинга
- Atmel AVR Studio 4 для ввода, компиляции и отладки программы
Примечание переводчика: Вы можете применять любой программатор. А от отладочной платы можно и вовсе отказаться, так как программа уже отдажена.
Программа
При создании программы я решил использовать ассемблер вместо C, потому что я просто хотел убедиться, что максимально эффективно использую весь этот крошечный объем программной памяти в 1K. Ну и просто из любопытства, на сколько велик будет этот код; Ну да ладно, давайте разберем подробно текст программы, который вы можете видеть ниже:
Пояснения к программе
Первая группа операций программы (см. текст программы выше) производит установку вершины стека. Стек использует память SRAM микроконтроллера. Мы устанавливаем указатель стека на конец этой памяти (память имеет 64 байта). Системная переменная RAMEND всегда содержит адрес последней ячейки памяти. То есть в нашем случае RAMEND = 64
Следующая группа операций устанавливает режим работы порта PORTB. Режимы каждой линии порта устанавливаются так, как показано в следующей таблице:
Инициализация Аналого-цифрового преобразователя
Следующая группа команд выполняет инициализацию встроенного АЦП микроконтроллера ATtiny13 (подробнее смотрите в фирменном описании микросхемы). Для того, что бы контроллер смог использовать свой встроенный АЦП мы должны выполнить следующие шаги:
A. Выбрать коэффициент предварительного деления и активировать АЦП
Предварительный делитель используется для деления тактовой частоты (внутренего или внешнего тактового генератора). Тактовая частота используется в схеме последовательных приближений АЦП для преобразования аналогового сигнала. Чтобы получить максимальное разрешение нужно выбирать частоту в пределах от 50 кГц до 200 кГц. В данной конструкции я использую деление на 64, поэтому тактовая частота будет составлять примерно 150 кГц (9600000 Гц / 64).
Благодаря тому, что мы не используем автозапуск преобразования (ADATE) и прерывание от АЦП (ADIF и ADIE), то мы можем установить эти биты таким образом чтобы, установить коэффициент деления 64 (ADPS2, ADPS1 и ADPS0) и включить АЦП (ADEN). Запись значения в регистр состояния АЦП производится следующим образом:
B. Выбрать источник запуска процесса преобразования АЦП
Мы будем использовать автономный режим запуска, значит, встроенный АЦП будет сам периодически запускать процесс преобразования, как только мы программно разрешим выполнять этот процесс:
Таким образом, записав во все три бита управления режимами запуска АЦП (ADTS2, ADT21 и ADTS0) уровень логического нуля, мы переводим АЦП в автономный режим работы:
C. Выбор канала АЦП
Мы должны указать, какой из каналов АЦП мы будем использовать, выбрав значения битов управления мультиплексором АЦП (MUX1 и MUX0) в регистре управления мультиплексором (ADMUX):
Из таблицы видно, что для того, что бы выбрать канал ADC1 (PB2), используемый в данном проекте необходимо присвоить биту MUX1 = 0 и биту MUX0 = 1. Далее мы выберем значение внутреннего опорного напряжения равным 1,1 вольт, записав в соответствующий бит (REFS0) значение логической «1»:
Когда встроенный АЦП закончит процесс преобразования, результат измерения запишется в пару регистров ADCH и ADCL. Однако в этом проекте мы используем 8-разрядное значение. Поэтому мы выбираем режим сдвига влево результата измерения. Для этого мы устанавливаем бит ADLAR в регистре ADMUX в единицу и будем читать результат только из реестра ADCH (младшие биты в регистре ADCL мы просто игнорируем).
D. Отключение функции цифрового входа для аналогового канала
И последнее, что необходимо выполнить для завершения процесса инициализации АЦП, это отключение для канала (ADC1) функции цифрового входа. Каждый разряд порта ввода-вывода в обычном режиме работает как вход для цифрового сигнала. Если данный вывод микросхемы мы используем как вход АЦП, то рекомендуется отключить функцию цифрового входа. Это позволяет уменьшить ток потребления и увеличить точность преобразования.
Записав в бит ADC1D значение логической «1», мы отключаем функцию цифрового входа для линии порта PB2:
Инициализация режима широтно-импульсной модуляции
Микроконтроллер ATtiny13 имеет два независимых канала ШИМ. Выход канала, который мы используем в этом проекте, называется OC0A (выходит на PB0). А другой канал называется OC0B (выходит на PB1). Для включения встроенного ШИМ микроконтроллера ATtiny13 мы используем следующие шаги:
A. Выбор режима генерации сигнала
Микроконтроллер ATtiny13 поддерживает режима ШИМ. Первый из них называется «Fast PWM» (быстрый ШИМ). Он обеспечивает самую высокую частоту выходного сигнала. Второй режим называется «Phase correct PWM» (ШИМ с корректной фазой). Этот режим обеспечивает симметричное изменение, как переднего, так и заднего фронтов выходного сигнала. Этот режим работает на более низких частотах по сравнению с «Fast PWM». В рамках этого проекта мы будем использовать «Fast PWM».
Установив COM0A1 = 1 и COM0A0 = 0, мы выбираем режим сброса OC0A при совпадении, и установки OC0A при достижении конца. Это означает, что в тот момент, когда значение счетного регистра TCNT0 таймера окажется равным значению регистра OCR0A, выход OC0A (PB0) будет сброшен в «0». Когда же таймер досчитает до своего максимального значения (TCNT0 = 255), на выходе OC0A установится логическая «1». Изменяя значение OC0A, можно менять ширину выходного импульса. Режим «Fast PWM» можно выбрать, установив в регистре TCCR0B бит WGM2 = 0, а в регистре TCCR0A биты WGM1 = 1 и WGM2 = 1.
B. Выбор тактовой частоты на входе таймера
Сердце встроенного ШИМ — 8-разрядный таймер/счетчик. Для формирования выходного сигнала существует специальная схема сравнения. она непрерывно сравнивает значение счетного регистра таймера TCNT0 со значением регистра OCR0A и использует результат сравнения для формирования выходного сигнала. Для того чтобы вся эта схема заработала, мы должны подать на вход таймера тактовый сигнал. В качестве тактового сигнала выбирается один из выходов со специального встроенного делителя тактовой частоты. Для выбора одного из этих сигналов служит специальный регистр TCCR0B:
В этом проекте я использую сигнал с выхода делителя с коэффициентом деления 256. Частоту выходного сигнала для режима Fast PWM можно рассчитать по следующей формуле:
Учитывая, что N — это коэффициент предварительного деления, при тактовой частоте внутреннего генератора 9,6 МГц выходная частота на OC0A будет равна
fOC0A=9600000 / (256 x 256) = 146.48 Hz
Вы должны поэкспериментировать и выбрать для себя самый подходящий коэффициент деления предварительного делителя, в зависимости от типа двигателя постоянного тока который вы используете. Попробуйте начать с большого коэффициента предварительного деления и постепенно уменьшать его наблюдая, как ведет себя двигатель. При этом необходимо контролировать, что бы биты FOC0A и FOC0B в регистре TCCR0B были установлены в «0» в режиме ШИМ.
Описание алгоритма
Работу программы я довольно подробно уже объяснил (думаю, что в самой программе достаточно комментариев). Однако мне хотелось бы пояснить работу всего алгоритма используя псевдокод в стиле языка C. Надеюсь, что это позволит лучше понять все детали. И так, вот этот псевдокод:
В тексте псевдокода можно увидеть бесконечный цикл for(;;), аналог которого на ассемблере выглядит следующим образом:
Внутри этого бесконечного цикла мы производим чтение положения переключателя, включаем и выключаем ШИМ, производим АЦП преобразование, включаем и выключаем индикатор.
При установке бита ADSC регистра ADCSRA в единицу мы конфигурируем встроенное АЦП микросхемы ATtiny13 для чтения канала (PB2) и начала процесса преобразования. Далее мы должны просто подождать, пока этот бит будет очищен. Это произойдет в тот момент, когда процесс преобразования будет закончен.
Как я уже объяснял ранее, я использую светодиодный индикатор, как индикатор правильной работы программы. Но для того, чтобы сделать эту индикацию более интересной, я использую выходное значение АЦП в качестве коэффициента задержки для мерцания светодиода. Это делает задержку переменной и зависящей от положения движка переменного резистора.
Если значение ADCH увеличивается, ширина выходного импульса на выходе OC0A (PB0) будет шире. Это приведет к тому, что скорость вращения двигателя постоянного тока станет быстрее. При этом время задержки мерцания светодиода будет больше. Если же значение ADCH уменьшается, то это означает, что длительность выходного импульса сигнала ШИМ уменьшается, и двигатель постоянного тока будет вращаться медленнее, а значение задержки мигания индикатора уменьшится. Вы можете изменить алгоритм регулировки, изменяя значение битов COM0A1 и COM0A0 в регистре TCCR0A. Это приведет к инвертированию сигнала ШИМ на выходе OC0A.
Загрузка и запуск кода
После компиляции и отладки (вы всегда должны пройти через эту процедуру) вы должны получить такой результат:
Собственно кодом занято около 128 байт из общего (1024 байт) объема программной памяти. Этот очень хороший результат, так как остается еще место на усовершенствование программы на будущее. Как вы видите 1K программной памяти микроконтроллера ATtiny13 вполне достаточно для несложного устройства использующего ШИМ и АЦП. Теперь можно прошивать код в микроконтроллер. Но прежде чем сделать это необходимо проверить микросхему ATtiny13 правильно ли установлены биты защиты и другие FUSE переключатели. Для правильной работы описываемого устройства в программе OvrOspII биты FUSE переключателей должны быть установлены следующим образом:
Убедитесь, что вы выбрали режим синхронизации от внутреннего RC генератора, частота 9.6МГц; время запуска: 14 CK + 64ms. Если все выставлено правильно, вы можете прошивать программу микроконтроллер.
Ниже вы можете посмотреть видеоролик, где показана работа описанного выше устройства.
Примечание: когда вентилятор крутится медленнее, индикатор мигает быстрее. И наоборот, когда вентилятор крутится быстрее, светодиод мигает медленнее. Однако на видео вращение вентилятора искажается. Вентилятор ускоряется, а кажется, что он вращается медленнее. Это происходит от того, что частота вращения вентилятора близка и даже превышает частоту кадров при съемке.