Ребенок у меня поклонник "очень странных дел" и под выход нового сезона решил сделать небольшую инсталляцию для лучшего погружения в атмосферу изнанки.
Заказал удобные модули на чипе ws2811, но через месяц доставки, понял, что привоз от 24 ноября до 14 декабря, это точно до 14 декабря.
Пришлось нарезать ленту, которая валялась дома с такими же модулями и припаять к ним витую пару (нужно три провода с каждой стороны модуля). Паял и чувствовал себя как в анекдоте курить паять пиздец люблю.
26 букв. 156 раз залудить😅
Уже после сборки решил подключить простенький пульт инфракрасный и прописать немного команд, чтобы с Уиллом можно было пообщаться. Типа «да», «нет», «беги» и тд. И обычный режим, когда фразы через рандомойзер.
Run
Колхозной гирлянде, колхозный блок управления) На плате ESP
Нет, это не айти, это режим просмотра «оно».
По факту такое рукоделие оценил больше всех я сам😅
Добавление в среду разработки редактора для рисования графических LD функциональных блоков.
Интересно мнение специалистов по АСУ ТП. Будет ли полезна функция графического оформления пользователем LD/FBD блоков внутри лестничных диаграмм? Добавил полноценный редактор рисования блоков, переменных , а так же их анимация. Например к фигуре : текст, линия, полигон... -идет привязка к переменной и ее визуальное изменение в зависимости от значения (появляется\исчезает, меняет цвет, вертится, перемещается и т.п).
Но если с анимацией - все понятно, с этим и SCADA может разобраться по морганиям и перемещениям. То будет ли полезным рисовать LD блоки для удобного чтения схем? Насколько знаю Siemens и Codesys не предлагают такого, у них все элементы/ функциональные блоки в LD одинаковы на вид и размерам (ваш опыт, как это читается если программа состоит из тысяч таких LD). Добавил возможность полностью создавать свои LD любого вида, любого размера, задавать его поведение кодом, и внедрять в цепи LD.
Мой друг недавно загорелся идеей собрать себе WordClock — часы, где время отображается не цифрами, а словами. Он нашёл проект в интернете, попросил меня помочь с электрикой. Он шарит в моделировании и имеет какой-то крутой 3d-принтер, но схемотехника для него дремучий лес.
Прототип, проекта из сети. Первое включение.
Я, как и положено зануде, посмотрел на схему, поковырял код... и честно сказал:
"Ну, такое. Схема мне не нравится, код... страшно открыть. Короче, давай я лучше сам спроектирую— с блэкджеком и микроконтроллером".
Так я и начал делать свой прототип WordClock'ов. Пока что всё довольно грубо, но уже работает в эмуляторе — показывает время словами с помощью адресной ленты и микроконтроллера.
Лучше свой кривой код, чем чужой кривой код )))
Проект на стадии «пишу код, рисую схему», и я думаю сделать пост (или серию) с:
качественным дизайном, без соплей из термоклея и пауком из проводов,
рассуждением по коду и логике,
и вообще рассказать, как сделать такую штуку самому, чтобы сборка была простой, в удовольствие.
Но перед тем как писать текст, снимать фото и рисовать схемы — хотел бы узнать, такой контент здесь интересен? Я уже публиковал здесь несколько DIY статей, реакция была разной. В этот раз решил поинтересоваться заранее)
Если здесь такое интересно, сделаю нормальный пост с фотками, пайкой, фейлами и не совсем.
Для тех кто дочитал, небольшое видео с тестовым запуском чужого проекта
Пару лет назад я наткнулся на один крутой проект: ребята взяли легендарную Pong от Atari и сделали её физическую версию.
Всё выглядело максимально весело: реальные "ракетки", мячик, механика — короче, чистый кайф. Раньше они даже продавали наборы для сборки, но как у них дела сейчас — без понятия. Я погряз в собственной попытке воплотить нечто подобное.
Как раз в это время мне пришлось задуматься о проекте для колледжа, так что решение пришло в голову моментально: я сделаю свою версию.
Мне вообще не понравился размер и то, как исключались игроки из игры (натягивание ленты в пазы, они даже не захотели добавить это в превью).
Разрешили работать в группе над проектом в третьем семестре, так что я воспользовался возможностью взять двух неопытных помощников (я-то прям опытный, ахахахаха).
Pong² — так я решил назвать сие творение.
С самого начала я решил: никаких готовых решений — только ручная работа, самодельные платы, собственный код и разработка механики с нуля (дурак да и только). Цель была не просто "скопировать игру", а создать своё видение этой игры от первого винтика до последнего байта прошивки.
Провал первый: курсовая за третий семестр
Начали с простого — концепта. Нужно было:
чтобы мячик действительно катался по полю, а не просто мигал на экране;
игроки управляли платформами с контроллеров;
ну и пока можно было не заморачиваться с печатными платами — хватит бредбордов.
Прикинул схему: 8 Ардуин (по 2 на каждый контроллер — одна в руке у игрока, вторая — в “центре управления полётами”). Для движения ракеток - Nema 17, да пару лимит-датчиков, что на 3д принтерах стоят.
Тут подключился один из участников — Саша. Сказал: “Я никогда не моделировал, но хочу попробовать сделать корпус контроллера. Научи.”
А я и не дурак отказываться. Показал ему основы работы в Fusion 360, объяснил как пользоваться скетчами, экструзией, зеркалами и прочими страшными словами — и отпустил в свободное плавание.
Честно? Основу он сделал сам. Да, на финальной стадии я вмешался — сгладил углы, убрал пару «аварийных» мест, но общий дизайн — его заслуга. И, учитывая, что это был его первый опыт в 3D, — респект.
Угадаешь, каким контроллером он вдохновлялся?
С дизайном заглядывали наперёд, добавив окошко для ведения счёта. В этой версии счёт показывать не планировалось.
Такое было моё видение игры. Шароуловители должны были появиться позднее, просто было сложно остановиться. Шестерни, натяжители, крепления и тд - всё вычерчено с нуля. За основу взят V-slot 2020, полтора метра в длину (помним, что я хотел побольше, да?), пришлось заказать 20шт.
В качестве толкателей заказаны на алишке соленоиды-толкатели на 20 Ньютонов и ходом сердечника в 10мм.
Связь - пятижильный провод, два провода из которого - питание, два - ШИМ сигнал и ещё один к транзистору, управляющему соленоидом.
Две основные группы запчастей для игры дались нелегко.
Часы фантазирования, подглядывания и проектирования; многочисленные попытки печати, за которыми обязательно следовали правки дизайна и новые испытания. Уже и не вспомнить, сколько было итераций — процесс оказался долгим, но невероятно увлекательным!
Вот так выглядит собранная основа
На фото — готовое шасси. Жёсткости конструкции вполне достаточно, а ход кареток получился плавным. Также можно увидеть нарезанную ДСП: два нужных нам куска были покрыты коричневой матовой краской в три слоя для аккуратного внешнего вида, а так же для контраста с белым шариком для софтбола. Шарик для пинг-понга не подошёл - слишком лёгкий и быстро терял бы скорость, не долетая до стороны противника.
Осталось дело за малым - натянуть ремни, собрать бредборды, написать код и убедиться, что нихрена не работает! К сожалению, код и фото бредбордов увидеть не получится, безвозвратно канули в цифровое небытие, вместе со старым ноутбуком...
Поиск ошибок, пот, ненависть, страдания — и всё ради одной цели. И вот, результат перед вами:
Да, можно увидеть, что осталась одна серьёзная проблема: усилия в 20 ньютонов оказалось недостаточно для комфортной игры. Времени на заказ более мощных соленоидов уже не было, поэтому игру демонстрировали в таком виде. К счастью, преподаватели отнеслись с пониманием — всё-таки, создать что-то подобное в отведённые сроки (4 месяца. Ещё про четыре будет в следующей главе) и без единого изъяна почти невозможно. В итоге "провал" был признан успехом, а на будущее заказаны более мощные соленоиды.
Функция измерения веса. Покажу конструкцию в 3д, так как показывать её в реальности весьма затруднительно. Я использую 60мм горшочки для гидропоники, поэтому проектировал под себя и свои нужды.
1/5
Сама измеряющая платформа с тензодатчиком. Печатается на 3д принтере и вставляется в мой кейс с растениями вместо обычной платформы (одной из 3х)
Собственно на изображениях видно, по центру стоит тензодатчик и вокруг него равноудаленно 7 слотов под горшочки с субстратом. От тензодатчика провод идет в АЦП HX711, но тут было несколько ньюансов: А) Обязательно заэкранировать кабель подключения от самого тензодатчика(я обернул экраном наполовину) и довести экран до АЦП. Б) Провести провод так, что бы если по нему капилярным эффектом начнет подниматься вода, он не добрался до датчика. Я сделал простую петлю и разместил его выше чем сам тензодатчик. Таким образом вода точно никак не попадет на АЦП. Сам же АЦП в герметичном корпусе. и вынесен отдельно от системы и подключается через TYPEC-TYPEC провод любой длины.
Это нужно для того, что бы провода от тензодатчика и до АЦП были как можно короче. а цифровой сигнал уже все равно на какое расстояние и с какими помехами передавать.
1/2
Корпус для АЦП.
Собственно сама функция измерения веса не замысловата и просто измеряет вес всего что стоит на ней. Тарирована вместе с платформой по умолчанию. Калибровка осуществляется по известному весу и выборкой в 50 измерений. Опять же, я встретил достаточно много проблем с этой фичей, но все удалось побороть. 1) Проблема влажного субстрата. Я знаю сколько весит горшочек с сухим субстратом и с мокрым. Но вода штука капающая. И эти самые капли, на начальных этапах роста дают не просто шум, а шумище. То есть когда растения весят 0.02 грамма, это начинает становится серьезной проблемой. Был введет флаг полива, и примерная интерполяция по времени, за сколько "худеет" горшочек от воды. + мы знали начальный и конечные веса. Это помогло уменьшить шум от измерений. Затем сверху накладывается алгоритм среднего, лимитации пиков (по сути фильтрация сигнала, если он превышает порог, то значит это значение либо шум, либо вода) и просто большая выборка на одно измерение, и вес стал стабильно учитываться. 2) Проблема контрафакта. Очень, ООЧЕНЬ много контрафакта на OZON. 2 штуки HX711 купленные мной, были с затертыми микрухами, неотмытым флюсом и шумели хуже чем пьяный сосед вася, периодически отваливались и отказывались измерять показания во всех режимах. (40\10), причинно следственной связи установить не удалось. В стерильном скетче и с идеальным подключением, вели себя неадекватно. Лишь на 3 раз удалось приобрести действительно хороший модуль, который ведет себя как заявляет производитель. На удивление он даже выглядел иначе.
Собственно, я упомянул, про распределение веса. у меня в системе 25 слотов на данный момент. (без весов 27). Так вот для каждого из слотов можно вычислить свой вес. Даже если растение не на весах, нужно что бы оно хотя бы раз там побывало единственное что. Работает это по принципу "разумного распределения", у каждого слота в системе есть свой индекс и 1 или 0 является ли этот индекс весами или нет. Если мы знаем, что растение например в системе 15 дней и оно одно сидит на измерительной платформе, то формула следующая
вес платформы - вес горшка - вес субстрата = вес этого конкретного растения.
Если на платформе сидят условно 5 растений, то этот вес просто делится на 5, при соблюдении того факта что это та же партия выращеваемых растений. (помните в предыдущем посте мы задавали количество посаженных растений? вот вот, там же и формируется уникальный ID посадки)
А дальше магия. У нас для каждого поддерживаемого растения системой,базово прописан теоретический вес, который перезаписывается реальным во время использования. Ну то есть по большому счету, некое самообучение. И логично предположить, что растение сидящее на весовой платформе в слоте с индексом 1, которому 5 дней примет массу A, а растения например в индексе 4,5,6 которым уже 25 дней, примет массу Общая масса растений - масса А / 3. Собственно как то так. А дальше, когда мы знаем уже реальную массу каждого растения, системе собственно не сложно предположить, что остальные растения из этой партии но в слотах не на весах, весят примерно столько же. И она присваивает массу уже этим растениям. Собственно как то так, это весьма сложно объяснить как оказалось. А дальше можно оставить на весах 7 уникальных растений например и с помощью этого алгоритма наблюдать за их поведением в зависимости от например различных факторов. (температуру поднять, чо будет? дать больше EC? и тд. ) все это пишется, запоминается и анализируется.
Ну и собственно график роста по CSV данным. Вот так салаты росли примерно с 25.04. (все что старше 30 дней улетает в долгосрочную память). Есть шумы и провалы, все таки я то трону весы, то сами растения на них, во время осмотра, все в норме.
Видно на графике, что сейчас салаты на платформе в стадии активного роста и прибавляют примерно по 0.1кг в сутки, что очень даже не плохо. Сейчас пару дней назад я снизил дозу EC до 1.2, до этого было 1.6, дальнейшие наблюдения покажут, осталась ли прежней скорость набора зеленой массы или замедлится. Салат Мини Ромэн.
Ну что бы далеко не отходить уже от конструкции, чуть вильнем в эту сторону. Это тоже отдельный и большой этап.
Контейнер для выращивания у меня сделан из ПВХ пластика на фрезерном ЧПУ. Тоесть по сути это был конструктор для склеивания. Клеил специальным клеем и сверху проходился ещё герметиком, тк вода может стоять в процессе эксплуатации весьма большим объемом. (около 1.8 литров. Возможно это не доработка и я поправлю в следующей генерации этот момент, но пока все работает отлично. Спроектирован так, что бы на обычном принтере можно было напечатать 3 крышки для высаживания растений и что бы влез в обычный металический стеллаж. Как по высоте так и по ширине. Идеально входил в стеллаж 800*300, тк изначально собственно под него и проектировался.
1/2
Конструкция контейнера.
Расположение самих форсунок тоже важно. Разместить их надо таким образом, что бы будущая корневая система не загородила собой одну\две\три из форсунок и не отняла питание у остальных растений, так же надо учесть что бы струя не била напрямую в горшочки, а увлажняла воздух вокруг, ну и естественно что бы это не было так, что из щелей фигачит водяной туман и увлажняет все вокруг и вокруг системы лужи.
Вариант 1, форсунки в верхней части направлены вниз.
Я сделал около 4-5 вариантов в модели, примерно просчитал конусами ~55 градусов, что соответствует моему давлению и диаметру форсунок. И самый нормальный вариант как по мне, без лишнего изобретательства велосипеда, это разместить их на будущем уровне воды внизу под 35 градусов к поверхности. Так же они заполняют пробелы друг друга. По одному борту стоят 4, по другому тоже 4 но со смещением на около 50мм.
В итоге финальный вариант выглядит уже вот так.
На дне имеются укрепления в виде полосок того же пластика, что необходимо для того что бы днище не прогибалось под весом жидкости и конструкция получилась легкой и жесткой и так же укреплены сами стенки ближе к крышке такими же полосами, что бы надежнее их скрепить между собой и дать опору для прямоугольника под печатные крышки уже.
Конструкция бака
Тут особо рассказывать нечего. Тут я не изобретал велосипед и сделал из контейнера удовлетворившего мои условия. Он должен закрываться плотно на защелки и быть не прозрачным, подходить по размеру. В принципе это всё. Дальше дело техники, я все монтировал на крышку, что бы при необходимости её поднять и вытащить сам бак и помыть\заполнить водой или что то ещё сделать, но честно я этого не делаю)) потому что заливаю воду просто в контейнер и она сама наполняет бак, но ситуации могут быть разные. Для обслуживания единственное что важно было, это не крепить ничего на сам контейнер, тк провода или шланги в дальнейшем будут мешать его обслуживанию. Единственное что пришлось сделать, это закрепить на быстросъемном печатном креплении датчик наличия воды на безопасном для насосе уровне. Если вдруг я все таки не увижу отсутствие раствора, он отключит насос и не даст ему работать вхолостую.
Продолжаем по функциям (системные функции)
Диспетчер задач. Да да, вы не ослышались. У меня есть свой диспетчер задач с блэкджеком и памятью. На самом деле вещь сугубо дебажная. Показывает она приоритет, ядро исполнения, сколько стека ест та или иная задача, за сколько выполняется и есть ли опасность краша системы по Watchdog, так же есть апи поинты для остановки или перезапуска задач, но пока в интерфейс не интегрировал ещё. Конечно это касается только задач FreeRTOS, задачи в Loop цикле при этом никак не отображаются.
Диспетчер задач
Лог система
Лог система, это отдельная вещь, тк в такой сложной системе надо логировать всё и ещё раз всё что можно. Но все же сталкивались с тем что в луп написал println и значение и больше в логах ты не хозяин. Да, конечно можно Усовершенствовать это делеями, а лучше миллисами или yield ами, но это разве гибкость? Когда логов становится много. Нет, не так. МНОГО, ОЧЕНЬ МНОГО, за пару секунд собирается 30-40 строк, пора что то с этим делать. А ведь так не хочется трогать уже сделанное полезное логирование, вдруг оно опять понадобится позже. Поэтому я уже известным путем и пошел. Сделал просто обертки для функций логирования, но уже с аргументами уровня логирования. DEBUG INFO WARNING ERROR. И собственно параметрами куда это самое логирование отслыать, в телегу на сд карту или в веб интерфейс. В тг просто по приколу, я хрен знает зачем, мне ни разу не пригодилось. А вот на SD очень даже, в связи с этим на фронте на самой ESP появилась даже кнопочка скачать лог. Пришлось ограничить правда размер до 4мб, как правило этого хватает для всех нужд. Но не было печали купила баба порося, это то я все сделал, но как отлавливать PANIC/WDT и прочие неприятности когда ты по ошибке вылез за предел массива или сожрал весь HEAP? Правильно, взять дешман ESP32Dev модуль и подцепить его TX\RX2 в RX\TX0 на Main ESP32S3 и заставить его читать вообще всё и отсылать по вебсокету на свой веб интерфейс. А ещё можно прикрутить кнопку принудительной перезагрузки контроллера, перепрошивки без необходимости лезть в корпус и подсоединять USB.
Возможность задать уровень настроек логирования.
Логирование всей фермы SLAVE контроллером на ESP32. Все идет в Live режиме, без перезагрузок страницы и без задержек через WebSocket.
Тут же прикрутил и фильтрацию логов по системам которые определяются автоматически, прикрутил MQTT для удаленного перезапуска Main и самое главное, на SLAVE сохраняются все Backtrace c Master контроллера и коды ошибок для дальнейшей диагностики + лог за минуту до критической ошибки. И вот это уже настоящая имба. Ты буквально независим от ошибок и USB провода и можешь прочитать всё что тебе нужно независимо от того, что с Master контроллером. Так ещё и ладно, эту идею можно развить и дальше, Slave контроллер может быть и резервным контроллером. Например самые важные функции это полив и свет, вполне можно автоматически дублировать и управлять теми же самыми реле при отключении Master контроллера. Уведомлять пользователя и тд. В будущем такое обязательно будет, но количество лапши внутри корпуса уже заставляет дергаться оба глаза. Поэтому потом, когда нибудь.
Резюмируя систему логирования, она получилась мощная, быстрая, понятная и самое главное удобная для использования. А большего мне и не надо. Красивости в ней только мешают, поэтому тут дизайна как такового и нет.
MQTT и умный дом.
Так же отдельный большой раздел.
Настройки подключения к MQTT. Все отображается в лайве, а так же есть подсказочки на какие топики подписаться если нужно это сделать вручную.
Обычно я не шел дальше ручной подписки на нужные топики, но тут что то захотелось ну прям автоматически все чтоб было. Итог таков. Если у вас дома есть Home Assistance и стоит расширение MQTT, вам больше ничего не надо делать. Все найдется и добавится в систему автоматически как надо и без танцев с конфигурациями, отдельным устройством, в котором усе уже сконфигурировано как нужно.
Мелочь, а указание авторства доставляет удовольствие.
Сама страничка сенсоров и релюшек.
Конечно забавно, но виртуальные реле из HA добавляются снова в HA, можно исправить, но не вижу смысла)
Не знаю, тут особо рассказывать то больше и нечего, из HA можно прокинуть уже куда хотите, хоть в Apple Home, хоть в Алису. Задавать сценарии и тд. В будущем возможно я расширю возможности настроек MQTT, что бы можно было выбрать а что конкретно вообще по этому вашему MQTT передавать то, но пока это жестко захардкожено и он передает все сенсоры и все реле. А больше как будто и не нужно, разве что блокировку таймеров и их настройку ещё бы завести, но как будто ту мач.
Система
Системный раздел умной фермы
Отсюда, можно забэкапить всё, что происходит в системе. конфигурацию реле, насосов, удобрений, бака, посадки и так далее и тому подобное. Всё качается в ZIP архиве и так же восстанавливается в одну кнопку на чистой системе. Это очень очень полезно, тк я за время тестирования и кучи форматирований флешек и Spifs просто устал заполнять всё руками. А так же помогает если вдруг вы сменили SD или отчистили SPIFS обновив прошивку. (Дада, кнопка файловой системы называется LittleFS так это потому что я всегда их путаю, но в данном проекте SPIFS)
Ну и возможность обновить систему через OTA .bin или обновить сам веб интерфейс, чего я делать больше не планирую.
Telegramm
Это последняя в этом посте система, телеграмм уведомления.
Ну во первых, она может срать вам в личку постоянными уведомлениями о срабатывании таймеров.
Во вторых, может уведомлять о том, что система засорена и насос не будет включен, или кончился раствор. (скриншоты из тестирования)
Конечно же она шлет ежедневные отчеты в 9 или во сколько вы выберете утра. С фотографией, параметрами и счетчиком незапланированных перезапусков за все время. (незапланированный перезапуск, это перезапуск даже от обновления прошивки, его можно скинуть)
Ну и конечно, система может выслать вам неприятные сообщения, которые вас уже изрядно бесят.
Ну и последнее
Каждый запуск системы, это куча проверок на работоспособность всех микросервисов системы. И их запуск. О чем телеграмм бот и сообщает. Тут немного дублируется логирование, тк STILL BETA. Но ничего)
Давайте на этом закончим вторую часть. В третей, я хотел бы рассказать уже о датчиках, их калибровке, температурных компенсациях, проблемах, шкалах NaCl и других. Австралийских аршинах в измерении EC. А в четвертой, если успею доделать 4.2, расскажу об интерфейсах взаимодействия с фермой. (Веб интерфейс, экран Nextion) вообщем очень много какой инфой могу поделится в этом цикле постов.
Впервые за 6.5 лет, что я здесь решил сделать хоть сколько-то серьёзный пост, да и авторский контент точно не помешает. Сразу предупреждаю: телегу не рекламирую, реферальных ссылкок не будет, фоткал на тапок, чукча не писатель, маска моя - тег моё хуё-моё.
Тут есть мат, дилетантство, шизофренические текстовые конструкции и огромное количество моментов, в которых захочется сказать "Автор, ты совсем еблан?"
Погнали!
Дело началось в августе 2023 года, когда я впервые для себя открыл такой тип досуга как косплей-фестивали, а в частности Томскую Con.Версию. Тогда же у меня с товарищем возникла идея сделать косплей на персонажей из нашей общей любимой игры - Watch Dogs 2 - Ренча и Маркуса.
И если с образом Маркуса (негр, справа) проблем не возникло никаких - в косплейном обществе такие костюмы называют "шкаф" (в плане, одеться в персонажа можно просто достав обычные шмотки из шкафа), то с Ренчем (чудик слева в маске) дела уже обстоят интереснее.
Как минимум, потребуется маска, о создании которой я сегодня и хочу написать.
Изначальной идеей было купить уже готовый вариант маски (как на изображении ниже), но почесав репу и прикинув писю к носу мы поняли, что вариант это такой себе, ибо дорого и плохо (на тот момент подобные маски стоили около 7-10 т.р. и не имели анимации) , и надо бы запариться и скрафтить маску самим.
вот такую маску хотели купить изначально
Идея то появилась, а как реализовать – неясно. Хотелось видеть анимации, полную поддержку эмотиконов и качество чуть лучше, чем подвал в Шэньчжэне.
Пошёл гуглить. Нагуглил уже известный всем вариант маски с очками Chemion, еще какую-то фигню и чего-то загрустил.
От грусти полез шерстить гитхаб и тут меня ждал успех. Мы смогли найти опенсорсный проект маски от TomMakesThings построенный на базе светодиодных матриц MAX7219, Arduino и базовой простой как три копейки пластиковой маски с того же али. Мало того, этот проект соответствовал всем нашим требованиям, управлялся по блютузу и имел кайфовое приложение.
Долго не думая, мы почти сразу начали закупаться компонентами.
С алиэкспресса были заказаны: шасси маски, паяльные расходники, а Arduino Uno я решил заменить на ESP32 (из-за дешевизны и уже встроенного блютуза).
Трудности возникли уже на этапе покупки матрицы. Оказалось, что в наличии ни в нашем, ни в ближайших городах не бывает таких матриц в нужном нам цвете (белый) а брать синий или красный как-то фу, но зато есть куча адресных матриц WS2812b. Естественно, библиотеки для управления тем и этим типом матриц отличаются чуть более, чем полностью, поскольку матрицы на MAX7219 – аналоговые, WS2812 же – цифровые.
“Придется переписывать код” – подумал я, заказал матрицы и ушел в запой на 4 дня.
Во время этого самого запоя я при помощи рук, ChatGPT и такой-то матери таки смог понять реализацию оригинального кода, пару тысяч раз чертыхнуться и переписать почти весь код (кроме некоторых на мой взгляд бесполезных анимаций) на библиотеке FastLED, которая и будет управлять адресными светодиодами.
Процесс ардуинокода, костылей, а также самоненависти (вот до чего доводят с++, особенно если твой максимум - "Hello, World!")
На симуляторе ардуино все заработало просто идеально, и оставалось только протестировать на реальном железе и посмотреть, как всё работает в жизни. На этом этапе я ещё не знал, насколько бесполезными были мои страдания.
Забрал посылку с маской. Как оказалось, матрицы на базе WS2812 слишком большие, что в корне губило нашу идею с использованием адресных светодиодов вместо “аналоговых” матриц MAX7219.
Ушел в тильт на пару дней и чуть было не решил забить нафиг на весь косплей, но вдруг случилось неожиданное – великий и ужасный @AlexGyver, выкатывает проект (радио-голова Бендера) ровно на тех же MAX7129, которые использовались в маске от TomMakesThings и реализует в нем почти то же самое, что надо нам.
Наглядно видно насколько матрицы большие для использования в этом проекте
После просмотра видоса выяснилось, что моя догадка о том, что матриц такого типа с белыми светодиодами нет в продаже, но умные китайцы придумали вот такие белые сторонние светодиодные модули, совместимые с, собственно, контроллером:
Заказал, оплатил, получил. Заказал так же и сами модули MAX7219.
Так-то лучше! Теперь и матрицы чётко по размеру, и через "визор" маски можно видеть окружающий мир.
Наступило время сборки. Подключил все по схеме, но матрицы вели себя чрезвычайно странно: то не отображали ничего вовсе, то показывали какую-то белиберду; в общем, было очень неприятно. В итоге спустя полдня мучений и один убитый логический конвертер я решил забросить это дело на неопределенный срок.
схема подключения матриц к есп32 (да, для такого дилетанта как я требуется схема даже для очень простых вещей)
Неопределенный срок оказался длинной в два дня. Мне стало скучно и одним осенним утром я скупил ВООБЩЕ ВСЕ логические конвертеры, какие я смог найти в наличии и сел собирать по новой, теперь уже не на коленке и под банку пива, а на трезвую голову и с моральной поддержкой.
Снова какая-то хрень. Ничего не могу понять, есп вроде живая, конвертеры – новые. Подумал-подумал и решил поменять матрицу на стоковую красную. Собрал, запустил, заработало.
Куда же без косяков… белые дисплеи, купленные на замену стоковым красным, подключаются по схеме “общий анод”, а модули max7219 работают только с дисплеями “общий катод”.
Где-то тут были тщетные попытки переписать библиотеку под работу с общеанодными дисплеями, но почти сразу было понятно, что дело гиблое и надо бы покупать дисплеи и матрицы заново...
Новый день – новые траты!
Ну теперь-то всё точно должно получиться! Жду посылку.
Посылки пришли довольно быстро, матрицы были подкинуты на скорую руку к еспшке ииии.. да! Всё взлетело, заработало и красиво начало моргать светодиодами.
Ура, товарищи, победа! Теперь дело оставалось за малым, ещё раз переписать (а вернее, откатить) код к моменту, где всё работало, запихнуть железки в маску и проверить как всё это выглядит в деле.
На этот момент проект, который по сути своей можно было бы сделать за месяц (учитывая ожидание посылок с али), растянулся уже на 3 с половиной месяца... Криворуким быть тяжело!
На этом всё. Проект получился хоть не очень масштабным, зато дров наломать получилось знатных. Но, опыт есть опыт.
Наш разраб фигачит вообще адовые проекты.
Ну такой вот примерно рецепт усредненный, потому что вариаций масса.
Берётся готовый проект с гитхаба, он не тестится, тестить — это не про нашего разраба. Он берет этот проект, размазывает его по функциям и начинает рефакторить. Добавляет в него огромное количество костылей, хаков, спизженного кода со StackOverflow для вязкости, немного фиксов сверху. Все это компилится до дыма. Потом снимается с Arduino IDE, и разраб остужается на балконе. Потом он заливает это все на esp32 и, щедро полив анекдотами, отдаёт мадесте. Пишет пост на пикабу, шкрябая по клавиатуре. Пишет и приговаривает полушепотом: "ух, бля".
При этом у него на лбу аж пот выступает. Любезно мне иногда предлагает потестить, но я отказываюсь. Надо ли говорить о том, какой запах потом? Вонища такая, что в косбенде обои от стен отклеиваются.
История всему этому такова: 30-летний мальчик понял, что может играть с модельками и радоваться жизни. И вот в его жизни появляется радиоуправляемый грузовик!
Я не буду рассказывать, что и у кого я покупал, я думаю, на меня и так выльют ушат помоев с моим подходом и заодно научат, как надо. Я просто хочу поделиться тем, что с большим трудом за полгода наконец-то родил скетч для Arduino с экраном, чтобы превратить его в приборку для грузовика. Да, никто не увидит, но я буду знать, что оно там есть. На этом все. Спасибо за внимание. Если нужен скетч, то он лежит тут.
P. S. Я хотел использовать ESP8266, но там совсем не получилось. Я не уверен, что оно будет корректно работать. Если решите меня ткнуть носом в мои ошибки, буду благодарен. Есть решение от Тамии, но 14 тысяч прям жаба душит на модель, которая была сама собрана за 10 тысяч. В скрипте реализовано то, что скорость и коробку он считывает из начального состояния при включении.
*значение нейтрали скачет из-за того что я использую крутилку без фиксации
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <DHT.h>// можно добавить 2 слеша чтобы выключить // Определяем размеры экрана #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 32 //я использую 0.91 oled // Создаём объект для OLED дисплея Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // Определяем пины для DHT и создаем объект DHT #define DHTPIN 2 // можно добавить 2 слеша чтобы выключить #define DHTTYPE DHT11 // можно добавить 2 слеша чтобы выключить DHT dht(DHTPIN, DHTTYPE); // можно добавить 2 слеша чтобы выключить // Пин для считывания ШИМ-сигнала const int speedPin = A3; //пин на arduino // Переменные для начального значения и текущей скорости float initialPwmValue = 0; float currentSpeed = 0; bool isInitialValueSet = false; void setup() { Serial.begin(115200); display.begin(SSD1306_SWITCHCAPVCC, 0x3C, -1); dht.begin();// можно добавить 2 слеша чтобы выключить display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); // Выводим стартовое сообщение display.setCursor(30, 0); display.println("ZiL Dash Load"); // можно писать все чтот угодно display.setCursor(0, 15); display.println("Status CHECK! EBU_ok. err_14. START"); // можно писать все чтот угодно display.display(); delay(5000); // можно менять в соответствии сколько вы хотите видеть этот экран display.clearDisplay(); } void loop() { // Считывание ШИМ-сигнала int pwmValue = pulseIn(speedPin, HIGH); // Считываем время импульса float dutyCycle = map(pwmValue, 0, 10000, 0, 800); // Преобразуем в значения от 0 до 255 float speed = dutyCycle * (180.0 / 800.0); // максимальная скорость 88кмч подбирайте значения для себя // Преобразование значения ШИМ в скорость (примерно 0-100 км/ч) currentSpeed = dutyCycle * (180.0 / 100.0); // Установим начальное значение ШИМ при первой итерации if (!isInitialValueSet) { initialPwmValue = dutyCycle; isInitialValueSet = true; } // Вычисляем относительную скорость относительно начального значения
float relativeSpeed = dutyCycle - initialPwmValue; if (relativeSpeed < 0) { relativeSpeed = 0; } if (relativeSpeed < 0) { relativeSpeed = 0; // } // Очистка дисплея и вывод текущего состояния display.clearDisplay(); display.setTextSize(1); display.setCursor(0, 0); // Сравниваем текущее значение с начальным и выводим соответствующие букву для симуляции акпп if (dutyCycle < initialPwmValue) { display.setTextColor(SSD1306_WHITE); display.println("R"); display.setTextColor(SSD1306_BLACK); display.setCursor(5, 0); display.print("N"); display.setCursor(10, 0); display.print("D"); } else if (dutyCycle == initialPwmValue) { display.setTextColor(SSD1306_BLACK); display.setCursor(5, 0); display.print("R"); display.setTextColor(SSD1306_WHITE); display.setCursor(10, 0); display.print("N"); display.setTextColor(SSD1306_BLACK); display.setCursor(15, 0); display.print("D"); } else { display.setTextColor(SSD1306_BLACK); display.setCursor(5, 0); display.print("R"); display.setCursor(10, 0); display.print("N"); display.setTextColor(SSD1306_WHITE); display.setCursor(15, 0); display.print("D"); } // Считывание температуры float t = dht.readTemperature(); // Считываем температуру в Цельсиях// можно добавить 2 слеша чтобы выключить float h = dht.readHumidity(); // Чтение влажности, // можно добавить 2 слеша чтобы выключить if (isnan(h) || isnan(t)) {// можно добавить 2 слеша чтобы выключить Serial.println("chek!");// можно добавить 2 слеша чтобы выключить return; } // Отображаем температуру на дисплее display.setTextColor(SSD1306_WHITE); display.setCursor(30, 0); //положения по горизонтали и вертикали display.println("URAL/Zil Dash"); display.setCursor(0, 10);// можно добавить 2 слеша чтобы выключить display.print("T:");// можно добавить 2 слеша чтобы выключить display.print(t);// можно добавить 2 слеша чтобы выключить display.println("C");// можно добавить 2 слеша чтобы выключить display.setCursor(60, 10);// можно добавить 2 слеша чтобы выключить display.print("H: ");// можно добавить 2 слеша чтобы выключить display.print(h);// можно добавить 2 слеша чтобы выключить display.println(" %");// можно добавить 2 слеша чтобы выключить display.setCursor(15, 20); display.print("Speed: "); display.print(currentSpeed - (initialPwmValue * (180.0 / 100.0))); display.println(" km/h"); //если поменять на мили ничего не поменяется display.display(); // Обновление дисплея delay(10); // частота обновление данных display.clearDisplay(); // Очищаем экран для перерисовки }
Не судите строго, всем хорошего дня! В оптимизации скетча помогала мне нейронка от "нереклама"