Управление сервоприводом при помощи ШИМ
В разработке робототехнических систем зачастую возникает необходимость в управлении сервоприводом при помощи микроконтроллера. И если с электрическим подключением драйвера сложностей обычно не возникает, то инициализация таймеров-счётчиков микроконтроллера для генерирования широтно-импульсно-модулированного меандра на выводах OCnA/OCnB/OCnC
нередко вызывает затруднения.
В данной статье я попробую осветить этот вопрос по возможности подробно.
Выбор режима и расчёт частоты ШИМ
С выбором режима в данном случае вопросов на самом деле нет, поскольку режим сброса таймера при совпадении CTC (Clear Timer on Compare match) предназначен специально для управления сервоприводами, мигания светодиодом и т.п. задач.
Соответственно при использовании библиотеки VE_AVR C++ Class Library или библиотеки VEduino инициализацию таймера-счётчика следует начинать со строки:
DEV_TIMER1.setWaveGenMode(TimerW::CTC_OCRA);
Возникает вопрос, какой таймер использовать -- один из 16-битных или 8-битный таймер-счётчик 2? Ответ зависит от того, какая частота ШИМ требуется. Расчёт можно произвести по формуле:
fШИМ = fclk/(2*prescaler*OCRA)
где:
- fclk -- тактовая частота микроконтроллера (например 16e6 Гц для Arduino)
- prescaler -- значение предделителя:
1, 8, 64, 256 или 1024 для таймера-счётчика 0 и 16-битных таймеров
1, 8, 32, 64, 128, 256 или 1024 для таймера-счётчика 2
- OCRA -- значение регистра OCRnA (8-битное для 8-разрядных таймеров, 16-битное для 16-разрядных)
Соответственно, несложно подсчитать минимальную и максимальную частоты ШИМ, которые можно получить с помощью данного счётчика.
Несложно вывести формулу расчёта значения OCRnA, исходя из желаемой частоты ШИМ:
OCRA = fclk/(2*prescaler*fШИМ)
Допустим, что желаемая частота ШИМ равна 67 Гц, частота тактирования 16 МГц. Получаем следующие результаты:
Посмотрим, с каким предделителем частота ШИМ будет наиболее близка к 67 Гц.
Итак, в случае 16-битного таймера нам вполне подойдёт предделитель /8
. Предделитель /1
был бы ещё точнее, но значение 119403 превышает максимально-возможное значение 65534 (при 65535 вывод OC будет постоянно включен), и поэтому самый точный результат, который нам доступен в данном случае - 67,0017 Гц.
В случае 8-битного таймера-счётчика 2 максимально-возможное значение равно 254, поэтому только с предделителем /1024
возможно получить частоту, близкую к 67 Гц -- 66,77 Гц.
Итак, таймер и предделитель выбраны, поэтому следующая строка инициализации будет:
DEV_TIMER1.setClockSelect(TimerW::Prescaler_8);
Режим управления выводом OCnA
В расчётной формуле несложно заметить двойку, но возникает вопрос, откуда эта двойка взялась и что она означает. Эта двойка есть ничто иное, как половина периода меандра, поскольку нам требуется, чтобы сигнал на выводе OCnA
переключался из 0 в 1 и назад с заданной частотой. Соответственно в данном случае мы его переключаем при совпадении, и таким образом следующей строкой инициализации будет:
DEV_TIMER1.setCompOutModeA(TimerW::Toggle);
Переключение пина в режим вывода
Поскольку пин OCnA
по умолчанию пребывает в режиме ввода, то чтобы генерируемый таймером-счётчиком меандр ШИМ выводился из микроконтроллера, пин следует переключить в режим вывода. Для этого мы добавляем в код инициализации строку:
setModeOutput(DEV_TIMER1_OCA);
Включение питания таймера
В некоторых микроконтроллерах ATmega таймер-счётчик 1 по умолчанию включен, в других он по умолчанию выключен, поэтому чтобы его использовать, необходимо предварительно подключить его питание, добавив в код инициализации строку:
DEV_POWER.timer1On();
Автор: Андрей Шаройко <vanyamboe@gmail.com>