Ответ на пост «Оживляем неизвестный дисплей от японского поезда/автобуса»
Не знал, что они статьи и на пикабу выкладывают. Но самое главное отвалилось в посте — видео с итоговым результатом!
Вот такие часики-метеостанцию я запилил за пару недель из плазменного дисплея от старого японского автобуса.
Шрифты плюс-минус обычные, иконки погоды вышли как по мне шикарные, но самым тёплоламповым получился эффект дождя, который отрисовывается в дождливые (по прогнозу погоды) дни.
Ну и музыка тоже своя, да.
Кто нашёл отсылочки в видео (помимо самой очевидной на "Матрицу"), тому приз — два прекрасных нихуя %)
Безысходники прошивки положил на Гитхабе — https://github.com/vladkorotnev/plasma-clock/tree/develop/sr...
Отдельное спасибо @AlexGyver за его GyverPortal, иначе я бы на проект забил ещё на стадии размышлений о том, что придётся же админку писать с нуля.
Портативный RGB светильник с управлением по Wi-Fi
Подобные штуки мне показались востребованными среди тех, кто занимается фото- и видеосъёмкой, так что я решил сделать пару штук на продажу: мне было интересно попробовать что-то новое и пристроить давно лежавшие без дела комплектующие. Вот что получилось:
За основу был взят самый дешёвый настенно-потолочный линейный светильник - от него использовался корпус и провода. Светодиоды были заменены на ленту на WS2812, питающуюся от одного аккумулятора 16650 (18650 помещался в корпус с большим усилием и в дальнейшем мог его разорвать) через преобразователь на МТ3608. За заряд отвечает модуль на ТР4056: USB-C разъём выведен на торец корпуса, там же спрятаны два светодиода (зарядка идёт, зарядка завершена).
Лентой управляет ESP8266 с прошивкой WLED:
Веб-интерфейс содержит все необходимые настройки и позволяет активировать множество разнообразных эффектов:
Вот ещё склейка нескольких случайных режимов:
Прошивка также умеет работать с матрицами, поэтому в планах сборка аналогичного светильника, но уже в квадратном корпусе. Если будет интересно - напишу и про него.
matvey6191@gmail.com
Подборка ламп е27, которых стоит избегать
Долго, очень долго мы на сайте правили проблему с ранжированием лампочек в рейтингах ламп. Казалось бы - простая задача, сначала показать хорошие лампы, потом лампочки без оценки и потом завершить все теми лампами, которых стоит избегать.
Все это время мы показывали только лучшие лампы. Да, за какую-то пользователи проголосовали более положительно, за какую-то менее, но все время вашему вниманию были предоставлены более-менее неплохие экземпляры.
Но теперь мир розовых пони закончился, мы победили багу и рады показать вашему вниманию лампы, точки роста которых нас удивили и которые наверное лучше обходить стороной. Ведь вы же никогда не станете гуглить худшие лампы :). Ну а если захотите посмотреть сами и почитать обзоры на них, то заходите на собственно рейтинг ламп е27.
Итого, лампы e27 которые по совокупным данным надо обходить стороной:
Мощные лампы Эра 25Вт
InHome 8Вт
Polaroid 10Вт (скрепя сердцем, ведь лампа почти была прекрасной)
Bellight 12 Вт
Включай 11 Вт
Tp-Link 8.7 Вт
Iek 20 Вт
InHome 10 Вт
Ну а я напоминаю, что наш проект некоммерческий, мы ничего не продаем, а только стараемся собирать лампочки по всему интернету, агрегируем их и строим рейтинги. И надеюсь вскоре порадуем любителей светотехники новым функционалом.
А если не нашли в рейтинге лампочку, которую очень сильно не любите и считаете, что она обязана быть среди худших - не расстраивайтесь, впереди еще столько ламп для тестирования и, возможно, в будущем вы найдете ее в следующей подборке.
Берегите глаза!
Топ 20 интересных электронных DIY-наборов для любителей самостоятельной сборки и пайки, а где-то даже программирования
1) Самолет
Интересный набор для самостоятельной сборки и пайки электронных компонентов, после правильной сборки получится самолет с марцающими светодиодами. В набор входят резисторы, конденсаторы, десятичный счетчик CD4017BE, светодиоды и тд. Идеальный вариант для начинающих радиолюбителей. Стоит такой комплект около 1150 руб. ссылка на источник
2) Понижающий модуль питания
Электронный комплект «сделай сам» - преобразователь напряжения переменного тока. Вход источника питания AC15V или DC18V, фиксированный выход постоянного тока 3 В/4,5 В/5 В/6 В/9 В/12 В. Стоит такой набор около 1260 руб. ссылка
3) Часы
Набор для сборки цифровых часов, также имеются датчики для отображения температуры окружающего воздуха, будильник, календарь и тд. Стоит такой набор для пайки и сборки где-то 1285 руб. ссылка
4) Увлажнитель
Набор для самостоятельного изготовления мини-увлажнителя воздуха, который работает от USB. Стоит такой около 83 руб. ссылка
5) Машинка
Комплект электронных деталей для сборки умного автомобиля. Суть умной машинки в том, что после правильной сборки и пайки она сможет ездить по жирно нарисованным линиям и не отклоняться от курса, например по бумаге. Стоит такой около 385 руб. ссылка на источник
6) Табло
Набор электронный для самостоятельной сборки модуля со множеством светодиодов и разными режимами работы, как таймер с секундами, отоброжение линий и тд. Стоит комплект около 390 руб. ссылка
7) Электромагнитная пушка
Занимательный набор для любителей физики и электроники, на сборку электромагнитной пушки в акриловом корпусе потребуется около 90 минут, если все собрано верно, она сможет стрелять маленькими металлическими шариками. Стоит набор где-то 1490 руб. ссылка
8) Светильник
Дешевый набор для сборки светильника с красными светодиодами и разными режимами работы, которые управляются однокристальным микрокомпьютером AT89S52. Стоит такой набор 145 руб. ссылка
9) Радиоприемник
Набор для сборки FM радиоприемника, который работает от 2х батареек АА, после сборки нужно подключить наушники и 'ловить' различные радиостанции. Стоит набор 120 руб. ссылка
10) Робот-танк
Программируемый электромеханический конструктор на гусеницах Elegoo Conqueror Robot Tank Kit имеет несколько встроенных функций, таких как движение по траектории, заданной линией, детектор препятствий и дистанционное управление. Набор для сборки робота позволяет пользователям познакомиться с графическим программированием. Конструктор идеально подходит для детей и подростков, которые хотят посвятить свою жизнь карьере в сфере высоких технологий. Стоит такой около 8000 руб. ссылка на источник
11) Светильник-круг
Очень простой набор для сборки и самостоятельной пайки круглого модуля с красными светодиодами, создающие эффект вращающегося колеса. Работает от напряжения 3-5 вольт. Стоит такой 120 руб. ссылка
12) Счетчик Гейгера
Интересный набор для сборки детектора радиации, а именно обнаружения 20 мР/ч ~ 120 мР/ч гамма-лучей и 100 ~ 1800 от переменных/точек мягкого бета-излучения. Стоит такой наборчик где-то 2640 руб. ссылка
13) Микрофонный усилитель
Очень простой и дешевый набор для сборки и пайки микрофонного усилителя. В наборе идут провода, плата,, конденсаторы и тд. Идеальный вариант для тех, кто хочет научится паять и разбиратся в электронике, также читать схемы. Стоит набор 68 руб. ссылка
14) DIY набор для сборки устройства обнаружения магнитного поля
Набор позволяет собрать простое устройство с помощью которого можно обнаружить магнитное поле, а также северный и южный полюса. Набор предназначен для изучения основ радиоэлектронники и развития навыка пайки компонентов разного типа. Рекомендован для начинающих.
В комплект входит:
Печатная плата
Набор активных и пассивных элементов для сборки
Схема. Стоит такой набор около 112 рублей. Ссылка на источник
15) Спиннер
Набор 'Сделай сам' - светодиодный спиннер в прозрачном акриловом корпусе. Все компоненты нужно спаять на плате самостоятельно. После сборке получится крутой спиннер и при вращении красочно будут светить светодиоды. Стоит такой набор около 494 руб. ссылка
16) Частотомер
Частотомер 1 Гц — 50 МГц E0330 позволяет измерять частоту кварцевых резонаторов. Простой цифровой прибор позволяет измерять наиболее применяемые "кварцы". Тестер кварцевых резонаторов удобен. Сборка тестера с цифровой светодиодной шкалой не представляет проблем. Собрать частотомер своими руками за пару часов под силу даже начинающему радиолюбителю. Стоит такой 660 руб. ссылка
17) Сердце
Красивое электронное сердечко с разноцветно переливающимися светодиодами. Питается от батарейки, которая вставляется позади сердечка. Всего состоит из 32 светодиодов и других электронных компонентов. Стоит набор около 900 руб. ссылка
18) 'Песочные часы'
Набор интересный для сборки электронных песочных часов. Светодиоды включаются и выключаются в таком порядке, что создается эффект работающих песочных часов. Стоит комплект для пайки около 300 руб. ссылка
19) Музыкальная колонка
Прикольный DIY Bluetooth динамик с множеством функций, включая дистанционное управление, поддержку USB, карт памяти, Блютус и многое другое. Набор требует самостоятельной сборки и пайки. Стоит комплект на данный момент около 1700 руб. ссылка
20) Сварочный аппарат
Набор для создания аппарата для точечной сварки, например контактной сварки пластин для соединения аккумуляторов. Рабочее напряжение: 12 ~ 14,6 В. Стоит набор около 1500 руб. ссылка на источник
Хорошо разбираетесь в звездах и юморе?
Тогда этот вызов для вас! Мы зашифровали звездных капитанов команд нового юмористического шоу, ваша задача — угадать, кто возглавил каждую из них.
Переходите по ссылке и проверьте свою юмористическую интуицию!
Выполняем сторонние программы на микроконтроллерах с Гарвардской архитектурой: как загружать программы без знания ABI?
Зачастую в процессе разработки собственных устройств или моддинга уже существующих, встаёт задача выполнения стороннего кода: будь то ваши собственные программы с SD-флэшек, или программы, написанные другими пользователями с помощью SDK для вашего устройства. Тема компиляторов и кодогенерации достаточно сложная: чтобы просто загрузить ELF или EXE (PE) программу, вам нужно досконально разбираться в особенностях вашей архитектуры: что такое ABI, релокации, GOT, отличие -fPIE от -fPIC, как писать скрипты для ld и т. п. Недавно я копал SDK для первых версий Symbian и основываясь на решениях из этой ОС понял, каким образом можно сделать крайне «дешевую» загрузку любого нативного кода практически на любом микроконтроллере, совершенно не вникая в особенности кодогенерации под неё! Сегодня мы с вами: узнаем, что происходит в процессе загрузки программы ядром Linux, рассмотрим концепцию, предложенную Symbian Foundation и реализуем её на практике для относительно малоизвестной архитектуры — XTensa (хотя она используется в ESP32, детали её реализации «под капотом» для многих остаются загадкой). Интересно? Тогда добро пожаловать под кат!
❯ Как это работает?
Думаю, для многих моих читателей реализация процесса загрузки exe-программ и dll-библиотек в память процесса оставалась эдаким чёрным ящиком, в детали реализации которого вдаваться не нужно. Отчасти это так и есть: современные ОС разруливают процесс загрузки бинарников в память сами, не требуя от программиста вообще ничего, даже понимания того, куда будет загружена его библиотека или программа.
Давайте для общего понимания вкратце разберемся, как происходит загрузка программ в Windows/Linux:
1. Система создаёт процесс и загружает в память программы секции из ELF/PE. Обычные программы для своей работы используют 3 секции: .text (код), .data (не-инициализированный сегмент памяти для глобальных переменных), .bss (сегмент памяти для инициализированных переменных). Каждому процессу выделяется собственное адресное пространство, называемое виртуальной памятью, которое не позволяет программе испортить память ядра, а также позволяет не зависеть от разметки физической памяти на выполняющей машине. Концепцию виртуальной памяти реализует специальной модуль в процессоре, называемый MMU.
2. Если бы наши программы не использовали никаких зависимостей в виде динамических библиотек, то на этом процесс загрузки можно было бы закончить: каждая программа имеет свой адрес загрузки, относительно которого линкер строит связи между обращениями к коду/данным программы. Фактически, для самых простых программ линкеру остаётся лишь прибавить адрес загрузки программы (например, 0x100) к каждому абсолютному обращению к памяти.
Однако современные программы используют десятки библиотек и для всех предусмотреть собственный адрес загрузки не получится: кто-то где-то всё равно будет пересекаться и вероятно, портить память. Кроме того, современные стандарты безопасности в Linux рекомендуют использовать позиционно-независимый код, дабы использовать преимущества ASLR (Address Space Layout Randomization, или простыми словами возможность загрузить программу в случайное место в памяти, дабы некоторые уязвимости, завязанные на фиксированном адресе загрузки программы перестали работать).
3. Поэтому для решения этой проблемы придуман т. н. динамический линкер, который уже на этапе загрузки программы или библиотеки патчит программу так, чтобы её можно было загрузить в любой участок памяти. Для этого используются данные, полученные от обычного линкера а этапе компиляции программы: помимо .text, .data и .bss, линкер создаёт секции .rel и .rel-plt, которые называются релокациями. Если объяснять совсем условно, то релокации — это просто запись вида «какой абсолютный адрес в коде программы нужно пропатчить» -> «на какое смещение его пропатчить». Самая простая релокация выглядит вот так:
Где по итогу:
.rel-plt же служит для резолвинга вызовов к dll/so: изначально программа ссылается на заранее определенные в процессе компиляции символы, которые уже в процессе загрузки патчатся на физические адреса функций из загруженной библиотеки.
И казалось бы — всё очень просто, пока в дело не вступают GOT (Global Offset Table — глобальная таблица смещений) и особенности реализации конкретного ABI. И ладно бы x86 или ARM, там всё разжевано и понятно, однако на других архитектурах начинаются проблемы и не всегда очевидно что и где за что отвечает.
А ведь чаще всего нужно просто загрузить небольшую программу, которой не нужны комплексные загрузчики: немного кода, немного данных и всё. И тут у нас есть три выхода:
Писать полноценный загрузчик ELF-бинарников. ELF может оказаться громоздким для некоторых окружений и его реализация может оказаться тривиальной не для всех.
Зарезервировать определенный сегмент в памяти (пусть с 0xFFF по 0xFFFF) и скомпилировать нашу программу с адресом загрузки 0xFFF с параметром -fno-pic. В таком случае, линкер сгенерирует обращения к памяти по абсолютным адресам — если переменная лежит по адресу 0xFFF, то программа будет обращаться сразу к этому адресу памяти, без необходимости что либо динамически линковать. Именно такой подход использовался во времена ZX Spectrum, Commodore 64 и MS-DOS (однако там роль «виртуальной памяти» выполняла такая особенность 8086, как сегменты). У такого подхода есть и минусы: относительная невозможность загрузки сразу нескольких программ одновременно, зарезервированное пространство линейно отъест небольшой кусок памяти у основной прошивки, нет возможности динамической аллокации секций. Зато такой код теоретически будет работать быстрее, чем PIC.
Проблемы реализации такого способа: иногда нужно лезть в систему сборки основной прошивки и патчить скрипт линкера так, чтобы он не трогал определенный регион памяти. В случае esp32, например, это требует патча в сам SDK и возможного «откола» от мейнлайн дистрибутива.Использовать программу с относительной адресацией, однако без сегментов .bss и .data. Самый простой в реализации способ, который к тому же очень экономичен к памяти, позволяет загружать программу в любое место и пользоваться всеми фишками динамического аллокатора и не требует вмешательств в основную прошивку, кроме примитивного загрузчика программ. Именно его я и предлагаю рассмотреть подробнее.
Недавно мы сидели в чате ELF-сцены (разработка нативных программ под телефоны Siemens, Sony Ericsson, Motorola и LG с помощью хаков) и думали, как же можно реализовать загрузчик сторонних программ на практически неизвестных платформах. Кто-то предлагал взять ELF под основу — однако с его реализацией под некоторые платформы есть трудности, а кто-то предлагал писать «бинлоадер» — самопальный формат бинарников, который получается из, например, тех же эльфов.
В это же время я копал SDK для Symbian и хорошо помнил, что в прикладных приложениях для этой ОС нет поддержки глобальных переменных вообще. Да, сегмент .data и .bss полностью отсутствует — переменные предлагается хранить в структурах. Почему так сделано? Всё дело в том, что каждая программа в Symbian — это dll-библиотека, которую загружает EKA и создаёт экземпляр CApaApplication. И дабы была возможность загрузить dll один раз для всех программ (что справедливо для системных библиотек), ребята полностью выкинули возможность использования любых глобальных переменных. А ведь идея интересная!
Однако в таком подходе есть несколько серьезных ограничений:
Отсутствие глобальных переменных может стать проблемой при портированиии уже существующего софта, хотя вашим программам ничего не мешает передавать в каждую функцию структуру с глобальным стейтом, который можно при необходимости изменять. Кроме того, нет ограничений на использование C++ (за исключением необходимости ручной реализации new/delete и отсутствием исключений).
Отсутствие преинициализированных данных. Вот это уже может стать относительно серьёзной проблемой, у которой, тем не менее, есть свои обходные решения. Например если вы храните команды для инициализации дисплея в таблице, или какие-либо калибровочные данные — вы не сможете их объявить, просто используя инициализаторы в C. Тоже самое касается и строковых литерал. Тут есть два варианта: часть таблиц можно вынести на стек (если эти самые таблицы достаточно маленькие), либо подгружать необходимые данные из бинарника с помощью основной прошивки (например, LoadString и т. п.).
Давайте же на практике посмотрим, имеет ли право на жизнь такой подход!
❯ Практическая реализация
Формат нашего бинарника будет до безобразия прост: небольшой заголовок в начале файла и просто сырой дамп сегмента .text, который можно экспортировать из полученного elf даже без необходимости писать скрипт для линкера. При этом нужно учесть, что ESP32 — это микроконтроллер частично Гарвардской архитектуры, т. е. шина данных и кода у него расположены отдельно. Однако у чипа есть полноценный MMU, который позволяет маппить регионы физической памяти в виртуальную память, чем мы и воспользуемся в итоге!
Заголовок нашего бинарника будет выглядеть вот так:
Программа общается с основной прошивкой посредством псевдо-syscall'ов: функции, которая в качестве первого аргумента ожидает номер нужной службы и один 32х-битный указатель для описания структуры с параметрами. Реализация syscall'ов — одна из самых простых и неприхотливых с точки зрения обратной совместимости с будущими прошивками.
Концептуально всё очень просто: GetGlobalStateSize сообщает нашему загрузчику размер структуры для хранения глобального стейта, в то время как Start уже фактически заменяет main() в нашей программе. Необходимости в crt0 нет, поскольку весь необходимый инит выполняет бутлоадер ESP32. Впрочем, при желании вы можете выделить отдельный стек для вашей программы — это повысит надежность, если выполняемая программа удумает испортить стек.
Собираем нашу программу:
xtensa-esp32-elf-cc.exe test.c -fno-pic -nostdlib -nostartfiles -Wl,--section-start=.text=0x0
xtensa-esp32-elf-objcopy.exe --only-section=.text --output-target binary a.out run.bin
-fno-pic отключает генерацию кода, зависимого от GOT, -nostdlib и -nostartfiles убирает из билда crt0 и stdlib, благодаря чему мы получаем только необходимый код. --section-start задает смещение для загрузки секции .text на 0x0 (в идеале это делать необходимо из скрипта для ld).
objcopy скопирует из полученного ELF только необходимую нам секцию .text.
Как же это работает на практике? Давайте дизассемблируем выходной бинарник и посмотрим, что у нас дает на выхлопе cc:
Обратите внимание, что Start вызывает подфункции с помощью инструкции CALLX8, которая в отличии от обычного Immediate-версии CALL8, выполняет переход относительно текущего адреса в PC, благодаря чему переход полностью независим от адреса загрузки программы в памяти. А благодаря тому, что все данные, в том числе и указатель на глобальный стейт передаются через стек, нет необходимости релокейтить сегменты данных.
По итогу всё, что нужно от загрузчика бинарников — это загрузить программу в память для инструкций, выделить память для структуры с стейтом программы и передать управление Start. Всё!
Конкретно в случае ESP32, у нас есть два возможных решения задачи загрузки программы в память:
Загрузить программу в IRAM. Такая возможность теоретически есть, однако на практике загрузчик ESP32 устанавливает права только на чтение и выполнение на данный регион памяти. Попытка что-то скопировать туда закончится исключением SIGSEGV. Кроме того, сегмент IRAM относительно небольшой — всего около 200Кб.
Самопрограммирование. Для этого, в esp32 есть два механизма — Partition API и SPI Flash API. Я выбрал Partition API для простоты реализации.
Для нашей прошивки необходимо будет переразметить флэш-память. Для этого запускаем idf.py menuconfig, идём в Partition Table -> Custom partition table CSV. Создаём в папке проекта partitions.csv, куда пишем:
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
executable, data, undefined, 0x110000, 0x10000
Для заливки программы можно использовать соответствующее Partition API, либо parttool.py:
parttool.py --port "COM41" write_partition --partition-name=executable --input "run.bin"
Переходим к загрузчику программы:
Прошиваем ESP32:
И смотрим результат:
SysCall 25
SysCall 35
SysCall 15
Всё работает!
❯ Заключение
Как видите, ничего сложного в выполнении сторонних программ при условии соблюдении некоторых ограничений нет. Да, в таком подходе есть как серьезные плюсы, так и минусы, однако он делает своё дело и позволяет реализовать запуск игр на кастомных игровых консолях, или сторонних программ на самодельных компьютерах. Ну и конечно же не стоит забывать про плагины! Авось в вашем решении нужна возможность расширения функционала устройства, однако предоставлять исходный код или даже объектные файлы нет возможности — тогда вам может пригодится и такая методика.
Пожалуй, стоит упомянуть ещё один… очень своеобразный метод, который я иногда встречаю при реализации самодельных компьютеров. Люди пишут… эмуляторы 6502/Z80 :)
И если такой подход ещё +- применим к ESP32, то в AVR просадки производительности будут слишком серьезными. Так зачем, если можно использовать все возможности ядра на максимум?