Русский
Русский
English
Статистика
Реклама

Nodemcu

Максимально универсальный семисегментный дисплей. Часть вторая Software

28.12.2020 12:07:24 | Автор: admin
КДПВ


<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
Мне несказанно повезло и все мои модули 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 просто молча глохнет при попытках прошивки.

Конкретнее
В некоторых непонятных ситуациях при смене обычной прошивки на NodeMCU модули на ESP8266 перестают правильно инициализироваться. Это лечится или предварительной зашивкой файла esp_init_data_default.bin по адресу 0x7C000 или установкой галочки Erase Chip в NodeMCU-PyFlasher.

Процесс успешной заливки образа должен выглядеть следующим образом:


Теперь перемычку J4 можно снять, перезапустить плату и начать писать скрипты в программе ESPlorer. Я не преследую цели написать курс по программированию на lua, эта тема хорошо освещена на многих ресурсах. Лично от себя могу дать рекомендацию на блог avislab там понятным языком написана целая серия статей, в которых освещаются вопросы от азов до общения с облачными хранилищами.
Ниже приведу минимальный набор скриптов для реализации вполне себе функциональных (показывающих время!) часов, требующих только стартовой настройки подключению к сети WiFi. Часики прошли уже проверку временем, все работает отлично, не сбоит, за более чем полугода работы зависли один раз, как я понял, через проблемы с интернетом, полечились простым перезапуском.

Библиотека по работе с MAX7219 - max7219.lua

local spi_index = 1;local cs_pin = 3;-- MAX7219 SPI Master Initializationfunction 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 Outputfunction 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 intensityfunction 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 Initializationfunction 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);    endendcollectgarbage();


