Электронные часы на Arduino и модуле DS3231
Собрать хорошие оффлайновые электронные часы – это здорово, ведь они пригодятся в любом доме даже в наш век глобальной синхронизации через беспроводные сети. В этой статье я хочу поделиться созданным для Ардуино проектом электронных часов, в том числе предложить вашему вниманию схему устройства и скетч для него.
Также я детально расскажу о своём опыте реализации проекта и покажу, какие часы вышли у меня, но это скорее иллюстрации и примеры, чем подробная инструкция по сборке. Я уверен, что каждый самодельщик всё равно соберёт проект по-своему и внесёт в него собственные модификации.
Подойдёт ли проект новичкам?
Да. Новичок в Ардуино, вдоволь намигавшийся светодиодами, обычно задаётся вопросом: «Что бы такого сделать не очень сложного, но интересного и полезного?». Большинство сразу ударяется в беспроводные коммуникации, но по-моему, электронные часы – отличный вариант. Если новичок изучит и реализует этот проект, то он на практике познакомится:
• С библиотекой Wire.h и, хоть и совсем немного, с основами протокола I2C.
• С микросхемами часов реального времени (RTC).
• С побитовыми операциями.
• С популярной микросхемой сдвигового регистра 74HC595.
• С 7-сегментными светодиодными индикаторами.
• С мультиплексированием светодиодного дисплея.
• С управлением транзисторами посредством сигналов микроконтроллера.
• С выводом данных в терминал с помощью функций класса Serial через COM-порт (преобразователь USB-UART).
Говорю об этом с уверенностью, поскольку я тоже вчерашний новичок и я действительно многому научился, создавая этот проект.
Общее описание устройства
Электронные часы со светодиодным дисплеем и возможностью ручной настройки времени.












