Дисплей tm1637 на FreeBSD
Всё началось с покупки нового телевизора...
С полки исчезла DVB-T2 приставка, почти ненужная, но Чемпионат по футболу смотрел именно на ней! Через пару-тройку дней, когда интерес к новым возможностям телевизора угас, я осознал, что с приставкой потерял нечто важное - часы! Простенькие электронные часы на лицевой панели приставки, самосинхронизирующиеся как-то там, всегда на виду... были... Но, вроде бы, не всё безнадёжно - рядом на полке стоит мой... эээ... мини-сервер точного времени для домашней сети - Raspberry Pi 2 c GLONASS-приёмником и под управлением FreeBSD (и кому, как не ему, знать точное время?), а в ящике стола завалялся 7-сегментный цифровой дисплей tm1637 0.36" с двумя точками как на часах и четырьмя контактами (рублей 50 за него отдал на Aliexpress.com)... Четыре проводка с F-F-контактами для соединения с "малинкой" тоже найдутся.
Посмотрим, что мы с этим можем сделать...
С полки исчезла DVB-T2 приставка, почти ненужная, но Чемпионат по футболу смотрел именно на ней! Через пару-тройку дней, когда интерес к новым возможностям телевизора угас, я осознал, что с приставкой потерял нечто важное - часы! Простенькие электронные часы на лицевой панели приставки, самосинхронизирующиеся как-то там, всегда на виду... были... Но, вроде бы, не всё безнадёжно - рядом на полке стоит мой... эээ... мини-сервер точного времени для домашней сети - Raspberry Pi 2 c GLONASS-приёмником и под управлением FreeBSD (и кому, как не ему, знать точное время?), а в ящике стола завалялся 7-сегментный цифровой дисплей tm1637 0.36" с двумя точками как на часах и четырьмя контактами (рублей 50 за него отдал на Aliexpress.com)... Четыре проводка с F-F-контактами для соединения с "малинкой" тоже найдутся.
Посмотрим, что мы с этим можем сделать...
- Первым делом поищем в Интернете типовые подключения для таких дисплейчиков, ну, чтобы не "городить огород"... Ага, предлагают пины 38 и 40 для CLK и DIO, соответственно. С питанием, интересно, - 5В, но прекрасно работает и от 3.3В.
Итак, наши первые данные - пины на разъёме "Малины": - CLK - 38 (GPIO20)
- DIO - 40 (GPIO21)
- VCC - 17 (3.3V)
- GND - 34 (GND)
- На просторах Интернета была найдена вполне работоспособная библиотека от bitbank2, адаптированная для Linux: Но она использует libarmbianio для доступа к gpio, а у нас libgpio. Посмотрев её код и "покурив" man gpio я решил попытаться заменить вызовы AIOWriteGPIO на аналогичные gpio_pin_high и gpio_pin_low. Дело оказалось проще, чем я думал и, после нескольких правок типов переменных, библиотечка собралась. Окрылённый быстрым результатом, я запустил по инструкции сборку приложенной к коду демонстрационной программы, получил бинарник и запустил его ... а уж, после того как до меня дошло, что номера пинов 38 и 40 в исходном коде программки следует заменить номерами GPIO 20 и 21, соответственно (см. "Raspberry PI pinout" в любимом поисковике), по дисплею бодро побежали циферки с мигающим двоеточием.
- Осталось написать свою программку с использованием этой библиотеки для отображения времени. Её задачи просты:
- Зажечь (инициализировать) дисплей;
- В фоне периодически опрашивать локальное (местное) время системы;
- Выводить полученное время на цифровой дисплей;
- При окончании работы, по возможности, корректно завершить взаимодействие с устройствами;
- Неплохо бы реализовать авто-(старт|стоп) при старте и выключении системы.
Язык програмирования С я учил "по ходу" :-), но програмка, на мой взгляд, получилась маленькая и лаконичная. В ней реализованы наши первые 4 задачи - бесконечный цикл, в цикле запрос localtime(3), форматирование строки и вывод её на дисплей 2 раза в секунду, чередуя при этом наличие разделительных двух точек, а также, программа при старте перехватывает сигналы SIGTERM и SIGINT (нормальное завершение и прерывание выполнения) с целью выключить дисплей.
Пятая задача решается сервисным скриптом /usr/local/etc/rc.d/digitalclock в котором она "демонизируется" (запускается в фоновом режиме, отключенной от терминала, с помощью команды daemon(8). Если эта возможность интересна, то скрипт следует скопировать в указанное место и активировать строчкой
CODE:
digitalclock_enable="YES"
в системный файл конфигурации /etc/rc.conf или, что более модно, в индивидуальный файл конфигурации /usr/local/etc/rc.conf.d/digitalclock
Вот, как будто, и всё!
Но после того, как мне надоело любоваться делом рук своих, у программки обнаружилась несколько недостатков:
- Вывод времени происходил два раза в секунду, и выводилось сразу 4 знака, поэтому занимала эта задача ~0.30% процессорного времени, что мне показалось многовато. Хотелось выводить 4 знака, только когда часы и минуты реально изменились, а в остальное время выводить только мигающее двоеточие. Этого используемая библиотека не позволяет;
- Смешно сказать, но секунды оказались не совсем секундами - рядом с дисплеем находится GLONASS-приёмник и частота мигания у них обоих явно не совпадает;
- Для запуска программы в качестве сервиса, приходится использовать системную утилиту daemon(8) и она висит дополнительным процессом, что, как-то, не комильфо.
Для решения первой проблемы была найдена и адаптирована аналогичным образом к libgpio ещё одна библиотека, написанная для Arduino:
Библиотека описывает класс для tm1637 и для сборки использует c++ (в нашем случае clang++).
Для автоматической сборки был создан Makefile - его задача, собрать стандартную библиотеку с версией, софтверную ссылку на неё со стандартным именем, типа libtm1637.so, и положить её на стандартное место, в /usr/local/lib - у предыдущей библиотеки он был.
Как пользоваться методами объявленного класса понятно из папки ./examples. Эта библиотека уже позволяет выводить произвольный символ в произвольную позицию, в частности, для мигающего двоеточия достаточно 2 раза в секунду выводить только один символ (экономия в 4(!) раза).
Для точного вывода секунд я использовал POSIX-таймер, создаваемый через timer_create(2), вызывается точно 2 раза в секунду и, если время изменилось с момента прошлого вызова, печатает все 4 знака, а если не менялось, то печатает только второй знак, каждый раз включая или выключая у него признак двоеточия (если кто не знает, то двоеточие - это дополнительный сегмент второго по порядку знака на дисплее tm1637. Я не знал).
В программу добавилось создание файла с номером процесса pidfile(3) и процедура daemon(3) (Пример использования прямо в man pidfile), что избавило от запуска дополнительной утилиты (Ох уж эти шутники из FreeBSD - в конце примера открывается бесконечный цикл с дублированием процессом самого себя. "Малины" хватило секунд на 20 - да, наступил на грабли, не заметил шутки).
Переписан оказался и скрипт запуска сервиса - он стал проще и лаконичнее.
То, что что получилось, мне понравилось! Теперь задача потребляет только ~0.10%, а секунды на дисплее мигают в такт индикатору PPS на GLONASS - приёмнике.
В Makefile библиотеки добавил сборку первоначальной программы (та, что с простым циклом), слегка поправленной для новой библиотеки. Чтобы её попробовать, нужно набрать в каталоге библиотеки:
CODE:
make demo
./demo
Поскольку для FreeBSD прикладного ПО для GPIO, мягко сказать, не очень много, мне приятно добавить свои 2 копейки в корзинку.
Отсюда можно скачать исходные коды библиотеки tm1637 для FreeBSD и программы:
Работает "как часы".
Я тут подумал, и ...закажу-ка я, пожалуй, ещё один такой дисплей, но ностальгически жёлтого цвета и размером 0,56".
P.S.: Подтверждаю работоспособность библиотеки на Orange Pi Zero (Allwinner H2+) под управлением FreeBSD. Только поправить номера пинов - они различаются.
Комментарии
Показывать комментарии Как список | Древовидной структурой