10 июня 2012 г.

Бинарные часы на AVR

Идея

Началось все с того что захотелось сделать какое-нибудь полностью законченное устройство на микроконтроллере AVR. 

Выбор пал на бинарные часы, т.к. они просты в изготовлении и достаточно эффектно смотрятся. А еще потому что мне всегда нравился плазмоид бинарных часов из KDE который выглядит вот так: 


Что такое бинарные часы?

Для тех кто не знает что такое бинарные часы и как по ним определить время, сделаю небольшое отступление. Бинарные часы это просто часы которые показывают время в двоичной (или бинарной) системе счисления, вместо привычной нам десятичной. 

Бинарные часы бывают разные (как в общем-то и обычные часы) - с разным количеством и расположением индикаторов,  с секундами или без, с 24-х или 12-и часовым форматом времени и т.д. Я решил остановиться на варианте максимально похожем на вышеупомянутый плазмоид из KDE:


Часы состоят из шести вертикальных колонок - две колонки на часы, две на минуты, и две на секунды (слева на право). Каждая колонка по сути представляет собой одну цифру (т.е. по две цифры на часы, минуты и секунды). 
В часах четыре горизонтальных строки, так как нам нужно уметь показывать цифры от нуля до девяти (по крайней мере для младшего разряда), а двоичное представление девятки - 1001, содержит четыре разряда (бита). Младший разряд находится снизу.

Проще всего понять какое время показывают часы анализируя "циферблат" слева на право, снизу вверх. Запишем значение двоичного числа представленного самым левым столбцом часов изображенных на картинке выше (условившись что горящий индикатор обозначает единицу, а потухший - ноль): 0010 в двоичной системе счисления это 2 - в десятичной. Аналогичным образом запишем значение второго столбца: 0001 в двоичной системе счисления (как и в десятичной), или просто единица. То есть на часах 21 час. Точно так же можно прочитать что часы показывают 35 минут и 28 секунд. Немного практики и читать время с бинарных часов будет получаться почти так же быстро как и с обычных.

Реализация

Итак, с идеей понятно, приступим к реализации.

Начнем с индикатора ("циферблата") - который представляет собой решетку из светодиодов.
Поскольку в часах 4 горизонтальных и 6 вертикальных рядов, общее количество необходимых светодиодов - 6 * 4 = 24. На самом деле, можно обойтись меньшим количеством светодиодов, т.к. не все разряды будут задействованы - например старшая цифра часов (самый левый столбец), может показывать число не больше двух (при двадцати часовом формате времени), а значит можно сэкономить целых два светодиода. Но я этого делать не стал и поставил все 24 светодиода, т.к. хотел (в будущем) использовать эти часы для показа простых текстовых сообщений.

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

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

Схема и печатная плата

Схема достаточно стандартная: микроконтроллер, питание, сброс, разъем для подключения программатора. К TOSC1 и TOSC2 подключен часовой кварц от которого будут тикать часы. Кнопки настройки времени подтянуты к напряжению питания. Десять выходов на светодиоды (6 столбцов+ 4 строки). На каждую горизонтальную строку подключен резистор для ограничения тока через светодиод.
Печатная плата получилась односторонняя, но все же с двумя перемычками с другой стороны (отмечены красным) которые достаточно просто сделать из тонкой медной проволоки.

Корпус

Наверное, это самая неинтересная часть. Но, в то же время, именно она заняла большую часть времени.

Сам корпус сделан из деревянных досок скрепленных гвоздями и клеем. После сборки доски были тщательно отшлифованы, вскрыты морилкой и несколькими слоями мебельного лака.

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

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

Программная часть

Программу я решил писать на ассемблере. Не потому что это самый удобный язык разработки, а исключительно в образовательных целях. Исходные коды можно найти ниже в разделе "Файлы".

Весь код описывать не буду, т.к. он достаточно подробно откомментирован. Опишу только ключевые моменты.

Развертка производится по столбцам, то есть сначала некоторое время горят светодиоды только первого столбца, затем второго и т.д. Происходит это очень быстро и глаз не успевает этого заметить, поэтому создается впечатление что все зажженные светодиоды горят одновременно. Для отображения значения времени в столбце используется макрос DISPLAY_COLUMN. Переключение столбцов осуществляется по таймеру Timer0.