Характеристики и особенности
• Однополярное питание от источника постоянного напряжения на 5 В. Как вариант, можно питать схему от 3,3 В, но в таком случае нужно учесть некоторые нюансы (см. ниже).
• Точность порядка ±3 ppm. Это значит, что каждую секунду часы сбиваются примерно на 3 миллионные доли секунды. В итоге погрешность составляет около 2 минут в год. На самом деле, это весьма и весьма неплохо.
• Точка на дисплее, разделяющая часы и минуты, мигает, показывая отсчёт секунд.
• Возможность ручной настройки текущего времени с помощью кнопок.
• Продолжение отсчёта времени без потери данных в случае отключения основного питания. Осуществляется за счёт резервной батарейки модуля RTC.
Схема устройства и основные аппаратные узлы
Ниже приведена принципиальная схема часов. Изображение в более высоком качестве содержится в прикреплённом к посту PDF-файле (https://vk.com/sla_rw?w=wall-214685134_1).
В моём исполнении устройство включает следующие основные аппаратные узлы:
• Китайская копия платы Arduino Pro Mini.
Собрана на базе микроконтроллера ATmega328P с кварцевым резонатором (кварцем) на 16 МГц.
Разумеется, можно обойтись без платы разработки и смонтировать микроконтроллер самостоятельно, но я всё-таки предпочёл использовать готовую плату. Во-первых, на ней уже имеется необходимый для работы микроконтроллера «обвес»: кварц, конденсаторы между землёй и выводами кварца, подтягивающий резистор на выводе RESET микроконтроллера, а также опциальные удобства вроде кнопки перезагрузки. Во-вторых, на ней нанесена наглядная и привычная цоколевка Ардуино.
В качестве альтернативы проект может быть реализован практически на любом микроконтроллере AVR семейства ATmega, а также на небезызвестном китайском чипе LGT8F328P (клон ATmega328P). Другие совместимые с Arduino IDE микроконтроллеры (например, ESP32 и STM32), конечно, тоже имеют достаточный функционал, но их использование потребовало бы модификации скетча, поскольку используемая в нём библиотека Wire.h создана именно для микроконтроллеров AVR.
• Готовый модуль часов реального времени на основе микросхемы DS3231.
Модуль должен иметь встроенные резисторы, подтягивающие линии I2C к «плюсу» питания схемы. Как правило, эти резисторы в наличии, но если вам вдруг достался модуль без них, подключите резисторы номиналом от 4,7 кОм до 10 кОм между каждой линией RTC и «плюсом» питания схемы.
В качестве альтернативы в проекте можно без каких-либо модификаций использовать модуль на базе более старой микросхемы DS1307, поскольку она имеет идентичные с DS3231 I2C-адреса (как основной адрес микросхемы, так и адреса регистров времени) и алгоритмы работы. Однако по возможности лучше использовать DS3231, поскольку она имеет более высокие технические характеристики (см. ниже).
• 4-знаковый 7-сегментный светодиодный дисплей с общими катодами.




Каждый знак на дисплее (знакоместо) представляет собой классический 7-сегментный индикатор. Правильно подобранные комбинации нулей и единиц («байт-маски»), одновременно подаваемых на выводы дисплея, заставляют светодиоды светиться в сочетаниях, образующих цифры (и, опционально, некоторые буквы, но в данном проекте нам достаточно цифр).
Лично я бы скорее называл эти индикаторы 8-сегментными, поскольку помимо 7 светодиодов, образующих цифры, у каждого знака имеется 1 дополнительный светодиод – точка после цифры. Но так уж сложилась терминология.
В управлении дисплеем применяется мультиплексирование. Этот метод заключается в том, что в любой момент времени на дисплее включён только один знак, но микроконтроллер последовательно переключает знаки с такой частотой, что для человека все четыре знака кажутся горящими одновременно. Это упрощает аппаратную часть устройства (уменьшает необходимое количество управляющих выводов) и снижает его энергопотребление.
Дисплей с общими анодами тоже подойдёт, но в таком случае потребуется побитово инвертировать приведённые в скетче байт-маски и изменить подключение переключающих транзисторов: коллекторы соединяются с «плюсом» питания схемы, эмиттеры соединияются с общими анодами дисплея, базы соединяются с выводами микроконтроллера через резисторы на 150 Ом.
• 4 биполярных NPN-транзистора.
Подойдут любые маломощные транзисторы с максимальным током коллектора от 100 мА, например, 2N222, 2N4401, 2N3904, BC548 или КТ315.
Каждый транзистор соответствует одному общему катоду и, соответственно, одному знаку на дисплее. Когда транзистор открыт, ток может протекать через соответствующий знак, зажигая светодиоды. Когда транзистор закрыт, знак будет полностью выключен независимо от приложенной к дисплею байт-маски. Микроконтроллер попеременно подаёт на транзисторы открывающие и закрывающие сигналы, тем самым переключая активный знак.
• Микросхема 74HC595 (широко известная как просто «595»), выступающая в качестве драйвера дисплея.
595 преобразует поступающие на её вход последовательные сигналы в 8 параллельных выходных сигналов. Это и есть байт-маска. Выводы 595 соединяются с выводами дисплея, соответствующими сегментам индикаторов, через резисторы на 670 Ом.
• 3 кнопки настройки текущего времени.




Обычные кнопки, смонтированные на специально вырезанном куске макетной платы. Второй контакт каждой кнопки соединён с зёмлей. Макетная плата крепится к передней панели корпуса с помощью винтов и гаек.
Наверное, было бы проще использовать кнопки, крепящиеся непосредственно к корпусу (без платы), но кнопок с разъёмным соединением у меня либо не было под рукой, либо они были слишком громоздкими и не помещались в маленьком корпусе.
• Питание схемы
Схему можно питать от любого нормального источника напряжения на 5 В. Встроенный линейный регулятор напряжения платы Ардуино использовать не рекомендую – слишком уж неэкономичен, так что питание нужно подключать непосредственно к выводу 5V платы (к выводам VCC микроконтроллера).
Я остановился на импульсном преобразователе напряжения (вход 5-24 В, выход 5 В). Кроме того, я хотел сделать устройство немного «всеядным» в плане разъёмов питания.



По-хорошему нужно было разместить преобразователь и разъёмы внутри корпуса, но на это не хватило места.
Если вы планируете питать схему от 3,3 В, учтите, что в таком случае частоту ATmega следует снизить до 8 МГц и позаботиться о наличии кварца с соответствующим номиналом. LGT8F328P, по идее, в замене кварца не нуждается (у микросхемы имеется встроенный генератор), но я не проверял.
Программное обеспечение
Скетч приложен к посту: https://vk.com/sla_rw?w=wall-214685134_1
В комментариях к коду дано подробное описание основных функций и во многом разъяснено, что и как работает.
Основные процессы
Микросхема часов реального времени (RTC) ведёт непрерывный отсчёт времени и хранит его текущие значения в своих регистрах.
Микроконтроллер (МК) через интерфейс I2C раз в такт опрашивает RTC, получает от неё текущие значения часов, минут и секунд в формате packed binary-coded decimal (BCD) и переводит их в обычный числовой формат.
МК определяет, какие цифры необходимо отобразить на дисплее, выбирает байт-маску, соответствующую очередной отображаемой цифре, и загружает её в 595. Параллельно МК переключает активный знак.
Кнопка переключения режима при первом нажатии вводит часы в режим настройки времени, при повторном – выводит часы из него. В режиме настройки времени часы прекращают отображать текущее время, вместо этого они отображают значения часов и минут, которые готовы к отправке в RTC в качестве новых значений текущего времени. Пользователь с помощью кнопок настройки часов и минут устанавливает их новые значения. По завершении настройки выбранные пользователем значения часов и минут записываются в память RTC и часы возобновляют отсчёт и отображение времени.
Сборка
Основная часть устройства (плата Ардуино, 595, транзисторы, резисторы) собрана на обрезанной под нужный размер макетной плате. Для соединения с периферийными устройствами на основной плате предусмотрены наборы штырьковых контактов:
• Под общее питание схемы.
• Под выводы Rx, Tx и DTR преобразователя USB-UART (для загрузки скетчей в МК).
• Под питание RTC.
• Под шины I2C.
• Под кнопки настройки времени.
• Под шлейф дисплея.
Ах, пайка. Самая приятная для меня часть монтажа. При работе с макетными платами я люблю сочетать эмалированные и неэмалированные одножильные медные провода, дорожки из припоя и многожильные медные провода с изоляцией из ПВХ или силикона.


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







Как крепить плату внутри корпуса, я тоже заранее не подумал. В итоге я сделал внутри задней крышки «подушку» из термоклея и стойки из винтов. Плата помещается между этими стойками и прижимается к «подушке» с помощью прижимных пластинок.
Модуль RTC я просто посадил на термоклей.










Мысли россыпью
• Как уже было упомянуто, DS3231 и DS1307 в известной степени взаимозаменяемы, но DS3231 – гораздо более современная микросхема, которая по своим качествам значительно превосходит «старшую сестру». В частности, она имеет встроенную аппаратную температурную стабилизацию и повышенную точность (±3 ppm у DS3231 против ±20 ppm у DS1307).
Если вы всё же используете DS1307 и столкнулись с совсем уж неудовлетворительной погрешностью (более ±25 ppm), то советую приобрести несколько сменных кварцев на 32.768 кГц и заменить кварц модуля на один из них. Мой опыт показывает, что в эту лотерею вполне можно выиграть – один из опробованных мною модулей DS1307 после такой замены вместо +35 ppm продемонстрировал гораздо более привлекательные +10 ppm.
• Хотя я указываю точные номиналы резисторов, на моей практике резисторы в данной схеме не так уж и важны. Однажды я в рамках другого проект собирал аналогичные часы и подключил выводы дисплея к выводам 595 напрямую, вовсе без резисторов. Ни микросхема, ни дисплей не пострадали. Вероятно, это связано с мультиплексированием, но я не уверен.
Резисторы, подключаемые к базам транзисторов, на практике тоже можно опустить.
• В случае отключения основного питания микросхема RTC продолжает отсчёт времени при условии подачи на неё напряжения от 2,5 В до 3,5 В от резервного источника питания. Для реализации этой функции модули RTC, как правило, имеют держатель для батарейки-«таблетки» номинальным напряжением 3,3 В.
Если вы не планируете использовать эту функцию в вашем проекте и хотите удалить резервную батарейку, необходимо соединить «плюс» резервного питания микросхемы RTC (положительный контакт держателя батарейки) с общим «плюсом» питания схемы или с землёй, в противном случае микросхема RTC с высокой вероятностью будет выдавать через шину I2C «мусор».
