[Схемотехника, DIY или Сделай сам, Электроника для начинающих] Максимально универсальный семисегментный дисплей. Часть вторая — Software
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
<irony>
Не прошло и полугода… Но зато конструкция прошла проверку временем!
</irony>
В продолжение первой части о проектировании максимально универсального семисегментного дисплея сделаем на получившихся модулях первое, что приходит в голову — конечно же часы! Так что это очередная статья про очередные часы. Без кнопок, на ESP8266, на NodeMCU и Lua. Кому до сих пор интересно — прошу под кат.
Кусочек hardware
Для создания часов требуется четырехразрядный индикатор (или шести, если отображать еще и секунды). Так как часы планируются полностью автономными настенными я решил делать их из двух модулей по два трехдюймовых индикатора. В наличии такие были красные с общим анодом, так что устанавливаем элементы master-платы согласно первой части статьи, для slave-платы устанавливает только боковой разъём и индикаторы. Соединяем вместе и вперед программировать!
Стартуем с NodeMCU
Писать на arduino-вых скетчах мне не позволяет религия, извините, а bare-metal прошивка под ESP8266 для данной задачи это явно перебор. Так что выбор вполне логично пал на NodeMCU и скриптовый язык lua. Вкратце, что такое NodeMCU — это открытый бесплатный проект на основе lua, имеющий отличную гибкость и достаточную мощность, что позволяет быстро и эффективно создавать разнообразные проекты. NodeMCU — модульная прошивка, а это значит, что можно собрать вариант конкретно под свой проект без лишних модулей. Благодаря обширной комьюнити NodeMCU уже умеет работать с разными протоколами обмена данных поверх WiFi (HTTP, MQTT, JSON, CoAP), периферией, с несколькими десятками популярных датчиков, с дисплеями, и даже умеет в файловую систему FatFS.
Для того, чтобы собрать прошивку под свой проект переходим на сайт www.nodemcu-build.com, вводим свою электронную почту, отмечаем галочками нужные модули и жмем Start your build.
Shit happens
SPL
Мне несказанно «повезло» и все мои модули ESP-07 оказались с флешем 512кБ на борту. Хотя по документации, описанию на сайте продавца и фото в интернете должно быть 1Мб. В связи с чем я целый вечер искал причину, почему модуль или не шьется вовсе или шлёт мусор в СОМ-порт при включении неистово мигая синим светодиодом. Оказалось master branch NodeMCU требует от 1 Мб флеша. Для таких же счастливчиков, как я нужно поставить галочку на сайте рядом с branch-ем версии 1.5.4.1 — это финальная версия, которая работает с 512кБ.
Для часов нам потребуется минималистичный набор модулей:
wifi — окно во внешний мир
enduser_setup — удобный интерфейс для подключения к сети WiFi
file — проект будет состоять из разных файлов, нужно уметь с ними работать
gpio — дергать ножками
net — модуль сетевого клиента
rtctime — часы реального времени
sntp — синхронизация часов по сети, кнопок то нет
spi — интерфейс для MAX7219
tmr — таймеры
Отметили, нажали на большую синюю кнопку и ждем пару минут, пока на почту упадет ссылка на готовый бинарный образ для заливки в контроллер. Система просто отличная.
Для заливки образа, как и для сохранения lua-скриптов используется UART. Для подключения внешнего адаптера USB-to-UART (3.3V!) используется разъём J3 — UART. Как упоминалось в первой части, на плате присутствует посадочное место под преобразователь CH340. В случае его использования все общение с контроллером (и питание платы) будет производится через порт USB на плате. Удобно если проект требует частых изменений или длительного процесса разработки программы. Для переключения в режим записи во флеш нужно предварительно установить на плате перемычку J4. Скорость UART — 115200 бод, номер правильного СОМ порта оставляю на вас.
Для прошивки образа рекомендую утилиту NodeMCU-PyFlasher. Возможно, она покажется не такой простой как популярная NodeMCU-Flasher, но является более универсальной и помогает в ситуациях, когда NodeMCU-Flasher просто молча глохнет при попытках прошивки.
Конкретнее
SPL
В некоторых непонятных ситуациях при смене обычной прошивки на NodeMCU модули на ESP8266 перестают правильно инициализироваться. Это лечится или предварительной зашивкой файла esp_init_data_default.bin по адресу 0x7C000 или установкой галочки Erase Chip в NodeMCU-PyFlasher.
Процесс успешной заливки образа должен выглядеть следующим образом:
Теперь перемычку J4 можно снять, перезапустить плату и начать писать скрипты в программе ESPlorer. Я не преследую цели написать курс по программированию на lua, эта тема хорошо освещена на многих ресурсах. Лично от себя могу дать рекомендацию на блог avislab — там понятным языком написана целая серия статей, в которых освещаются вопросы от азов до общения с облачными хранилищами.
Ниже приведу минимальный набор скриптов для реализации вполне себе функциональных (показывающих время!) часов, требующих только стартовой настройки — подключению к сети WiFi. Часики прошли уже проверку временем, все работает отлично, не сбоит, за более чем полугода работы зависли один раз, как я понял, через проблемы с интернетом, полечились простым перезапуском.
Библиотека по работе с MAX7219 - max7219.lua
SPL
local spi_index = 1;
local cs_pin = 3;
-- MAX7219 SPI Master Initialization
function max7219_spi_init()
print('SPI init');
spi.setup(spi_index, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 16, 80, spi.HALFDUPLEX);
gpio.mode(cs_pin, gpio.OUTPUT, gpio.PULLUP);
gpio.write(cs_pin, gpio.HIGH);
end
-- MAX7219 Output
function max7219_output(digit, value)
local data = digit*256 + value;
gpio.write(cs_pin, gpio.LOW);
spi.send(spi_index, data);
gpio.write(cs_pin, gpio.HIGH);
end
-- MAX7219 set intensity
function max7219_intensity(value)
local data = 0x0A00 + value;
gpio.write(cs_pin, gpio.LOW);
spi.send(spi_index, data);
gpio.write(cs_pin, gpio.HIGH);
end
-- MAX7219 Initialization
function max7219_init(digits, intensity)
print(string.format("MAX7219 init for %d digits", digits));
gpio.write(cs_pin, gpio.LOW);
-- Display test mode off
spi.send(spi_index, 0x0F00);
gpio.write(cs_pin, gpio.HIGH);
gpio.write(cs_pin, gpio.LOW);
-- Normal Operation mode
spi.send(spi_index, 0x0C01);
gpio.write(cs_pin, gpio.HIGH);
gpio.write(cs_pin, gpio.LOW);
-- Intensity duty cycle
-- [min 0x0A00 .. 0x0A0F max]
spi.send(spi_index, 0x0A00 + intensity);
gpio.write(cs_pin, gpio.HIGH);
gpio.write(cs_pin, gpio.LOW);
-- Decode-Mode
-- [0 - no decode, 1 - B-Code mode]
spi.send(spi_index, 0x09FF);
gpio.write(cs_pin, gpio.HIGH);
gpio.write(cs_pin, gpio.LOW);
-- Scan-Limit Register Format
spi.send(spi_index, 0x0B04);
gpio.write(cs_pin, gpio.HIGH);
-- Set blank as default
for d=0, digits do
max7219_output(d, 0x0F);
end
end
collectgarbage();
main cкрипт - init.lua
SPL
local point = 0;
local time_zone = 3;
local sntp_cnt = 1;
local cur_intensity = 0x0F;
function timer_do()
tm = rtctime.epoch2cal(rtctime.get());
if point == 0 then point = 1; else point = 0; end;
max7219_intensity(cur_intensity);
max7219_output(5, tm["min"]%10);
max7219_output(4, tm["min"]/10);
max7219_output(2, tm["hour"]%10 + (128*point));
max7219_output(1, tm["hour"]/10);
if tm["hour"] <= 7 then
-- from 0 to 8
cur_intensity = 0x01;
else
if tm["hour"] <= 18 then
-- from 8 to 19
cur_intensity = 0x0F;
else
if tm["hour"] <= 22 then
-- from 19 to 22
cur_intensity = 0x05;
else
-- from 23 to 24
cur_intensity = 0x01;
end
end
end
end
function sntp_sync()
print ("SNTP sync");
sntp.sync("194.54.161.214",
function(sec, usec, server, info)
rtctime.set(sec + 3600*time_zone)
tm = rtctime.epoch2cal(rtctime.get());
print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]));
sntp_cnt = 4320;
end,
function(err, str)
print("Nope...")
end
)
end
function timer_sntp()
if sntp_cnt > 0 then
sntp_cnt = sntp_cnt - 1;
else
if wifi.sta.status() == wifi.STA_GOTIP then
print("Connected to WiFi as:" .. wifi.sta.getip());
sntp_cnt = 6;
sntp_sync();
else
print("No WiFi");
end;
end
end
require("max7219");
max7219_spi_init();
max7219_init(5, cur_intensity);
rtctime.set(1577872800 + 3600*time_zone);
tm = rtctime.epoch2cal(rtctime.get());
print(string.format("%02d:%02d:%02d", tm["hour"], tm["min"], tm["sec"]));
enduser_setup.start(
function()
print("Connected to WiFi as:" .. wifi.sta.getip())
sntp_sync();
end,
function(err, str)
print("enduser_setup: Err #" .. err .. ": " .. str)
end
);
local mytimer = tmr.create();
mytimer:register(500, tmr.ALARM_AUTO, timer_do);
mytimer:start()
local sntp_timer = tmr.create();
sntp_timer:register(10000, tmr.ALARM_AUTO, timer_sntp);
sntp_timer:start()
collectgarbage();
Файл для шаринга параметров enduser_setup - enduser_setup.lua
SPL
local p = {}
p.wifi_ssid="ssid"
p.wifi_password="password"
-- your own parameters:
p.utc_zone="xxx"
return p
Во флеш контроллера также нужно залить страницу enduser_setup.html с интерфейсом подключения к сети WiFi.
Несмотря на такой компактный скрипт часы действительно получаются функционально законченными. Реализован следующий сценарий: при включении, на основе enduser_setup модуля создаётся открытая WiFi-точка с названием SetupGaget_xxx.
При подключении к которой и попытке перейти по какому-либо адресу (или просто по 192.168.4.1) открывается интерфейс подключения к доступным сетям.
Такая себе landing-page, куда нужно ввести название сети и пароль. Можно ввести вручную или выбрать из списка доступных. При нажатии на кнопку контроллер пытается подключится к выбранной сети и в случае успеха выводит радостное сообщение и отключает WiFi-точку. Дополнительно я добавил на страницу настройку часового пояса.
После подключения к Интернету часы синхронизируются с сервером точного времени по протоколу SNTP и начинают тихо выполнять свою основную функцию — отображать время на дисплее, помигивая точкой второго разряда.
Буквально в несколько строчек можно добавить периодическую синхронизацию времени и изменение яркости в зависимости от времени суток. Если вы счастливый обладатель модулей с 512кБ памяти придется писать проверками, как в коде выше, если же есть возможность использовать master branch версию — рекомендую использовать модуль простого планировщика событий cron.
Аналогично и с функцией изменения яркости дисплея, которая выше также реализована на банальных проверках.
cron
SPL
cron.schedule("0 */12 * * *", function(e)
print("Every 12 hours");
sntp_sync();
end)
Сразу прошу прощения за фото, съемка ярких светодиодных индикаторов оказалась той еще задачей, даже при хорошем фронтальном освещении картинка выглядит не очень. В жизни часы выглядят яркими, равномерными и вокруг солнечный день.
Что еще?..
Теперь пара слов о других идеях. С помощью универсального семисегментного дисплея и простого lua-скрипта под NodeMCU можно буквально за час сделать настольные/настенные счетчики событий (клиенты, коммиты, факапы) или отсчитыватели времени до чего-то, будь до дедлайн или отпуск. Или считать дни без падений сервера.
Возможно несколько вариантов решения. Самый простой — использовать все тот же модуль enduser_setup добавив на стартовую страницу необходимые параметры, например, инкрементировать или декрементировать число и с каким периодом.
Второй, более гибкий вариант — подвязать дисплей к какой-либо странице в Интернете, откуда он будет брать актуальные данные. Этот вариант подходит для отображения курсов валют, температуры воздуха на улице или количества выздоровевших от коронавируса и любых других часто обновляемых данных.
Возможен так же вариант прямого управления дисплеем с телефона используя любую из множества программ для прямой коммуникации с esp8266 по WiFi. Такое решение будет подходящим для отображения счета в настольных играх или на спортивных событиях, например, школьного масштаба.
И конечно же, никто не запрещает подключить всевозможные датчики к esp8266 и отображать температуру, влажность или давление. Хоть уровень углекислого раза в помещение.
Как простенький пример, и как раз по случаю грядущего праздника, я запилил счетчик дней до Нового Года.
NY ждун
SPL
local time_zone = 3;
local sntp_cnt = 1;
local cur_intensity = 0x0F;
local days = 189;
function print_days()
max7219_intensity(cur_intensity);
max7219_output(3, days%10);
max7219_output(2, (days%100)/10);
max7219_output(1, days/100);
if tm["hour"] <= 7 then
-- from 0 to 8
cur_intensity = 0x01;
else
if tm["hour"] <= 18 then
-- from 8 to 19
cur_intensity = 0x0F;
else
if tm["hour"] <= 22 then
-- from 19 to 22
cur_intensity = 0x05;
else
-- from 23 to 24
cur_intensity = 0x01;
end
end
end
end
local dpm = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
function days_till_ny()
tm = rtctime.epoch2cal(rtctime.get());
days = dpm[tm["mon"]-1] - tm["day"];
if (tm["year"]%4) and (tm["mon"]<=2) then days = days - 1; end;
local month = tm["mon"];
while(month < 12)
do
days = days + dpm[month];
month = month + 1;
end;
print_days();
end
function sntp_sync()
if wifi.sta.status() == wifi.STA_GOTIP then
print("Connected to WiFi as:" .. wifi.sta.getip());
print ("SNTP sync");
sntp.sync("194.54.161.214",
function(sec, usec, server, info)
rtctime.set(sec + 3600*time_zone)
tm = rtctime.epoch2cal(rtctime.get());
print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]));
days_till_ny();
end,
function(err, str)
print("Nope...")
end
);
else
print("No WiFi");
end;
end;
require("max7219");
max7219_spi_init();
max7219_init(3, cur_intensity);
rtctime.set(1577872800 + 3600*time_zone);
tm = rtctime.epoch2cal(rtctime.get());
print(string.format("%02d:%02d:%02d", tm["hour"], tm["min"], tm["sec"]));
enduser_setup.start(
function()
sntp_sync()
end,
function(err, str)
print("enduser_setup: Err #" .. err .. ": " .. str)
end
)
cron.schedule("0 */12 * * *", function(e)
print("Every 12 hours");
sntp_sync();
end)
collectgarbage();
Идей, как и вариантов их воплощения, великое множество. Наличие на борту контроллера с подключением к сети Интернет, модульная конструкция и возможность установки разного количества индикаторов разного размера и цветов открывает целое поле для полета фантазии. Вот такой вот универсальный индикатор получился.
Буду рад почитать конструктивную критику или интересные предложения.
Всем спасибо за внимание!
И всех с наступающими праздниками!
===========
Источник:
habr.com
===========
Похожие новости:
- [Управление разработкой, Управление проектами, Фриланс, Производство и разработка электроники, Электроника для начинающих] Как разработать корпус силами фрилансеров — промдизайнеров и конструкторов
- [PHP, Symfony, MongoDB, Разработка под Arduino] Использование Shopker для IOT
- [3D-принтеры, DIY или Сделай сам] Я хотел купить недорогой 3D-принтер, но посмотрел YouTube и расхотел
- [Системное администрирование, DIY или Сделай сам] Hotspot для бизнеса своими руками
- [Open source, Алгоритмы, Lua, Параллельное программирование] Такие важные короткоживущие данные
- [Реверс-инжиниринг, Программирование микроконтроллеров, Прототипирование, Интернет вещей, DIY или Сделай сам] Подключаемся к станку по изготовлению профлиста и считываем из него прокатную длинну
- [Анализ и проектирование систем, CAD/CAM, Производство и разработка электроники, Электроника для начинающих] Анализ целостности сигналов в PADS Professional (5/6)
- [Научно-популярное, DIY или Сделай сам, Лайфхаки для гиков, Химия] Малышка на миллион. Сковиллей
- [Разработка систем связи, Схемотехника, DIY или Сделай сам, Звук] Радиоприемник прямого усиления на СВ, 2020 год, Москва. Что можно услышать?
- [API, Lua, Умный дом, Звук] Роутер Микротик управляет радиотрансляцией и озвучивает Умный дом
Теги для поиска: #_shemotehnika (Схемотехника), #_diy_ili_sdelaj_sam (DIY или Сделай сам), #_elektronika_dlja_nachinajuschih (Электроника для начинающих), #_diy_ili_sdelaj_sam (diy или сделай сам), #_elektronika_dlja_nachinajuschih (электроника для начинающих), #_semisegmentnyj_indikator (семисегментный индикатор), #_esp8266, #_lua, #_nodemcu, #_shemotehnika (
Схемотехника
), #_diy_ili_sdelaj_sam (
DIY или Сделай сам
), #_elektronika_dlja_nachinajuschih (
Электроника для начинающих
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:49
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
<irony> Не прошло и полугода… Но зато конструкция прошла проверку временем! </irony> В продолжение первой части о проектировании максимально универсального семисегментного дисплея сделаем на получившихся модулях первое, что приходит в голову — конечно же часы! Так что это очередная статья про очередные часы. Без кнопок, на ESP8266, на NodeMCU и Lua. Кому до сих пор интересно — прошу под кат. Кусочек hardware Для создания часов требуется четырехразрядный индикатор (или шести, если отображать еще и секунды). Так как часы планируются полностью автономными настенными я решил делать их из двух модулей по два трехдюймовых индикатора. В наличии такие были красные с общим анодом, так что устанавливаем элементы master-платы согласно первой части статьи, для slave-платы устанавливает только боковой разъём и индикаторы. Соединяем вместе и вперед программировать! Стартуем с NodeMCU Писать на arduino-вых скетчах мне не позволяет религия, извините, а bare-metal прошивка под ESP8266 для данной задачи это явно перебор. Так что выбор вполне логично пал на NodeMCU и скриптовый язык lua. Вкратце, что такое NodeMCU — это открытый бесплатный проект на основе lua, имеющий отличную гибкость и достаточную мощность, что позволяет быстро и эффективно создавать разнообразные проекты. NodeMCU — модульная прошивка, а это значит, что можно собрать вариант конкретно под свой проект без лишних модулей. Благодаря обширной комьюнити NodeMCU уже умеет работать с разными протоколами обмена данных поверх WiFi (HTTP, MQTT, JSON, CoAP), периферией, с несколькими десятками популярных датчиков, с дисплеями, и даже умеет в файловую систему FatFS. Для того, чтобы собрать прошивку под свой проект переходим на сайт www.nodemcu-build.com, вводим свою электронную почту, отмечаем галочками нужные модули и жмем Start your build. Shit happensSPLМне несказанно «повезло» и все мои модули ESP-07 оказались с флешем 512кБ на борту. Хотя по документации, описанию на сайте продавца и фото в интернете должно быть 1Мб. В связи с чем я целый вечер искал причину, почему модуль или не шьется вовсе или шлёт мусор в СОМ-порт при включении неистово мигая синим светодиодом. Оказалось master branch NodeMCU требует от 1 Мб флеша. Для таких же счастливчиков, как я нужно поставить галочку на сайте рядом с branch-ем версии 1.5.4.1 — это финальная версия, которая работает с 512кБ.
Для часов нам потребуется минималистичный набор модулей: wifi — окно во внешний мир enduser_setup — удобный интерфейс для подключения к сети WiFi file — проект будет состоять из разных файлов, нужно уметь с ними работать gpio — дергать ножками net — модуль сетевого клиента rtctime — часы реального времени sntp — синхронизация часов по сети, кнопок то нет spi — интерфейс для MAX7219 tmr — таймеры Отметили, нажали на большую синюю кнопку и ждем пару минут, пока на почту упадет ссылка на готовый бинарный образ для заливки в контроллер. Система просто отличная. Для заливки образа, как и для сохранения lua-скриптов используется UART. Для подключения внешнего адаптера USB-to-UART (3.3V!) используется разъём J3 — UART. Как упоминалось в первой части, на плате присутствует посадочное место под преобразователь CH340. В случае его использования все общение с контроллером (и питание платы) будет производится через порт USB на плате. Удобно если проект требует частых изменений или длительного процесса разработки программы. Для переключения в режим записи во флеш нужно предварительно установить на плате перемычку J4. Скорость UART — 115200 бод, номер правильного СОМ порта оставляю на вас. Для прошивки образа рекомендую утилиту NodeMCU-PyFlasher. Возможно, она покажется не такой простой как популярная NodeMCU-Flasher, но является более универсальной и помогает в ситуациях, когда NodeMCU-Flasher просто молча глохнет при попытках прошивки. КонкретнееSPLВ некоторых непонятных ситуациях при смене обычной прошивки на NodeMCU модули на ESP8266 перестают правильно инициализироваться. Это лечится или предварительной зашивкой файла esp_init_data_default.bin по адресу 0x7C000 или установкой галочки Erase Chip в NodeMCU-PyFlasher.
Процесс успешной заливки образа должен выглядеть следующим образом: Теперь перемычку J4 можно снять, перезапустить плату и начать писать скрипты в программе ESPlorer. Я не преследую цели написать курс по программированию на lua, эта тема хорошо освещена на многих ресурсах. Лично от себя могу дать рекомендацию на блог avislab — там понятным языком написана целая серия статей, в которых освещаются вопросы от азов до общения с облачными хранилищами. Ниже приведу минимальный набор скриптов для реализации вполне себе функциональных (показывающих время!) часов, требующих только стартовой настройки — подключению к сети WiFi. Часики прошли уже проверку временем, все работает отлично, не сбоит, за более чем полугода работы зависли один раз, как я понял, через проблемы с интернетом, полечились простым перезапуском. Библиотека по работе с MAX7219 - max7219.luaSPLlocal spi_index = 1;
local cs_pin = 3; -- MAX7219 SPI Master Initialization function max7219_spi_init() print('SPI init'); spi.setup(spi_index, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 16, 80, spi.HALFDUPLEX); gpio.mode(cs_pin, gpio.OUTPUT, gpio.PULLUP); gpio.write(cs_pin, gpio.HIGH); end -- MAX7219 Output function max7219_output(digit, value) local data = digit*256 + value; gpio.write(cs_pin, gpio.LOW); spi.send(spi_index, data); gpio.write(cs_pin, gpio.HIGH); end -- MAX7219 set intensity function max7219_intensity(value) local data = 0x0A00 + value; gpio.write(cs_pin, gpio.LOW); spi.send(spi_index, data); gpio.write(cs_pin, gpio.HIGH); end -- MAX7219 Initialization function max7219_init(digits, intensity) print(string.format("MAX7219 init for %d digits", digits)); gpio.write(cs_pin, gpio.LOW); -- Display test mode off spi.send(spi_index, 0x0F00); gpio.write(cs_pin, gpio.HIGH); gpio.write(cs_pin, gpio.LOW); -- Normal Operation mode spi.send(spi_index, 0x0C01); gpio.write(cs_pin, gpio.HIGH); gpio.write(cs_pin, gpio.LOW); -- Intensity duty cycle -- [min 0x0A00 .. 0x0A0F max] spi.send(spi_index, 0x0A00 + intensity); gpio.write(cs_pin, gpio.HIGH); gpio.write(cs_pin, gpio.LOW); -- Decode-Mode -- [0 - no decode, 1 - B-Code mode] spi.send(spi_index, 0x09FF); gpio.write(cs_pin, gpio.HIGH); gpio.write(cs_pin, gpio.LOW); -- Scan-Limit Register Format spi.send(spi_index, 0x0B04); gpio.write(cs_pin, gpio.HIGH); -- Set blank as default for d=0, digits do max7219_output(d, 0x0F); end end collectgarbage(); main cкрипт - init.luaSPLlocal point = 0;
local time_zone = 3; local sntp_cnt = 1; local cur_intensity = 0x0F; function timer_do() tm = rtctime.epoch2cal(rtctime.get()); if point == 0 then point = 1; else point = 0; end; max7219_intensity(cur_intensity); max7219_output(5, tm["min"]%10); max7219_output(4, tm["min"]/10); max7219_output(2, tm["hour"]%10 + (128*point)); max7219_output(1, tm["hour"]/10); if tm["hour"] <= 7 then -- from 0 to 8 cur_intensity = 0x01; else if tm["hour"] <= 18 then -- from 8 to 19 cur_intensity = 0x0F; else if tm["hour"] <= 22 then -- from 19 to 22 cur_intensity = 0x05; else -- from 23 to 24 cur_intensity = 0x01; end end end end function sntp_sync() print ("SNTP sync"); sntp.sync("194.54.161.214", function(sec, usec, server, info) rtctime.set(sec + 3600*time_zone) tm = rtctime.epoch2cal(rtctime.get()); print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"])); sntp_cnt = 4320; end, function(err, str) print("Nope...") end ) end function timer_sntp() if sntp_cnt > 0 then sntp_cnt = sntp_cnt - 1; else if wifi.sta.status() == wifi.STA_GOTIP then print("Connected to WiFi as:" .. wifi.sta.getip()); sntp_cnt = 6; sntp_sync(); else print("No WiFi"); end; end end require("max7219"); max7219_spi_init(); max7219_init(5, cur_intensity); rtctime.set(1577872800 + 3600*time_zone); tm = rtctime.epoch2cal(rtctime.get()); print(string.format("%02d:%02d:%02d", tm["hour"], tm["min"], tm["sec"])); enduser_setup.start( function() print("Connected to WiFi as:" .. wifi.sta.getip()) sntp_sync(); end, function(err, str) print("enduser_setup: Err #" .. err .. ": " .. str) end ); local mytimer = tmr.create(); mytimer:register(500, tmr.ALARM_AUTO, timer_do); mytimer:start() local sntp_timer = tmr.create(); sntp_timer:register(10000, tmr.ALARM_AUTO, timer_sntp); sntp_timer:start() collectgarbage(); Файл для шаринга параметров enduser_setup - enduser_setup.luaSPLlocal p = {}
p.wifi_ssid="ssid" p.wifi_password="password" -- your own parameters: p.utc_zone="xxx" return p Во флеш контроллера также нужно залить страницу enduser_setup.html с интерфейсом подключения к сети WiFi. Несмотря на такой компактный скрипт часы действительно получаются функционально законченными. Реализован следующий сценарий: при включении, на основе enduser_setup модуля создаётся открытая WiFi-точка с названием SetupGaget_xxx. При подключении к которой и попытке перейти по какому-либо адресу (или просто по 192.168.4.1) открывается интерфейс подключения к доступным сетям. Такая себе landing-page, куда нужно ввести название сети и пароль. Можно ввести вручную или выбрать из списка доступных. При нажатии на кнопку контроллер пытается подключится к выбранной сети и в случае успеха выводит радостное сообщение и отключает WiFi-точку. Дополнительно я добавил на страницу настройку часового пояса. После подключения к Интернету часы синхронизируются с сервером точного времени по протоколу SNTP и начинают тихо выполнять свою основную функцию — отображать время на дисплее, помигивая точкой второго разряда. Буквально в несколько строчек можно добавить периодическую синхронизацию времени и изменение яркости в зависимости от времени суток. Если вы счастливый обладатель модулей с 512кБ памяти придется писать проверками, как в коде выше, если же есть возможность использовать master branch версию — рекомендую использовать модуль простого планировщика событий cron. Аналогично и с функцией изменения яркости дисплея, которая выше также реализована на банальных проверках. cronSPLcron.schedule("0 */12 * * *", function(e)
print("Every 12 hours"); sntp_sync(); end) Сразу прошу прощения за фото, съемка ярких светодиодных индикаторов оказалась той еще задачей, даже при хорошем фронтальном освещении картинка выглядит не очень. В жизни часы выглядят яркими, равномерными и вокруг солнечный день. Что еще?.. Теперь пара слов о других идеях. С помощью универсального семисегментного дисплея и простого lua-скрипта под NodeMCU можно буквально за час сделать настольные/настенные счетчики событий (клиенты, коммиты, факапы) или отсчитыватели времени до чего-то, будь до дедлайн или отпуск. Или считать дни без падений сервера. Возможно несколько вариантов решения. Самый простой — использовать все тот же модуль enduser_setup добавив на стартовую страницу необходимые параметры, например, инкрементировать или декрементировать число и с каким периодом. Второй, более гибкий вариант — подвязать дисплей к какой-либо странице в Интернете, откуда он будет брать актуальные данные. Этот вариант подходит для отображения курсов валют, температуры воздуха на улице или количества выздоровевших от коронавируса и любых других часто обновляемых данных. Возможен так же вариант прямого управления дисплеем с телефона используя любую из множества программ для прямой коммуникации с esp8266 по WiFi. Такое решение будет подходящим для отображения счета в настольных играх или на спортивных событиях, например, школьного масштаба. И конечно же, никто не запрещает подключить всевозможные датчики к esp8266 и отображать температуру, влажность или давление. Хоть уровень углекислого раза в помещение. Как простенький пример, и как раз по случаю грядущего праздника, я запилил счетчик дней до Нового Года. NY ждунSPLlocal time_zone = 3;
local sntp_cnt = 1; local cur_intensity = 0x0F; local days = 189; function print_days() max7219_intensity(cur_intensity); max7219_output(3, days%10); max7219_output(2, (days%100)/10); max7219_output(1, days/100); if tm["hour"] <= 7 then -- from 0 to 8 cur_intensity = 0x01; else if tm["hour"] <= 18 then -- from 8 to 19 cur_intensity = 0x0F; else if tm["hour"] <= 22 then -- from 19 to 22 cur_intensity = 0x05; else -- from 23 to 24 cur_intensity = 0x01; end end end end local dpm = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; function days_till_ny() tm = rtctime.epoch2cal(rtctime.get()); days = dpm[tm["mon"]-1] - tm["day"]; if (tm["year"]%4) and (tm["mon"]<=2) then days = days - 1; end; local month = tm["mon"]; while(month < 12) do days = days + dpm[month]; month = month + 1; end; print_days(); end function sntp_sync() if wifi.sta.status() == wifi.STA_GOTIP then print("Connected to WiFi as:" .. wifi.sta.getip()); print ("SNTP sync"); sntp.sync("194.54.161.214", function(sec, usec, server, info) rtctime.set(sec + 3600*time_zone) tm = rtctime.epoch2cal(rtctime.get()); print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"])); days_till_ny(); end, function(err, str) print("Nope...") end ); else print("No WiFi"); end; end; require("max7219"); max7219_spi_init(); max7219_init(3, cur_intensity); rtctime.set(1577872800 + 3600*time_zone); tm = rtctime.epoch2cal(rtctime.get()); print(string.format("%02d:%02d:%02d", tm["hour"], tm["min"], tm["sec"])); enduser_setup.start( function() sntp_sync() end, function(err, str) print("enduser_setup: Err #" .. err .. ": " .. str) end ) cron.schedule("0 */12 * * *", function(e) print("Every 12 hours"); sntp_sync(); end) collectgarbage(); Идей, как и вариантов их воплощения, великое множество. Наличие на борту контроллера с подключением к сети Интернет, модульная конструкция и возможность установки разного количества индикаторов разного размера и цветов открывает целое поле для полета фантазии. Вот такой вот универсальный индикатор получился. Буду рад почитать конструктивную критику или интересные предложения. Всем спасибо за внимание! И всех с наступающими праздниками! =========== Источник: habr.com =========== Похожие новости:
Схемотехника ), #_diy_ili_sdelaj_sam ( DIY или Сделай сам ), #_elektronika_dlja_nachinajuschih ( Электроника для начинающих ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:49
Часовой пояс: UTC + 5