Недавно ко мне обратились знакомые из макетной мастерской и предложили поработать над весьма интересным проектом. Им необходимо было выполнить макет, в котором бы двигались детали нескольких машин (кран, экскаватор, разрушитель). Логика несложная, но особенность в том, что они должны были двигаться со скоростью, гораздо ниже, чем скорость самих приводов, а это возможно реализовать только проходом через промежуточные точки. В этой статье я хочу познакомить вас с интересным методом точного управления большим количеством сервоприводов.
В моем случае предполагалось использовать четыре привода. Для этого проекта я изготовил небольшую плату:
![image](https://habrastorage.org/r/w780q1/getpro/habr/post_images/007/b21/fcb/007b21fcb15d9d709310217a8ac310a1.jpg)
![image](https://habrastorage.org/r/w780q1/getpro/habr/post_images/c0a/903/640/c0a903640085cbf01b2a7ecbe4f73ff7.jpg)
Сама плата простая – микроконтроллер Atmega16A-AU, стабилизатор для контроллера, два стабилизатора на приводы и PLS-разъем для подключения приводов. В моем случае на приводы нагрузки почти не было (сервы двигали бумажными деталями) поэтому для приводов хватило одного линейного стабилизатора на небольшом радиаторе.
По управлению приводами я нашел две наиболее интересные статьи у alex-exe и di halt'а. Но в обоих методах есть определенные недостатки. В первом случае: необходимо слишком часто вызывать прерывание, что труднопредсказуемо замедляет выполнение основного цикла и не позволяет получить высокую точность позиционирования. При его реализации привод достаточно сильно дергается, точность установки – около 1 градуса. Собственно, вот видео:
Метод DI HALT’а предполагет формирование по возрастанию, то есть необходимо дополнительно обсчитывать сигналы.
В связи с этим я хочу предложить еще один метод, который позволяет избежать обе эти трудности.
Принцип управления сервопривода прост: необходимо с периодом 15-20мс отправлять импульсы с длительностью 0,8-2,3мс. Длительность импульса определяет положение сервопривода. Предлагаемый метод предполагает формирование импульсов на ножках МК одного за другим, как показано на рисунке.
![image](https://habrastorage.org/r/w780q1/getpro/habr/post_images/ab5/87c/ad5/ab587cad5d8c69ea7fc50b011448c506.jpg)
Для реализации такого метода достаточно всего одного таймера. Я настроил таймер на увеличение каждую микросекунду. Весь период сигнала – 18000мкс, время на формирование одного импульса – 4500мкс. Прерывание по таймеру при управлении четырьмя сервами вызывается восемь раз. Отсюда вытекает ограничение метода: не получится на один таймер повесить больше 8-ми приводов (за 20мс можно сформировать максимум 8 импульсов длительностью 2,3мс).
Переменные angle1-angle4 это углы в нормированных единицах, меняющиеся в основном цикле программы. Для изменения угла от 0 до 180 градусов они должны меняться от 800 до 2200. Все управление происходит в обработчике прерываний. При первом срабатывании таймера в единицу выставляется нога ответственная за первый привод. Тут же в регистр OCR1A записывается значение угла для этого привода. При следующем срабатывании нога устанавливается в 0 и в регистр OCR1A записывается количество тактов, которое осталось до конца периода управления одним приводом (у меня он выставлен 4500). Затем все то же самое проделывается с ногой, ответственной за второй привод. Таким образом, каждые 4,5мс на одной ноге за другой появляется импульс необходимой длительности, причем с точность до 1мкс! То есть точность установки угла будет меньше 10-ти минут и ограничена характеристиками самого привода. Итак, сам код:
Текст всей программы приводить не буду, скажу только что углы в основном цикле могут формироваться любым образом – хоть по данным с UART, хоть с ADC. Я же фактически руками забил куда ехать, где и сколько постоять и т.д. Также у меня еще был тумблер. Во включенном положении сервы двигаются по программе, а при выключении возвращаются в свое исходное положение. При необходимости все исходники проекта могу выслать на почту.
Вот видео работы четырех приводов:
Обратите внимание на привод в левом нижнем углу – движения практически не заметно! Этот привод управляет стрелой крана. Добавлю еще про сами приводы. Мне в руки попало четыре разных привода – два аналоговых и два цифровых. Примечательно, что оба аналоговых привода могли работать нормально только пару минут, а потом начинать произвольно дергаться, зажиматься в крайних положениях и т.д., хотя оба привода рабочие – проверял сервотестером. Цифровые приводы выполняли все четко и стабильно по несколько часов подряд (а может и суток). Нареканий от заказчика я не слышал. Для стрелы крана я использовал привод Hi-Tech, который изменял свою позицию с минимальным шагом.
И напоследок – фото макета. Видео, к сожалению, выложить не могу.
![image](https://habrastorage.org/r/w780q1/getpro/habr/post_images/e14/a8c/690/e14a8c690bac99df4d3cea15b7fbf3a7.jpg)
UPD:
Основная статья теперь хранится здесь.
В моем случае предполагалось использовать четыре привода. Для этого проекта я изготовил небольшую плату:
![image](https://habrastorage.org/getpro/habr/post_images/007/b21/fcb/007b21fcb15d9d709310217a8ac310a1.jpg)
![image](https://habrastorage.org/getpro/habr/post_images/c0a/903/640/c0a903640085cbf01b2a7ecbe4f73ff7.jpg)
Сама плата простая – микроконтроллер Atmega16A-AU, стабилизатор для контроллера, два стабилизатора на приводы и PLS-разъем для подключения приводов. В моем случае на приводы нагрузки почти не было (сервы двигали бумажными деталями) поэтому для приводов хватило одного линейного стабилизатора на небольшом радиаторе.
По управлению приводами я нашел две наиболее интересные статьи у alex-exe и di halt'а. Но в обоих методах есть определенные недостатки. В первом случае: необходимо слишком часто вызывать прерывание, что труднопредсказуемо замедляет выполнение основного цикла и не позволяет получить высокую точность позиционирования. При его реализации привод достаточно сильно дергается, точность установки – около 1 градуса. Собственно, вот видео:
Метод DI HALT’а предполагет формирование по возрастанию, то есть необходимо дополнительно обсчитывать сигналы.
В связи с этим я хочу предложить еще один метод, который позволяет избежать обе эти трудности.
Принцип управления сервопривода прост: необходимо с периодом 15-20мс отправлять импульсы с длительностью 0,8-2,3мс. Длительность импульса определяет положение сервопривода. Предлагаемый метод предполагает формирование импульсов на ножках МК одного за другим, как показано на рисунке.
![image](https://habrastorage.org/getpro/habr/post_images/ab5/87c/ad5/ab587cad5d8c69ea7fc50b011448c506.jpg)
Для реализации такого метода достаточно всего одного таймера. Я настроил таймер на увеличение каждую микросекунду. Весь период сигнала – 18000мкс, время на формирование одного импульса – 4500мкс. Прерывание по таймеру при управлении четырьмя сервами вызывается восемь раз. Отсюда вытекает ограничение метода: не получится на один таймер повесить больше 8-ми приводов (за 20мс можно сформировать максимум 8 импульсов длительностью 2,3мс).
Переменные angle1-angle4 это углы в нормированных единицах, меняющиеся в основном цикле программы. Для изменения угла от 0 до 180 градусов они должны меняться от 800 до 2200. Все управление происходит в обработчике прерываний. При первом срабатывании таймера в единицу выставляется нога ответственная за первый привод. Тут же в регистр OCR1A записывается значение угла для этого привода. При следующем срабатывании нога устанавливается в 0 и в регистр OCR1A записывается количество тактов, которое осталось до конца периода управления одним приводом (у меня он выставлен 4500). Затем все то же самое проделывается с ногой, ответственной за второй привод. Таким образом, каждые 4,5мс на одной ноге за другой появляется импульс необходимой длительности, причем с точность до 1мкс! То есть точность установки угла будет меньше 10-ти минут и ограничена характеристиками самого привода. Итак, сам код:
ISR(TIMER1_COMPA_vect)
{
if (takt == 0)
{
PORTC |= 0b00000001;
OCR1A = angle1;
}
if (takt == 1)
{
PORTC = PORTC & 0b11111110;
OCR1A = cycle - angle1;
}
if (takt == 2)
{
PORTC |= 0b00000010;
OCR1A = angle2;
}
if (takt == 3)
{
PORTC = PORTC & 0b11111101;
OCR1A = cycle - angle2;
}
if (takt == 4)
{
PORTC |= 0b00000100;
OCR1A = angle3;
}
if (takt == 5)
{
PORTC = PORTC & 0b11111011;
OCR1A = cycle - angle3;
}
if (takt == 6)
{
PORTC |= 0b00001000;
OCR1A = angle4;
}
if (takt == 7)
{
PORTC = PORTC & 0b11110111;
OCR1A = cycle - angle4;
}
takt = takt + 1;
if (takt == 9) takt = 0;
}
Текст всей программы приводить не буду, скажу только что углы в основном цикле могут формироваться любым образом – хоть по данным с UART, хоть с ADC. Я же фактически руками забил куда ехать, где и сколько постоять и т.д. Также у меня еще был тумблер. Во включенном положении сервы двигаются по программе, а при выключении возвращаются в свое исходное положение. При необходимости все исходники проекта могу выслать на почту.
Вот видео работы четырех приводов:
Обратите внимание на привод в левом нижнем углу – движения практически не заметно! Этот привод управляет стрелой крана. Добавлю еще про сами приводы. Мне в руки попало четыре разных привода – два аналоговых и два цифровых. Примечательно, что оба аналоговых привода могли работать нормально только пару минут, а потом начинать произвольно дергаться, зажиматься в крайних положениях и т.д., хотя оба привода рабочие – проверял сервотестером. Цифровые приводы выполняли все четко и стабильно по несколько часов подряд (а может и суток). Нареканий от заказчика я не слышал. Для стрелы крана я использовал привод Hi-Tech, который изменял свою позицию с минимальным шагом.
И напоследок – фото макета. Видео, к сожалению, выложить не могу.
![image](https://habrastorage.org/getpro/habr/post_images/e14/a8c/690/e14a8c690bac99df4d3cea15b7fbf3a7.jpg)
UPD:
Основная статья теперь хранится здесь.