Pull to refresh

Управление несколькими сервоприводами с высокой точностью на МК ATmega16

Reading time 3 min
Views 51K
Недавно ко мне обратились знакомые из макетной мастерской и предложили поработать над весьма интересным проектом. Им необходимо было выполнить макет, в котором бы двигались детали нескольких машин (кран, экскаватор, разрушитель). Логика несложная, но особенность в том, что они должны были двигаться со скоростью, гораздо ниже, чем скорость самих приводов, а это возможно реализовать только проходом через промежуточные точки. В этой статье я хочу познакомить вас с интересным методом точного управления большим количеством сервоприводов.

В моем случае предполагалось использовать четыре привода. Для этого проекта я изготовил небольшую плату:

image

image

Сама плата простая – микроконтроллер Atmega16A-AU, стабилизатор для контроллера, два стабилизатора на приводы и PLS-разъем для подключения приводов. В моем случае на приводы нагрузки почти не было (сервы двигали бумажными деталями) поэтому для приводов хватило одного линейного стабилизатора на небольшом радиаторе.

По управлению приводами я нашел две наиболее интересные статьи у alex-exe и di halt'а. Но в обоих методах есть определенные недостатки. В первом случае: необходимо слишком часто вызывать прерывание, что труднопредсказуемо замедляет выполнение основного цикла и не позволяет получить высокую точность позиционирования. При его реализации привод достаточно сильно дергается, точность установки – около 1 градуса. Собственно, вот видео:



Метод DI HALT’а предполагет формирование по возрастанию, то есть необходимо дополнительно обсчитывать сигналы.

В связи с этим я хочу предложить еще один метод, который позволяет избежать обе эти трудности.

Принцип управления сервопривода прост: необходимо с периодом 15-20мс отправлять импульсы с длительностью 0,8-2,3мс. Длительность импульса определяет положение сервопривода. Предлагаемый метод предполагает формирование импульсов на ножках МК одного за другим, как показано на рисунке.

image

Для реализации такого метода достаточно всего одного таймера. Я настроил таймер на увеличение каждую микросекунду. Весь период сигнала – 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

UPD:
Основная статья теперь хранится здесь.
Tags:
Hubs:
+41
Comments 34
Comments Comments 34

Articles