====== Серводвигатель ====== //Необходимые знания: [HW] [[et:hardware:homelab:motor]], [HW] [[et:hardware:homelab:sensor]], [AVR] [[et:avr:io]], [AVR] [[et:avr:timers]], [LIB] [[et:software:homelab:library:module:motor]], [LIB] [[et:software:homelab:library:adc]]// ===== Теория ===== [{{ :examples:motor:servo:motor_servomotor.jpg?220|RC серводвигатель}}] [{{ :examples:motor:servo:motor_servo_signal_position.png?220|Взаимосвязь между шириной сигнала PWM и положением рычага находящегося на валу.}}] RC (сокращение, на английском языке //radio-controlled//) серводвигатель - широко распространенный в моделизме и роботике исполнительный механизм, который состоит из маленького двигателя постоянного тока, зубчатого редуктора и управляющей логики. Ротор серводвигателя, как правило, двигается в какое-то определенное положение и пытается это положение постоянно удерживать. Положение ротора зависит от управляющего сигнала, переданного серводвигателю. В зависимости от типа двигателя, максимальный угол поворота может быть разным. Реже встречаются серводвигатели с постоянным вращением. В таком случае управляющий сигнал определяет не положение ротора, а скорость вращения. Распространена так же практика, когда серводвигатель, который определяет положение, переделывают в постоянно вращающийся. По существу, это означает, что дающий из положения ротора обратную связь потенциометр заменяется на два фиксированных резистора и от зубчатого колеса удаляется ограничивающий полное вращение механизм. Один из важных признаков серводвигателя является хороший вес и мощность. Управляющим сигналом серводвигателя является специфический сигнал широтно-импульсной модуляции (PWM), где длительность импульса определяет положение ротора. Период сигнала - 20 мс (частота 50 Hz) и ширина высокого полупериода 1-2 мс. 1 мс обозначает одно крайнее положение ротора и 2 мс другое крайнее положение ротора. 1,5 мс обозначает среднее положение ротора. Традиционный RC серводвигатель носит и имя аналогового серводвигателя. Причина в том, что в последнее десятилетие появились так называемые дигитальные серводвигатели. Разница между ними заключается в том, что в аналоговом серводвигателе мотор управляется входным сигналом 50 Hz PWM, а в дигитальном серводвигателе мотором управляет отдельный микроконтроллер с более высокой частотой. Входной сигнал у дигитального серводвигателя такой же, но высокая частота модуляции двигателя позволяет определять положение точнее и быстрее. ~~CL~~ ===== Практика ===== На плате модуля «Двигатели» Домашней Лаборатории есть два разъема для подключения RC серводвигателя. Концы разъемов PWM сигнала подсоединены к выводам PB5 и PB6 микроконтроллера, альтернативной функцией которых являются выходы А и В единиц сравнения 16 битнога таймера 1. Таймер 1 способен создавать PWM сигнал, в связи с чем управление двигателями в программе происходит очень просто. Сложнее только настройка таймера. Таймер 1 нужно настроить на режим создания PWM сигнала, где максимальное значение таймера обозначено ICR регистром. С помощью делителя такта таймера и меняющимся в программе максимального значения можно точно обозначить необходимую для управления серводвигателя частоту PWM сигнала. Регистром сравнения таймера можно обозначить длину высокого полупериода обоих PWM сигналов. У таймера имеются специальные единицы сравнения, которые отслеживают значение счетчика. Если оно становится таким же, как и значение регистра сравнения, то они меняют значение выхода единицы сравнения. Далее приведен программный код библиотеки Домашней Лаборатории, управляющий серводвигателями, который в целях универсальности использует параметры таймера, определенные макрофункцией. К примеру, для нахождения периода используется постоянная //F_CPU//, которая обозначает тактовую частоту микроконтроллера. Для разных тактовых частот не нужно самому вычислять параметры таймера макросами, и компилятор так и так переводит сравнения макросами в постоянные, так что память программы не увеличивается и не занимает больше время исполнения. // // Значение таймера для достижения полного периода (20 мс) PWM. // F_CPU - тактовая частота микроконтроллера, которая делится на 8 и 50 Hz. // #define PWM_PERIOD (F_CPU / 8 / 50) // // Центрально положение серво PWM (1,5 мс / 20 мс) // Центральное положение достигается взятием из полного периода 15/200 // #define PWM_MIDDLE_POS (PWM_PERIOD * 15 / 200) // // Повторный фактор, чтобы получить необходимый период +1 // в процентах (-100% до 100%) складывается для того, чтобы полупериод // точно достигал границ 1 и 2 мс или немного выще. // #define PWM_RATIO (PWM_PERIOD / 20 / 2 / 100 + 1) // // Настройка выводов // static pin servo_pins[2] = { PIN(B, 5), PIN(B, 6) }; // // Подготовка к работе выбранного серводвигателя. // void servomotor_init(unsigned char index) { // Вывод PWM сигнала выходом pin_setup_output(servo_pins[index]); // Настройка таймера 1 // Делитель такта 8 // Быстрый PWM режим, где TOP = ICR // OUTA и OUTB низким при сравнении timer1_init_fast_pwm( TIMER1_PRESCALE_8, TIMER1_FAST_PWM_TOP_ICR, TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH, TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH, TIMER1_FAST_PWM_OUTPUT_DISABLE); // Определение периода с помощью максимального значения timer1_set_input_capture_value(PWM_PERIOD); } // // Обозначение позиции серводвигателя // Параметр позиции от -100 до 100 процентов // void servomotor_position(unsigned char index, signed short position) { switch (index) { case 0: timer1_set_compare_match_unitA_value( PWM_MIDDLE_POS + position * PWM_RATIO); break; case 1: timer1_set_compare_match_unitB_value( PWM_MIDDLE_POS + position * PWM_RATIO); break; } } Пример программы использует функции, описанные в библиотеке Домашней Лаборатории. В начале программы заставляют работать таймер первого серводвигателя, генерирующий PWM сигнал, функцией //servomotor_init//. Значение положения серводвигателя получается из канала 3 аналого-дигитального преобразователя, куда на плате модуля «Датчики» подсоединен потенциометр. Для того чтобы получить необходимый для управления серводвигателя интервал от -100 до 100, от значения ADC отнимается половина максимума (т.е. 512) и делится на 5. Результатом является ±102, но небольшая неточность не считается, так как серводвигатели сами отличаются в отношении PWM сигнала и угла поворота. Для точного передвижения придется в приложениях обозначить ширину полупериода PWM методом проб и ошибок. Так же у моделей радиоуправляемых пультов для точной настройки существуют соответствующие возможности (на английском языке //trim//). При запуске программы, изменяется в соответствии с положением потенциометра и положение вала серводвигателя. // // Тест программа серводвигателя // модуля «Двигатели» Домашней Лаборатории. // #include #include // // Основная программа // int main(void) { short position; // Настройка ADC adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Настройка двигателя servomotor_init(0); // Бесконечный цикл while (true) { // Считывание позиции потенциометра и перевод // в область серводвигателя position = ((short)adc_get_value(3) - (short)512) / (short)5; // Обозначение позиции серводвигателя servomotor_position(0, position); } }