Поиск

2 августа 2013 г.

Автоматизация ведра или управление сервоприводом и датчик присутствия на AVR

Завалялось у меня некоторое количество сервоприводов для авиамоделей, и решил я их пустить в дело.

И вот в очередной раз наклоняясь, чтобы открыть крышку мусорного ведра, задумался, почему бы это дело не упростить.

Например так: поднес руку — крышка открылась, выкинул, что надо, — крышка закрылась.
В общем, решил продемонстрировать контроллер сервопривода на Atmel AVR ATtiny44A c датчиком присутствия на ИК приемнике TSOP4838.
Ведро использовано металлическое блестящее, в которой крышка открывается педалью, такие ведра можно найти во многих магазинах.





Электронная начинка


Алгоритм работы

  • ИК светодиод постоянно шлет некий бинарный код, ИК приемник его читает и если произошло совпадение выдается команда на открытие крышки.
  • После открытия крышки ждем 7 сек и закрываем крышку, если сенсор не активен.
  • Если во время открытия крышка уперлась в препятствие, то — пищим, ждем некоторое время (3 сек) и повторяем попытку. При повторной неудачи «засыпаем» на более длительное время (60 сек).


ИК Датчик


Принцип работы основан на свойстве отражения ИК лучей от препятствия.
ИК диод посылает в пространство модулированную кодовую посылку, а ИК приемник ее принимает.
Для регулирования мощности передачи используется подстроечный резистор RV1.
Несущая частота сигнала 38 кГц. 
Используется бифазное (манчестерское) кодирование. Для него не требуется кварцевой стабилизации частоты.

Вот осциллограммы кодирования бита:





Вот осциллограмма пакета:



ИК приемник (я использовал Vishay TSOP4838) принимает сигнал, декодирует и выдает на выход пакет в инвертированном виде.

Пакет повторяется через определенное время:



ИК приемник устройство «умное» и пытается отфильтровать сигнал, подавляя помехи, различные импульсы, которые не подходят под его понимания подходящего формата пакета.
Поэтому между пакетами должны быть пауза не меньше минимальной.
Например, при использовании TSOP4838, если сделать паузу в 15 бит при длине пакета 8 бит, то приемник будет достаточно часто пропускать пакеты.
При паузе в 30 бит — пакеты не пропускаются.

Сервопривод



Для открывания крышки используется стандартная серва Futaba S3001.
У нее выдаваемое усилие при 4.8 В около 2.4 кг/см, а при 6 В — 3 кг/см.
Крышка металлическая и относительно тяжелая, но данного сервопривода для нее хватает.

Питание на сервопривод подается только на время его позиционирования. Для этого используется Logic level MOSFET транзистор.
Для контроля потребляемого сервоприводом тока используется резистор 0.5 Ом.
Микроконтроллер замеряет падение напряжения на нем и, при превышении, отключает питание сервопривода.
Пиковое значение потребляемого тока во время открытия крышки 500 мА, во время закрытия — 150 мА, при «заклинивании» — 550 мА.

Сервопривод управляется импульсами длительностью от 1.1 до 1.8 мс, которые следуют каждые 0.02 секунды.
После окончания управляющего импульса сервопривод, при необходимости, начинает позиционироваться.

Осциллограммы:
Желтым — управляющие импульсы, голубым — потребление сервопривода (падение напряжения на шунте).

Вот осциллограмма начала нормального позиционирования сервопривода:



Нормальное позиционирование, где-то в середине перемещения:



Вот осциллограммы заклинивания сервы:



При старте держим руками:



Как можно видеть, в самом начале идет достаточно большое потребление практически не зависимо от того может сервопривод перемещаться или нет.
Так же видно, что моментальное потребление сервопривода не может быть больше определенного значения, и для контроля невозможности перемещения привода нужно, в идеальном случае, вычислять площадь под голубым графиком.
В программе падение напряжения на шунте считываются c помощью АЦП и используется простой способ суммирования моментальных значений в течении периода. Если сумма превышает определенный порог — сервопривод останавливается.
Порог подбирается экспериментально.
Значение при котором произошло срабатывание защиты сохраняется в EEPROM.