main cкрипт - init.lua
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    endendfunction 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    )endfunction 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;    endendrequire("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
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
cron.schedule("0 */12 * * *", function(e)  print("Every 12 hours");  sntp_sync();end)



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

Что еще?..


Теперь пара слов о других идеях. С помощью универсального семисегментного дисплея и простого lua-скрипта под NodeMCU можно буквально за час сделать настольные/настенные счетчики событий (клиенты, коммиты, факапы) или отсчитыватели времени до чего-то, будь до дедлайн или отпуск. Или считать дни без падений сервера.

Возможно несколько вариантов решения. Самый простой использовать все тот же модуль enduser_setup добавив на стартовую страницу необходимые параметры, например, инкрементировать или декрементировать число и с каким периодом.
Второй, более гибкий вариант подвязать дисплей к какой-либо странице в Интернете, откуда он будет брать актуальные данные. Этот вариант подходит для отображения курсов валют, температуры воздуха на улице или количества выздоровевших от коронавируса и любых других часто обновляемых данных.
Возможен так же вариант прямого управления дисплеем с телефона используя любую из множества программ для прямой коммуникации с esp8266 по WiFi. Такое решение будет подходящим для отображения счета в настольных играх или на спортивных событиях, например, школьного масштаба.

И конечно же, никто не запрещает подключить всевозможные датчики к esp8266 и отображать температуру, влажность или давление. Хоть уровень углекислого раза в помещение.

Как простенький пример, и как раз по случаю грядущего праздника, я запилил счетчик дней до Нового Года.





NY ждун
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    endendlocal 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();endfunction 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();


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

Буду рад почитать конструктивную критику или интересные предложения.
Всем спасибо за внимание!
И всех с наступающими праздниками!
Подробнее..

Из песочницы Как я умный аквариум делал (backend)

27.09.2020 12:08:21 | Автор: admin

image


Пролог


Работая программистом в одной из больших и успешных компаний Москвы, я не переставал совершенствовать свои навыки программирования и проходил различные курсы на платформе Udemy.
Конечно просто смотря курс и повторяя все за автором было скучновато, да и были моменты которые я не понимал ввиду своей некомпетентности на тот момент. Нужно делать свои проекты, основываясь на том, что дает автор курса подумал я, и был конечно же прав. Только настоящие трудности и их разрешение дает вам бесценный опыт, это и есть настоящая обучение.


Обучался я в основном web программированию, поскольку и работал на том же направлении. Охватывал Full-stack разработку, поскольку решил, что нужно разбираться как в серверной части, так и во фронтовой. Учил JavaScript и различные фреймворки для бека это были Express, Appolo GraphQL (поскольку на работе был именно такой стек, да и в целом хотелось попробовать что-то отличное от REST подхода), на фронте это был все тот же Apollo GQL и Vue.


И вот немного окрепнув в этой связке, завершая один из учебных проектов, я задумался, что бы сделать интересного, где можно было бы задействовать мои знания. Эта мысль меня уже давно беспокоила, конечно многие мне советовали, для того что бы получить опыт, можно сделать с нуля свой "В контакте", "The Facebook", "Instagram" и т.д. и они были правы, действительно это бы прибавило мне опыта, но такие большие проекты я боялся не вывести в одиночку и забросить его.


Как то раз мой друг решил купить себе аквариум, тогда я думал, что это глупое занятие, что толку пялится на рыб? Подумал я тогда...


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


Спустя время аквариумистика мне понравилась и прочитав кучу инфы, понял что мне хочется морской аквариум. Во-первых это красиво, настоящее море и кораллы у тебя дома. Во-вторых это сложно и бросает тебе вызов. Будет интересно подумал я.


И так почитав разные статейки я пришел к тому, что я хочу для начала попробовать так называемый "Нано риф" маленький морской аквариум от 20-50 литров, в который даже "Самп" необязательно ставить. Выяснилось, что мне нужно освещение в разных спектрах (белый, синий, зеленый, красный), при всем этом светодиоды должны светить одновременно, поэтом RGB светодиоды мне не подойдут. Освещение должно само меняться, создавая иллюзию дня и ночи. Нужен был рассвет и закат. Нужно следить за температурой. Нужно следить за химической составляющей воды. Делать ее подмены. И еще много всего. И тут я подумал, что можно какую то часть из этого автоматизировать, по крайней мере что касаемо освещения и температуры.


Еще несколько лет назад я делал несложные приспособления на платформе Arduino. Было весело и интересно, было решено сделать умный аквариум на базе этой платформы, позже я поменял саму платформу.


Не переплачивай делай сам


Выбор был сделан в пользу платы NodeMCU это такая "Ардуина" с уже встроенным WI-FI на борту (ESP 8266), что мне и нужно было, хотя у меня и была в закромах Arduino nano и сам wi-fi модуль в отдельном исполнении, но его надо было прошивать для этого и т.д. Заказал на известном сайте в поднебесной новенькую NodeMCU, пришла быстро и работа закипела.



По старинке скачал Arduino IDE настроил ее на работу с этой платой (на Windows 10, сам драйвер встал по умолчанию), и открыл пример для подключения к WI-FI. Не знаю почему, долго я мучил ее но так и не влетело мое подключение, начала гуглить. Почитав несколько статей, узнал, что на платку можно залить прошивку для некоего языка Lua(потратив усилия и время потом уже вычитал, что еще есть Micro python, но об этом позже)


Прошив плату и открыв документацию вместе с форумом, увидел примеры кода, которые шокировали даже меня, человека который нормально относится к C++ в Arduino и знающего JS и Python(немного). И там был синтаксис которого я не хотел:


init.lua


print ( "Waiting ...")tmr.register (0, 5000, tmr.ALARM_SINGLE, function (t) tmr.unregister (0); print ( "Starting ..."); dofile ( "main.lua") end)tmr.start (0)

main.lua


--WiFi Settupwifi.setmode(wifi.STATION)local cfg={}cfg.ssid="wifi_point_name"cfg.pwd="point_pass"wifi.sta.config(cfg)cfg = nilcollectgarbage()=wifi.ap.getip()

Пример для подключения к WI-FI был менее ужасным, но тем не менее, я не хотел разбираться в этих begin и end. Почитав документацию к esp-8266 узнал, что есть на ней некая прошивка с Питоном на борту. Точнее это было не просто обычный Питон, это было Micro python, некая обрезанная версия его, но все же это было лучше чем lua ИМХО. И я полез искать прошивки и инструменты


Скачиваем с сайта прошивку под нужную плату и прошиваем при помощи esptool прошиваем


pip install -g esptoolesptool.py --port COM3 --baud 460800 write_flash --flash_size=detect 0 esp8266-20191220-v1.12.bin

скачиваем специальную IDE EsPy для работы с "Микропитоном" и понеслась.


Для начала прочитал что на плату надо залить обязательных два файла, без которых ничего не поедет, а именно:


  • boot.py скрипт, который загружается первым при включении платы. Обычно в него вставляют функции для инициализации модулей, подключения к Wi-Fi и запуска WebREPL;
  • main.py основной скрипт, который запускается сразу после выполнения boot.py, в него записывается основная программа.

Далее читаю как все используют интерфейс взаимодействия WebREPL очень схоже с тем как используют ssh подключение для работы с raspberri, но он был мне не нужен, поскольку EsPy умел общаться с платой и можно было также закачивать свеженаписанный скрипт на плату без использования esptool, хотя и там не было ничего сложного. Первый шаг подключение к WI-FI засунул в скрипт самый базовый и легкий код.


boot.py


import networkimport time''' Код подключения к WiFi '''wlan_id = "my_point"wlan_pass = "strong_pass"wlan = network.WLAN(network.STA_IF)wlan.active(True)if wlan.isconnected() == False:    wlan.connect(wlan_id, wlan_pass)    while wlan.isconnected() == False:        time.sleep(3)        print("Connection Fail...")print('Device IP:', wlan.ifconfig()[0])

В файлик main.py решил добавить запуск самого приложения, код получился простым и лаконичным, в дальнейшем добавил туда создание таски для asyncio, что бы было все асинхронно(хоть и питоновские библиотеки были сыроваты для этого).


main.py


from app import app_startapp_start()

Далее наткнулся на библиотеку MicroPyServer которая была не большой (всего один файлик), и позволял на базовом уровне создать веб-сервер с роутами(библиотека была построена на сокетах). Ну что ж напишем Хэлсчек для проверки и зальем все на плату.


app.py


from micropyserver import MicroPyServerimport ujsonserver = MicroPyServer()def send(self, **kwargs):        '''            Отправляем ответ        '''        server.send(            ujson.dumps(kwargs),            content_type="Content-Type: application/json",            # Добавляем заголовки для CORS политики            extra_headers=["Access-Control-Allow-Origin: *"]        )        gc.collect()def healthcheck():    send(success=1, healthcheck='green')server.add_route("/healthcheck", healthcheck)def app_start():    server.start()

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


  • main.py
  • boot.py
  • app.py
  • micropyserver.py

Запускаем, видим что сервак локально поднялся и предлагает сходить на http://192.168.1.70/ и проверить. Идем в браузер, делаем запрос http://192.168.1.70/healthcheck, и о чудо все работает, сервер отвечает



// Json from chrome browser{    "success": 1,    "healthcheck": "green",}

Далее ждал когда приедут нужные мне hardware запчасти (датчик температуры, LED-матрицы, LCD-дисплей и т.д. ), пока ждал, принялся писать бекенд дальше, все разбил на классы и начал писать. Для начала решил написать Помошника для сервера, который бы включал в себя парсер запросов и функцию отправки, и добавил Класс для работы с датчиком температуры.


app.py


from heater import Heater# ... пропущен кодclass HttpHelper:    """        Простой парсер GET запросов    """    def __init__(self):        pass    def parse(self, request):        '''            парсер строки ответа сервера        '''        lines = request.split("\r\n")        result = {            'lines': lines,            'method': ure.search("^([A-Z]+)", lines[0]).group(1),            'path': ure.search(                "^[A-Z]+\\s+(/[-a-zA-Z0-9_.]*)", lines[0]            ).group(1),        }        param_split = ure.sub("\/([a-z]+_?)+?\?", '', lines[0].split(" ")[1])        result['params'] = self.get_params(param_split.split("&"))        return result    def get_params(self, params_as_array):        '''            создает словарь для query параметров        '''        params = {}        for element in params_as_array:            splited = element.split("=")            params[splited[0]] = splited[1]        return params    def send(self, **kwargs):        '''            Отправляем ответ        '''        server.send(            ujson.dumps(kwargs),            content_type="Content-Type: application/json",            extra_headers=["Access-Control-Allow-Origin: *"]        )        gc.collect()# ... пропущен кодdef get_water_temperature_C(request):    '''        Отдает температуру в Цельсиях    '''    try:        water_heater.get_water_tmp_C()        http_helper.send(            success=1,            water_temperature_c=water_heater.water_tmp        )    except Exception as e:        print(e)        http_helper.send(success=0, error=e)# ... пропущен кодserver.add_route("/healthcheck", healthcheck)server.add_route("/get_water_tmp", get_water_temperature_C)# ... пропущен код

heater.py


import machineimport onewireimport ds18x20HEATER_PIN = 2class Heater:    def __init__(self):        self.water_tmp = 0.00        self.heater_pin = machine.Pin(HEATER_PIN)        self.sensor = ds18x20.DS18X20(onewire.OneWire(self.heater_pin))    def get_water_tmp_C(self):        rows = self.sensor.scan()        self.sensor.convert_temp()        for rom in rows:            self.water_tmp = self.sensor.read_temp(rom)        return self.water_tmp

LED я ждал больше всего и хотелось поскорей уже их прикрутить к проекту и все проверить. Основу для размещения я взял достаточно большой корпус от видеокарты, с алюминиевым радиатором. По моим расчетам туда встанут 5 матриц:



  • белый 2 штуки
  • зеленый 1 штука
  • красный 1 штука
  • синий 1 штука

Все они питались от 32 вольт, взял блок питания для термотринтеров (24V) и повышающий преобразователь. Посоветовавшись со знающим другом, принял решение подключать все их через микросхему, которая называется в простонародье "составной транзистор Дарлингтона", понравилось, что все на одной небольшой микросхеме и не нужно париться с радиаторами охлаждения, если бы я выбрал биполярные транзисторы. Все приехало, все спаял и прикрутил к радиатору. Светодиоды не стал промазывать термо-пастой, так как знал, что на все 100% они не будут гореть и тепло будет хорошо отводится и так. Получилось все конечно не на продажу, но в целом меня внешний вид пока устраивал.


Написал класс для них, и добавил роуты для работы через API.


Прицепил еще LCD дисплей, что бы видеть на каком IP стартанул сервер, поскольку на тот момент еще не было реализовано статичный ip для этого. Ну и после этого пошел писать frontend для того, что бы можно было с любого устройства смотреть инфу и управлять аквариумом.



Эпилог


В целом получил хороший опыт в разработке IOT устройства, работа над которым еще не завершена и будет продолжаться. В процессе пришлось немного подкорректировать работу библиотеки MicroPyServer, а именно объем передаваемых данных в сокете. Поскольку я пришел к тому, что при нескольких запросах в течении небольшого промежутка, память просто заканчивалась и контроллер падал с ошибкой, пока не придумал как ее можно отловить в try except, но это надо будет сделать.


micropyserver.py


# ... пропущенный кодdef _get_request(self):        """ Return request body """        # было выставлено 4096 , при этом быстро возникает MemoryError        return str(self._connect.recv(1024), "utf8")

В планах:


  • Автоматизировать работу с освещение, что бы он сам проверял саму освещенность в комнате + создавал эффект заката и рассвета, а ночью лунный свет.
  • Автоматизировать анализ воды
  • Автоматизировать нагрев воды
  • Автоматизировать помпу течения
  • Автокормушка
  • Автодолив
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru