Введение
Итак, у меня есть собака.
Краткое резюме:
Кличка: Белка
Окрас: Белый с рыжим
Порода: Западносибирская лайка с кем-то еще
Происхождение: Дворянское
Стоимость: 0р 0к
Собака была приобретена в собственном подъезде за еду и кров. Была выброшена какими-то негодяями без еды и воды в картонной коробке без фирменных логотипов породы и адреса завода-изготовителя. Ну да не важно, мы и с менее качественным товаром имели дело, а тут такая рыжая морда, и совсем бесплатно. Берем!
Пришлось принимать товар как есть, NO-NAME. Скорее всего, сделано в Китае. Гарантийные претензии тоже непонятно, кому предъявлять, а они были — в собаке водились глисты длиннее ее самой. К счастью, все это в прошлом. Зверюга подросла. Доказала свою преданность и послушность, за что получила возможность гулять без веревки на шее. Поскольку это не просто собака, а настоящая собака-гуляка, которая привыкла к полноценной четырёхразовой прогулке без поводка (она у меня совсем не агрессивная, но очень любознательная и послушная), ей потребовался своеобразный маячок, чтобы наблюдать ее похождения даже в темноте, и не нервничать, куда ж она подевалась. А подеваться ей есть куда — ее любимое занятие — приносить палки хозяину, и требовать, чтобы он ее кинул. Ну а найти-уж ее дело. Но это ж не простая собака, а собака, у которой папка- программист и немножко электронщик. Впрочем, даже простой ошейник с DealExtreme приковывает взгляды окружающих, особенно радуются дети. Разве это не стоит того? Но начнем с начала. Под катом много текста!
Заводские модели
Итак, я заказал с DX ошейник, который светится в темноте. Если вам любопытно, то вот он. Так выглядят его потроха:
Могу ли я его рекомендовать к покупке? Вопрос спорный. И да, и нет. Почему да? Он работает. Его световод действительно светится, и есть 3 режима — постоянный, моргающий и быстро моргающий. Питается от одной батарейки CR2032. Расход около 20mah. Почему я его не порекомендую? Потому что хитрые китайцы сэкономили кусок световода, и на мою собаку его хватает лишь на половину шеи, поскольку он оказался впору лишь раскрытый на полную длинну. Впрочем, даже этого хватает на wow-эффект от других собаководов, да и просто особо впечатлительных граждан. Недавно появились ошейники значительно дешевле, причем в разных цветах, да и подешевле. Об их размерах и точных характеристиках я судить не берусь, у меня такого еще нет, но скоро будет, потому что рыжий для моего проекта не подходит — жду белый. На ибее тоже полно разных модификаций, ищется по запросу Dog collar. Тем не менее, я решил пойти дальше!
Итак, основная идея была сделать ошейник на RGB светодиоде, который переливался бы разными цветами. В Китае я таких не нашел, но хочется же сделать что-то необычное, чего ни у кого нет! Ну это же всяко круче, чем простая красная моргалка! Сейчас прибегут ардуиноненавистники, и скажут, что все, что могут микроконтроллеры Atmel-это мигать диодами. И будут правы — это у них получается весьма неплохо, по крайней мере, выходы вполне тянут светодиод без необходимости ставить транзисторы. Конечно, ардуину я не стал встраивать в ошейник, да у меня и не было ее ни разу. Но с контроллерами AtMega дело имел. Поэтому я выбрал AtTiny13A. Почему A? Потому что в них есть хитрые технологии энергосбережения! Давайте разбираться!
Энергосбережение
Поскольку питание у нас от батареек, энергию надо как-то экономить. Хотя бы в выключенном состоянии. Выключатель ставить не хотелось, поэтому на включение, выключение и переключение режимов у нас есть только одна кнопка. В результате курения Datasheet, выяснилось, что есть специальный режим power-down, который поможет нам сэкономить лишнюю энергию батарейки, когда у ошейника нет необходимости сиять на зависть окружающим! С него и начнем. Есть специальное прерывание INT0, которое позволяет проснуться нашей спящей красавице AtTiny без помощи семи гномов и прекрасного принца — надо лишь на нужную ногу повесить специально обученную кнопку! Ну и отлично! По кнопке просто сбросим все цвета, который мы должны отобразить до черного, сброс настроек последнего выбранного режима, ну и всякие подавления дребезга кнопок, выключение диода на момент нажатия, ну и конечно, переключение режима — зачем же еще пользователю нужна эта единственная кнопка! Прошу прощения за отсутствие тега code, почему-то он у меня все в одну строку сваливает.
ISR (INT0_vect)
{
OFF_LED();
WAITBUTTON();
mode++;
if (mode>MAX_MODE) mode=0;
want_new_color=1;
need_delay=0;
R_value=0;
G_value=0;
B_value=0;
ON_LED();
}
Отлично! У нас есть кнопка, которая будит наш контроллер и умеет менять режимы. Осталось прицепить диоды на нужные ноги, и вперед! А нужные-это какие? Да, проблема, на этом контроллере у нас лишь два канала ШИМ, а нужно три. Ну и фиг с ним, будем реализовывать программно.
Управление яркостью диодов
ШИМ- это не наш метод. Будем использовать BAM! Почему-то мне его реализация показалась даже проще, чем ШИМ. Да и ресурсов меньше надо. Осталось реализовать лишь хитрый алгоритм BAM. Но в нем и хитрого-то ничего нет. Устанавливаем нашу яркость в диапазоне от 0 до 255. Один байт, то есть. А дальше смотрим — если старший бит у нас 1, ставим задержку таймера на 128 единиц, если второй по старшинству — 64 ед, если третий- 32, и т. д. По сути-обычная битовая маска со сдвигом на единицу. Проще пареной репы! Главное выяснить, должен ли с этим битом гореть диод, или должен быть погашен. Разумеется, тут у нас применен обычный таймер по сравнению с регистром OCR0A. Код таймера:
ISR(TIM0_COMPA_vect)
{
OCR0A>>=1;
if (OCR0A==0) OCR0A=0x80;
//Все погашены
uint8_t leds=0xFF;
//Обнуляем биты для включения диодов
if (R_value&OCR0A) leds^=LED_R;
if (G_value&OCR0A) leds^=LED_G;
if (B_value&OCR0A) leds^=LED_B;
//Зажигаем!
PORTB=leds;
}
Да, код BAM (Bit angle modulation) не менее банален, чем код ШИМ (PWM – Pulse Width Modulation), при этом требует меньше ресурсов! В качестве эксперимента, мне удалось запустить микроконтроллер на частоте 600кГц (4.8МГц, делитель 8), делитель счетчика 8, но разрядность БАМ всего 5 бит, иначе глючило все нещадно, контроллер не успевал отрабатывать прерывания без видимого мерцания. Не 8, конечно, но заработало, и не мерцало! Как сделал? Да опять же, просто! Просто отбросил младшие биты, немного изменив код:
OCR0A>>=1;
if (OCR0A==8) OCR0A=0x80;
Думаю, во многих случаях это будет отличный вариант. Почему я полез в эти эксперименты? Потому что накосячил с кодом, и у меня не включался режим power-down, поэтому я вынужден был экспериментировать с максимальными возможностями BAM на сверхнизких частотах для экономии энергии в якобы выключенном режиме. Уверен, что если бы я уверенно владел ASM-ом, у меня бы все работало и на минимальной частоте процессора-128кГц. Но я им не овладел… (FOREVERALONE.JPG)
Что еще? Нарастание и убывание яркости сделано приближенным к экспоненте. В связи с ограничением памяти тиньки не устроил ни рассчет экспоненты (пришлось бы тащить с собой нефиговый кусок кода математического модуля, который весит едва ли меньше всей памяти тиньки). Массив отпал по той же причине — 256 байт предварительно рассчитанных элементов+накладные расходы. Поэтому я принял решение использовать простенькую апроксимацию, просто оценил на глаз удовлетворяющие меня значения. Получилось весьма компакто и вполне работоспособно.
uint8_t inc_light(uint8_t value) {
if (value<50) value++;
else if (value<128) value+=2;
else if (value<253) value+=3;
else value=255;
return(value);
}
Режимы
Больше никаких открытий в коде нет. Блок main() написан в виде конечного автомата, в зависимости от выбранного режима увеличиваем или уменьшаем яркость компонентов R, G, B. А все остальное сделают прерывания. Да, стоит упомянуть про мой «генератор случайных чисел». Random() оказался довольно увесистым, поэтому я заменил его обычным регистром TCNT0. Тем самым, который считает время.
if (want_new_color) {
new_color=color;
while((color==new_color)|(new_color==0)) {
new_color=((TCNT0^(TCNT0>>3)) & 0b00000111);
}
color=new_color;
want_new_color=0;
}
Конечно, элемента случайности в нем не так уж и много, но три-четыре бита псевдорандома из него выжать можно, тем более, нет необходимости генерировать несколько случайных чисел подряд. При таком малом объеме памяти всегда приходится идти на компромиссы.
Сделано несколько режимов. Первый — плавное перетекание цвета из одного в другой. Цвета выбираются случайно. Исключения — черный.
Второй режим выглядит как разноцветные вспышки с разными интервалами времени между ними. Третий — «проблесковый маячек». Красно-синяя моргалка. На транспорте такую ставить запрещено, а вот на собаку можно. Просто небольшой глум. Остальные три режима — просто вспышки красного, синего, или зеленого по выбору. Код компилировался в AVR Studio 4.18 build 700, WinAVR-20100110. Размер составил 992 байта, почти под завязку. Более новую версию не качал. Возможно, и пожирнее HEX получится. А может, и меньше. По коду всё, пожалуй.
Про железо
Схему не привожу, ее и нет. Есть печатная плата, на которой все видно.
Потребовалось уместить все на кусочке текстолита с площадью около 4 квадратных сантиметров. Кнопка вешается между выходов BTN и GND и приклеена с обратной стороны платы термоклеем. Сердце нашей светодиодной моргалки AtTiny13A, как я уже упоминал. В качестве питания выбраны 2 элемента CR2032 (6V), и уже полюбившаяся мною микросхема LP2980 с напряжением стабилизации 5V и током до 50mA. Поэтому рассчитывайте номинал резисторов, чтобы ток через каждый из диодов не превышал 15mA. Самый пик нагрузки приходится на белый цвет, когда потребление подходит к «потолку» этой мелкосхемы, но это бывает не так часто. Думаю, можно будет поставить и стабилизатор на 3.3V. На 9.6МГц контроллер должен работать вполне стабильно. Конденсаторы танталовые на 47мкф, 10V, тип B. При переполюсовке тот, который на входе, у меня натурально взорвался. К счастью, все остальное выжило, хоть я и опасался тотальной гибели компонентов. Случайное подключение к 12V тоже прошло без последствий, но повторять это я не рекомендую.
Фото в собранном виде, припаян разъем программатора.
Разумеется, перед сборкой разъем программатора с проводами отпаивается. На светодиод одевается световод, и закрепляется термоусадкой на плате (ну или синей изолентой). Почему это еще не сделано? Читай дальше!
Недостатки
Чего не удалось сделать — более или менее человеческое управление питанием. Стабилизатор имеет функцию отключения питания, но как ей воспользоваться, если на микроконтроллере не будет питания? Совсем без стабилизатора тоже нельзя, на свежих элементах напряжение доходит почти до 7V, при максимальных паспортных 5.5V для атмелевских контроллеров. Если у кого-то есть идеи, делитесь. При данной реализации ток потребления схемы составил около 65 микроампер. Меня это, впрочем, удовлетворило. А теперь самый большой fail: в моем рыжем ошейнике все цвета выглядят рыжими, хоть синий, хоть зеленый. Отбелить подручными средствами не удалось. Поэтому ни фоток, ни видео в собранном виде нет. Теперь жду белый ошейник с тинидил, и надеюсь, что мои потроха в него влезут как надо. В крайнем случае, корпус с рыжего в белый воткну.
Видео работы
Полосатость света — глюки матрицы от БАМ. Мерцание не заметно на самом деле. Всем кто дочитал, спасибо!
Да, совсем забыл про исходники и печатную плату
Автор: BugMaker