Схема:


Программа

Программа написана на С в Atmel Studio 6.1.
Использован микроконтроллер AVR ATtiny44A c 14 выводами в DIP корпусе.
Работает он на частоте приблизительно 7904000 Гц для того, чтобы легко получить 38000 Гц для ИК светодиода.
По умолчанию частота 8 МГц, и частота 7.9 МГц получена путем изменения регистра OSCCAL.
У меня получилось значение 0xA7 при напряжении 5 В.
При изменении напряжения питания или температуры частота немного уйдет, но на работоспособность ИК датчика это влияния не оказывает.

Для передачи — приема ИК сигнала, управления сервоприводом, отсчета времени используется один единственный 8-ми битный таймер, работающий на частоте 988 кHz и настроенный на режим Fast PWM.
Частота сигнала задается регистром OCR0A. В нем значение, при котором будет обнуляться счетчик таймера (TCNT0).
В OCR0B заносится значение, определяющее коэффициент заполнения импульсов. В нашем случае — 50%.
Таймер настроен так, что смена значения на выводе контроллера, к которому подключен ИК диод, происходит 2 раза в период (заданный OCR0A) — при нулевом значении TCNT0 и когда TCNT0 равен OCR0B.

В прерывании по равенству TCNT0 и OCR0B выполняется все работа по приему — передачи ИК сигнала.


ISR(TIM0_COMPB_vect) {
        static uint8_t IR_error = 0;
         
        if(++IR_pulsecnt == IR_BIT_LENGTH/2)
        {
                if(IR_pausecnt == 0)
                {
                        if(((IRSENS_IN & IRSENS) == 0) != ((TCCR0A & (1<<COM0B1)) != 0)) IR_error = 1;
                        TCCR0A ^= (1<<COM0B1);
                }
        } else if(IR_pulsecnt == IR_BIT_LENGTH)
        {
                IR_pulsecnt = 0;
                if(IR_pausecnt)
                {
                        if(--IR_pausecnt == 0)
                        {  // after pause send again
                                IR_send = IR_SENDDATA;
                                goto IRStartSending;
                        }
                } else {
                        if(IR_send == 0)  // Packet was sent
                        {
                                if(IR_error == 0) IRDetected = 1; else IR_error = 0;
                                IR_pausecnt = IR_PAUSEBITS;
                                TCCR0A &= ~(1<<COM0B1); // assumes that COM0B0 = 0
                        } else
                        {
IRStartSending:
                                TCCR0A = (TCCR0A & ~((1<<COM0B1))) | ((1<<COM0B1) * (IR_send & 1));
                                // assumes that COM0B0 = 0, if 1 - generate (Clear OC0B on Compare Match, set OC0B at BOTTOM)
                                IR_send>>=1;
                        }
                }
        }
}


Особенность функции отправки такова — пакет считается отправлен, когда битовый буфер равен 0. Это значит, что в старшем разряде пакета для отправки всегда должна быть единица.
Генерирование ИК сигнала начинается при установки бита COM0B1 в регистре TCCR0A. Подразумевается, что бит COM0B0 равен 0 и нигде до этого не устанавливался.

Управление сервоприводом, отсчет времени, подавление дребезга контакта кнопок выполняются в прерывании по переполнению этого же таймера.
В стандартном режиме, открытие крышки выполняется в два этапа — сначала несколько циклов медленно, затем быстро до полного открытия. Сделано для уменьшении нагрузки на сервопривод и тяги.

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

Сборка

Сервопривод подключается к вертикальной тяге, горизонтальная тяга и педаль выбрасываются.
ИК диод и приемник крепятся в выступающую пластиковую ножку. Места для них там как раз хватает.





Видео:
http://youtu.be/GKyD2-g8stk

Исходник: TouchlessCover.zip

2 комментария:

  1. круто, молодец. ты прям реализуешь мои мечты :)

    ОтветитьУдалить
  2. Прикольно, только что делать когда батарейка сядет и 220 закончится? Бардак будет дома?

    ОтветитьУдалить