Смена времени происходит раз в секунду по прерыванию переполнения таймера Timer/Counter2. Поскольку частота кварца равна 32768Гц, а предделитель таймера установлен на 128, то переполнение однобайтового таймера будет происходить раз в секунду (32768 / (128 * 256) = 1), что очень удобно.

Обработка нажатий на кнопки происходит в процедурах button_stop_pressed для кнопки перевода часов в режим настройки и обратно, button_set_pressed для кнопки установки времени и button_switch_pressed для кнопки переключения столбца. Обратите внимание, что в процедуре button_stop_pressed текущее время сохраняется в EEPROM. Это сделано для того что бы время не сбрасывалось если нужно, например, переключить часы в другую розетку (при включении часов время считывается из EEPROM).

Вся основная "работа", такая как - опрос состояние кнопок,  переключения активного столбца развертки и вывод времени происходит в main. Начальная инициализация выполняется в reset.


Результат

То что получилось в результате можно посмотреть на видео ниже. Там же запечатлены и некоторые стадии процесса изготовления.

Файлы

Шаблон печатной платы в формате PDF - скачать.
Исходные коды прошивки - скачать.

В качестве заключения

В общем, для первого устройства, думаю, получилось весьма неплохо.

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

11 комментариев:

Unknown комментирует...

Добрый день подскажите разводку светодиодов пожалуйста)ато я ток залез в эти дебри)

Alik комментирует...

Светодиоды собраны в виде решетки с 4 строками и 6 столбцами. Выводы AVR которые подключены к строкам это PA0, PA1, PA2, PA3 (те, на которых стоят токоограничительные резисторы). Выводы PA4, PA5, PA6, PA7, PC4, PC5 подключены к столбцам. Каждый светодиод в решетке анодом подключен к соответствующему выводу строки, а катодом - к выводу столбца. Например светодиод находящийся во второй строке и третьем столбце будет анодом подключен к выводу PA1 а катодом - к PA6. Если понятнее не стало - могу нарисовать картинку :)

Unknown комментирует...

спасибо огромное!!!

Unknown комментирует...

но теперь косяк с тем сложноли переписать код на атмегу8?(у меня их мешок просто)
)

Alik комментирует...

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

Александр Чурс комментирует...

Здравствуйте. А какое нужно напряжение? Собрал устройство, пробовал запитать от usb, но не вышло. На дорожках ведущих с светодиодам напряжение в 4-5 вольта, но не на всех.

Alik комментирует...

Александр, напряжение 5V, так что можно запитать от USB.

Александр Чурс комментирует...

Мультиметр выдает, что от usb идет 5.4в. Но светодиоды не загораются. на кнопки не реагирует. Прошивал мк программой Khazama AVR Programmer, программатор usbasp. Не можете предположить в чем проблема? Я просто не силен в таком, та что надежда только на вас..)

Alik комментирует...

Тяжело угадать в чем проблема. Для начала я бы прозвонил дорожки, проверил надежность пайки и наименование компонентов (на случай если вдруг впаяли не тот резистор). Потом, стоит проверить напряжение на ножках микроконтроллера VCC, AVCC и RESET - там должно быть +5V. Еще я бы проверил конфигурацию FUSE-битов.

Если ничего не помогает, то сначала можно написать простую тестовую программу, например поморгать одним светодиодом, и посмотреть удастся ли заставить её работать.

Александр Чурс комментирует...

Проверил, примерно 5 вольт. 4.98, 5.04, 5.02. Возможно погрешности мультиметра. Резисторы вроде подходящие.
FUSE биты как нужно было проставлять? Я просто думал, они автоматически подтянуться. Прошивку брал готовую в виде hex файла, с копипастом вашей статьи с другого сайта. Вот от сюда http://radioparty.ru/device-avr/598-binary-clock-atmega32

Alik комментирует...

FUSE в прошивке не хранятся, их нужно менять/читать программатором. Насколько я помню, конфигурации по умолчанию должно быть достаточно. Но можно все равно прочитать фьюзы и посмотреть, на случай если случайно выставили что-то не то.

Отправить комментарий