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

Arduino

Мультисенсорный беспроводной датчик с E-Ink дисплеем

08.04.2021 12:19:54 | Автор: admin
Приветствую всех читателей Хабра и особенно читателей раздела DIY или Сделай сам! В сегодняшней статье я расскажу о своем очередном DIY проекте из серии устройств с дисплеями на электронных чернилах(e-ink). Устройство о котором пойдет речь это беспроводной мультисенсорный датчик с e-paper дисплеем 2.13 дюймов. На датчик можно установить сенсор температуры и влажности SHT21, HTU21D, SI7021, сенсор температуры влажности и давления BME280, сенсор атмосферного давления BMP280, сенсор освещенности MAX44009. Датчик работает от одной батарейки CR2450. Но ничего не мешает напаять на датчик держатель под батарейки CR2430 или CR2477.




Проект датчика с e-ink дисплеем размером 2.13 дюймов начинался достаточно давно. Первый прототип был сделан более года назад. Та первая версия работала на двух батарейках cr2450, имела стабилизированное питание. Со временем проект изменялся и оптимизировался, уменьшались размеры, менялись радио модули и сенсоры.


Плата окончательной версии датчика имеет размеры 72 mm * 31 mm, толщина текстолита 1.2mm. Размеры датчика в корпусе 76mm * 35mm * 12mm.
Устройство работает на микроконтроллере nRF52840, используется радио модуль MS88SF3 от компании MINEW. Модуль не имеет боковых падов для пайки, они расположены снизу радио модуля. Эта особенность немного напрягала, но глаза боятся, а руки делают. В итоге модуль достаточно просто напаивается феном (плату устройства, на которую устанавливался радио модуль я грел снизу).


Устройство имеет две модификации платы. В модификации А на датчике установлен сенсор BME280, светодиод, в модификации B добавлен датчик освещенности, датчики температуры и влажности SHT21, HTU21D, SI7021, добавлена возможность установки сенсора BMP280, добавлена защита от переполюсовки на транзисторе.




В модификации B место под пайку сенсоров BME280 и BMP280 сделал универсальным, BMP280 отлично устанавливается на место BME280. Это изменение я сделал уже в крайней ревизии второй версии датчика. Причиной стало резкое удорожание сенсоров BME (в среднем на 70% на последние два месяца). Теперь появилась возможность заменить функционал BME280 установив на плату BMP280 + SHT21 (серия BMP пока не поднимается в цене). Если кому-то известна причина такого роста цен на сенсоры BME, расскажите об этом в комментариях.


Корпус датчика был напечатан на FDM 3D принтере. После печати корпус дополнительно шлифовался и полировался. Для светодиода в модификации А и сенсора освещенности в модификации B в верхней части корпуса на внутренней стороне имеются углубления для последующего сверления отверстий. Просверленные отверстия я заливал полимерной смолой для SLA принтера.


Программа датчика написана под опенсорс проект MySensors. Датчик выводит на дисплей данные с сенсоров, заряд батарейки, уровень сигнала, прогноз изменения погоды на ближайшие часы. Рядом с данными с сенсоров так же выводится стрелками направление изменения значений. Было несколько вариантов дизайна интерфейса, варианты 2 и 3 доступны на моем гитхаб.






Есть возможность по нажатию кнопки инвертировать экран. На кнопку добавлен функционал простого меню с пунктами: инвертирование цвета, конфигурация устройства, презентация устройства, сброс датчика. В режиме конфигурации датчик в течение 20 секунд слушает эфир, в это время можно с контроллера УД отправить на датчик конфигурационные команды: изменение интервала отправки данных с сенсоров(от 1 минуты до 1 часа с шагом в 1 минуту), изменение интервала отправки данных о состояния батареи и уровне сигнала(от 1 часа до 24 часов). В режиме презентации устройство отправляет на контроллер УД данные о себе(название, версия прошивки) и о сенсорах, делает запрос о том в какой системе(метрическая или имперская) работает сеть. Так же отправляет свои конфигурационные настройки.

При работе в радиосети датчик передает данные:
  • Температура,
  • Влажность,
  • Атмосферное давление,
  • Уровень освещенности,
  • Прогноз погоды,
  • Уровень сигнала,
  • Уровень заряда батарейки,
  • Причина перезагрузки


Если сеть работает в метрической системе, то данные о температуре отправляются и выводятся на экран в Цельсиях, а данные об атмосферном давлении в миллиметрах ртутного столба(только при компиляции RU версии), иначе температура выводится в Фарингейтах, а атмосферное давление в Паскалях.

Перед компиляцией программы необходимо внести изменения в конфигурационный файл aConfig.h.
Какая языковая версия будет скомпелированна(RU или ENG):
#define LANG_RU

Вывод дебага в сериал:
#define MY_DEBUG

Мощность радиопередатчика:
#define MY_NRF5_ESB_PA_LEVEL (0x8UL)

Скорость передачи данных:
#define MY_NRF5_ESB_MODE (NRF5_1MBPS)


Потребление устройства в режиме сна 5 мкА, в режиме чтения сенсоров и обновления экрана 2-3 мА. В режиме передачи данных 8 мА, в режиме прослушивания 5мА. Время обновления экрана 300мс, время передачи одного сообщения с данными сенсоров 10мс, время передачи сообщения о заряде батареи с ожиданием эхо 100-300мс. Срок работы на одной батарейке CR2450 год и более(с конфигурацией опроса сенсоров раз в минуту и отправкой данных при изменении, опросе напряжения батарейки один раз в 6 часов и обязательной отправкой без сравнения).

Видео с демонстрацией работы датчика:

Рекомендую подписалтся на мой домашний канал, на нем я впервую очередь публикую самую свежую информацию о своих новых опенсорс проектах, их тестах.


Фото датчика:















GitHub проекта github.com/smartboxchannel/

В файле readme находится инструкция по установке и настройке среды для редактирования и компиляции ПО для датчика.

Если вам интересно все что связано с DIY, вы являетесть DIY разработчиком или хотите только начать, вам интересно использование DIY девайсов, а так же хотите узнавать первыми о моих проектах, то приглашаю всех заинтересованных в телеграм чат DIYDEV.

Всем, кто хочет делать устройства, начать строить автоматизацию своего дома, я предлагаю познакомиться с простым в освоении протоколом Mysensors телеграм-чат MySensors

А тем кто ищет достаточно взрослые решения для домашней автоматизации приглашаю в телеграм-чат Open Thread. (что такое Thread?)

Спасибо за внимание, всем добра!

Подробнее..

Начинаем писать под stm8, выбираем среды разработки и стартуем

28.04.2021 12:07:29 | Автор: admin
image

На пути в программировании stm8 есть развилка, о ней сегодня и поговорим.

Определимся что речь будет идти о средах которые могут писать под си. Для начала поговорим о подходах, я выделю 2 основных.

Первый установка ST Visual Develop и выбор в качестве компилятора COSMIC Бывший платный, а ныне бесплатный, но со своими заморочками; регистрация, получение ключа, и прочие танцы с бубном.

Второй же вариант, более простой VS Code + PlatformIO и компилятор SDCC полностью свободный. И опять же не все так просто. Sdcc не умеет исключать не используемые функции. Я решил этот вопрос хоть и успешно, но не без дополнительных действий при написании кода.

Первая среда, для любителей всё делать правильно


Для начала нам нужен ST Visual Develop. Устанавливаем и ставим запуск ярлыка всегда от администратора. В придачу к нему нам дают ST Visual Programmer, полезный инструмент, особенно когда стоит защита от записи и надо разблокировать микроконтроллер, а ведь китайские blue pill всегда приходят заблокированными. Китайцы бояться что мы украдём их круто оптимизированный Blink.

Вот так выглядит STVD
image
Я так понял её создали, когда в моде были 16 битные цвета...

Дальше нужно будет получить компилятор COSMIC и его лицензионный ключ. Заполняем то что просят, получаем дистрибутив и делаем запрос ключа по электронной почте (тут рулетка кому то сразу придёт, кому то придётся подождать).

После пройденного лабиринта из форм и запросов, когда всё уже установлено, начнём
image
image
При первом запуске нужно указать расположение ключа, его лучше поместить в директорию компилятора. После создания нажимаем F7, ошибок быть не должно. Если писать на чистых регистрах, то всё готово, но я такой хардкор не люблю, поэтому продолжим и добавим SPL библиотеку.

Распакуем куда-нибудь и заходим в папку STM8S_StdPeriph_Lib\Project\STM8S_StdPeriph_Template. Тут у нас шаблон проекта stm8s_conf.h это конфигурационный файл библиотеки, через него выбирается контроллер. Зайдём в main тут сразу с первых строк #include "stm8s.h" это ссылка на основную библиотеку, а так же кусок кода отладки который начинается с #ifdef USE_FULL_ASSERT, без отладочного кода будут сыпаться ошибки.

Теперь когда мы прошлись по верхам давайте пробовать запускать библиотеку. Добавляем в проект из шаблона main и конфигурационный файл в. В include files добавляем всё из STM8S_StdPeriph_Lib\Libraries\STM8S_StdPeriph_Driver\inc.
image
Теперь всё должно собраться.

Добавим stm8s_gpio.c и соберём простецкую мигалку. У меня один из светодиодов висит на D3, конфигурация ноги на выход выглядит так:

GPIO_DeInit(GPIOD);GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW);

Её вписываем в main до бесконечного цикла.

А вот функция смены состояния. GPIO_WriteReverse(GPIOD, GPIO_PIN_3); вписываем её в бесконечный цикл.

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

void Delay(uint16_t nCount){  /* Decrement nCount value */  while (nCount != 0)  {    nCount--;  }}

Впишем её в конец перед #ifdef USE_FULL_ASSERT. Так же впишем её прототип в начало, где под это выделено место в шаблонном main.

/* Private function prototypes -----------------------------------------------*/void Delay (uint16_t nCount);

Ну и наконец впишем функцию со значением в бесконечный цикл после функции смены состояния: Delay(0xFFFF);

Подключаем ST-Link и прошиваем, для этого нажимаем Start Debugging и Run. Светодиод моргает значит всё хорошо.

У кого не получилось вот полный main.c
/**  ******************************************************************************  * @file    Project/main.c   * @author  MCD Application Team  * @version V2.3.0  * @date    16-June-2017  * @brief   Main program body   ******************************************************************************  * @attention  *  * <h2><center> COPYRIGHT 2014 STMicroelectronics</center></h2>  *  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");  * You may not use this file except in compliance with the License.  * You may obtain a copy of the License at:  *  *        http://www.st.com/software_license_agreement_liberty_v2  *  * Unless required by applicable law or agreed to in writing, software   * distributed under the License is distributed on an "AS IS" BASIS,   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  *  ******************************************************************************  */ /* Includes ------------------------------------------------------------------*/#include "stm8s.h"/* Private defines -----------------------------------------------------------*//* Private function prototypes -----------------------------------------------*/void Delay (uint16_t nCount);/* Private functions ---------------------------------------------------------*/void main(void){GPIO_DeInit(GPIOD);GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW);  /* Infinite loop */  while (1)  {GPIO_WriteReverse(GPIOD, GPIO_PIN_3);    Delay(0xFFFF);  }  }void Delay(uint16_t nCount){  /* Decrement nCount value */  while (nCount != 0)  {    nCount--;  }}#ifdef USE_FULL_ASSERT/**  * @brief  Reports the name of the source file and the source line number  *   where the assert_param error has occurred.  * @param file: pointer to the source file name  * @param line: assert_param error line source number  * @retval : None  */void assert_failed(u8* file, u32 line){   /* User can add his own implementation to report the file name and line number,     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */  /* Infinite loop */  while (1)  {  }}#endif/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


Теперь посмотрим со стороны на эту среду.

По плюсам; у неё есть полноценная отладка, поддержка SPL из коробки. По минусам; она старая из этого вытекает, не очень приятный интерфейс и старый диалект си, на который многие свежие библиотеки придётся переписывать, в частности ставить переменные только вначале функций. Вес кода оставляет желать лучшего. Ну последний камень, этот инструмент может просто взять и вылететь, такое бывает, нечасто, но всё же.

Вторая среда, для тех кто не любит заморачиваться.


Второй подход это свободный и обновляемый компилятор SDCC, а так же среда PlatformIO.

Для начала установим VS Code и станем рабами Microsoft, далее найдём расширение PlatformIO.

image

Ждём пока миллион ползунков пройдёт до конца и перезапускаем программу. Открываем расширение (может быть и само откроется). Создаём новый проект и выбираем ближайшую плату с stm8s (микроконтроллер можно будет изменить в конфигурационном файле). В качестве фреймворка выбираем SPL мы же не ардуинщики, нас интересует хардкор.

Не удивляйтесь, проект будет создаваться прилично долго, потому как он на ходу будет подгружать компилятор, библиотеки и тд. И вот перед нами возник девственно голый проект, закрываем его он нам больше не нужен. В меню где мы создавали проект, открываем пример spl-blink, суть в том что blink генерирует неплохой шаблон в котором можно сразу писать. Правим пример под себя и прошиваем, всё моргает.

Разберем поподробнее среду разработки. Во первых весь проект должен лежать в src, иначе среда ведёт себя неадекватно. Во вторых открываем stm8s_conf.h и видим что все библиотеки кроме GPIO закомментированы, если этого не сделать то у мк не хватит памяти что бы поместить весь SPL в микроконтроллер (помните в начале я говорил что он загружает все функции что видит в код?).

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

/* Private define ------------------------------------------------------------*/#define _GPIO_DeInit#define _GPIO_Init#define _GPIO_WriteReverse#define _CLK_DeInit#define _CLK_SYSCLKConfig#define _TIM4_DeInit#define _TIM4_ITConfig#define _TIM4_ClearITPendingBit#define _TIM4_Cmd#define _TIM4_TimeBaseInit#define _TIM4_ClearFlag#define _HAL_GPIO_WritePin#define _GPIO_WriteLow#define _GPIO_WriteHigh//#define STM8S003/* Includes ------------------------------------------------------------------*/#include "stm8s.h"/* Uncomment the line below to enable peripheral header file inclusion */#if defined(STM8S105) || defined(STM8S005) || defined(STM8S103) || defined(STM8S003) ||\    defined(STM8S001) || defined(STM8S903) || defined (STM8AF626x) || defined (STM8AF622x)// #include "stm8s_adc1.h" #endif /* (STM8S105) ||(STM8S103) || (STM8S001) || (STM8S903) || (STM8AF626x) */#if defined(STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) ||\    defined (STM8AF62Ax)// #include "stm8s_adc2.h"


Каждую функцию я включаю через макрос, для этого у меня переписана большая часть SPL. Если вам оптимизация сильно не нужна, то такой упоротостью можете не заниматься.

Пройдёмся по преимуществам: работает почти из коробки, полностью бесплатно без попрошайничества, редакции языка обновляются и не придётся учить и переписывать код под си 80-90г. Сам интерфейс настраиваемый и намного приятнее. Для тех кто не любит win есть linux версия.

По минусам: нету полноценной отладки (над ней активно работают, но пока ничего приближённого к cosmic я не видел), в проекте небольшой хаос, раскидать по папкам пока нельзя.

Послевкусие.


Ну и на последок есть ещё среды, варианты и компиляторы, но либо это тот же SDCC вкрученный силой в Eclipse или ещё куда и работающий хуже чем в VS Code, либо это платные варианты IAR, Raisonance. Я лично пользуюсь и тем и тем, но чаще VS Code. Рекомендовать ничего не буду каждому своё, увидимся в комментариях)

Подробнее..

SOHO UPS в маленьком корпусе и своими руками. Менее чем за1500 руб

10.05.2021 12:10:00 | Автор: admin

Хотите обеспечить бесперебойное питание своим устройствам, но при этом не сильно потратиться? Именнотакой своей разработкой я и хотел с вами поделиться.

Все мы переживаем, когда устройства внезапно отключаются по питанию и не зря. Большая часть нештатного отключения электроэнергии сопровождается скачками повышенного напряжения, что в свою очередь может привести к поломке оборудования или сбросу настроек. Да, на этот случай различные компании выпускают ИБП, но они достаточно велики и весят как правило не менее нескольких килограмм.

А что если сделать такой источник бесперебойного питания, который можно поставить прямо рядом с защищаемым устройством лёгкое, компактное, недорогое?

Почему я об этом задумался?


Я живу в частном доме и моя работа на 100% зависит от доступности интернета.
Но так уж получилось, что в нашем районе Ленинградской области ситуация с энергоснабжением обстоит очень печально. Достаточно частыеотключении при резком изменении погоды,изношенные высоковольтные линии идущие к нам и прочее.Соответственно при аварии на электросетях падает вся сетевая инфраструктура и пока всё поднимется, восстановятся все маршруты (OSPF)пройдет минимум 2-3 минуты. Также стоит вспомнить об опасности таких отключений для самого оборудования. На запуск и ввод резервного источника питания (генератор) необходимо примерно 5-10 минут.

В данной ситуации UPS не роскошь он необходим как воздух.

Сетевая инфраструктура у меня построена на оборудовании MikroTik, оно простое но его достаточно много:
  • 951Ui-2HnD пограничный маршрутизатор в который приходит интернет от Cambium (радио-мост до БС МТС), также он защищает сеть и на нем поднят VPN-сервер для удаленного доступа.
  • hEX PoE выполняет роль маршрутизатора локальной сети и контроллера CAPsMAN.
  • CSS106-5G-1S в серверном шкафу
  • 3 штуки hAP Lite Wi-Fi точкидоступа для бесшовного роуминга. Их много, они раскиданы по всей территории и все на маленькой мощности. Используются только для мобильных устройств и умного дома.
  • OmtiTik5ac PoE и SXTsq Lite5 радиолинк до второго дома
  • BaseBox2 уличная точка доступа.

Питать всё этоот одного классического UPS не реально оборудование раскидано по территории. Во вторых при моих условиях АКБ внутри классического бесперебойника умирает примерно за 1.5 года, а стоимость новой батареи достаточно высока.

Постановка задачи


Я периодическидумал как решить данную задачуи принял решение сделать свой ИБП обладающий характеристиками:
  • Прост в разработке, желательно на готовых модулях
  • Недорого, чтобы можно было поставить возле каждого роутера Регулируемое выходное напряжение можно запитать не только оборудование с 12/24В роутеры / коммутаторы, но и, например, Intel NUC (у него 19В)
  • Размер корпуса не больше чем уhEX PoEдля сборки в виде модуля ИБП+Роутер

При детальном рассмотрении задачи и всего зоопарка оборудования я понял, что hAP Lite это слабое звено во всей цепочке. Во первых ему нужно 5В (всем остальным от 12 до 48), во вторых у него micro-usb разъем питания и нет PoE-in. Поэтому данные устройства были выведены изсписка защищаемых и при отключении ЭЭ они падают как и раньше.

В процессе раздумий над схемой я понял, что лучше использовать в качестве базового напряжения АКБ 12В, а дальше, по необходимости менять преобразователи на повышающий или понижающий. Это сделает UPSуниверсальным и позволит питать устройства в диапазоне от 1 до 48В, также снизит стоимость устройства за счет снижения количества АКБ до 3х.

Подбор компонентов


Для сборки нужны детали:
Цены указываю при покупке на территории РФ. Если брать у наших соседей, то стоимость будет ниже примерно на 60%, а т.к плата все равно будет ехать из-за бугра, то и детали можно смело брать там.
  1. Модуль заряда аккумуляторов 3S, 10A 1 шт. (180 руб)
  2. Повышающий (понижающий) DC-DC преобразователь XL6009 1 шт. (120 руб)
  3. Батарейный отсек 1х18650 на плату 3 шт. (150 руб)
  4. Гнездо питания на плату 5.5х2.1 (от 2 до 4 штук)
  5. Вольтметр 0.28" 0-100В (опционально)
  6. Диод Шотки SS34, 3А 3 шт.
  7. Резистор SMD 1206, 200R 1 шт
  8. Резистор SMD 1206, 1K 1 шт
  9. Стабилитрон 3.3В,BZX55C3V3 2 шт.
  10. Светодиод SMD 1206 2 шт.

Итого: 450 руб.
Изготовление печатной платы на jlcpcb с доставкой в РФ 750 руб. за 5 штук. (150 руб/шт)

3 аккумулятора размера 18650. Средняя стоимость 300 руб.

Итого общаястоимость за одно устройство: 1500 руб.

Обратите внимание, на АКБ нельзя экономить! Брать не явный Китай и желательно высокотоковый!
Нам не нужны повторения историй, коих и так увы очень много последнее время по всем федеральным каналам. АКБне обязательно должен быть с защитой, ввиду того, что плата заряда аккумулятора, используемая нами уже имеет защиту от чрезмерного заряда/разряда.

Тест взрывоопасности АКБ 18650
Сразу привожу наглядный тест на безопасность именно АКБ 18650. Вариант пробития гвоздем не рассматриваем ввиду нереальности https://www.youtube.com/watch?v=tOsxiLKyKwQ

Принцип работы


Принципиальная схема данного устройства очень простая


Итак унас есть один входной разъем питания (Vin), и три выходных (Vout). XP1 это стандартная гребенка PLS с шагом 2.54, к которойподключается кнопка включения питания, а также можно поставить джампер (как в моем случае), если планируется все время держать устройство во включенном состоянии.
Также на плате есть два светодиода, показывающие наличие напряжение во входной сети (Vin) и напряжения на выходе устройства (Vout), подключенные через стабилитрон (D1, D2) на 3В и резисторы (на нижней стороне платы)R2 220 Ом и R1 1кОм соответственно.
U6 это контакты для подключения модуля вольтметра, который отображает напряжение на выходе устройства.

Верхняя сторона платы

На нижней стороне платыу нас размещен контроллер заряда (U2) и три диода Шоттки (U3, U4, U5).

Нижняя сторона платы

Основной принцип работы схемы и переключения с основного на резервное питание зависит от трех диодов Шоттки U3, U4, U5.
Ниже представлена нагляднаясхема направления и какие узлы в каких ситуациях находятся под напряжением.


U4 пропускает напряжениетолько в направлении контроллера заряда, напряжение с контроллера непопадает обратно во входную сеть. Это достаточно важный диод, т.к при его отсутствии напряжение будет утекать из модуля заряда (АКБ) в направлении источника питания.

Розовым цветом показана ситуация, когда у нас присутствует напряжение во входной сети (Vin). В этом случае диоды U3 и U4 пропускают напряжение в направлении контроллера заряда (U2) и DC/DC-преобразователя (U1). При этом напряжение из АКБ и контроллера заряда (голубой маршрут) не поступает в розовую сеть через диоды U4 и U5.

U5 работает таким образом, что пока входное напряжение присутствует, на его катоде будет +, он будет в закрытом состоянии и не выпуститнапряжение из АКБ в направлении Vout, а также не пропустит напряжение из входной сети. Если же, напряжениена входе пропало U5тут же перейдет в свое рабочее состояние и пропуститнапряжение с АКБ в сторону DC/DC-преобразователя (U1) зеленый маршрут. Однако чтобы исключить петлю когда напряжение из АКБ попадает на вход модуля заряда, а также может утекать в источник питания на входе, мы используем диод U3 и пока на его катоде будет +, он будет закрыт.

Платы, полученные от jlcpcb как всегда отличные, здесь на самом деле придраться не к чему настоящее промышленное производство за очень гуманную плату. Срок изготовления 3-4 дня, срок доставки до Ленинградской области в районе 20 дней.


Распаиваем, проверяем


Печатаем корпус, собираем устройство и вот что у нас получилось




Проверка устройства под нагрузкой


Теперь, когда устройство собрано и мы знаем как оно работает, нам нужно запомнить, что мы можем от него питать. Самое главное это помнить какие токи потребления может обеспечить данное устройство. В схеме я использую преобразователь на 3А. Ток разряда АКБ 18650, как правило, равен двух-кратной величине ёмкости (если не рассматриваем высокотоковые). Таким образом при использовании аккумулятором емкостью 2000 mA, они способны отдавать ток до 4А.
Однако стоит помнить, что если мы на DC/DC-преобразователе увеличили выходное напряжение вдвое, например питаем оборудование от 24В током 1А, тоток до преобразователя также увеличитсявдвое и АКБ будут отдавать заряд током 2А.

Соответсвенно лучшезапомнитьтакую закономерность:
  • 12В 3А
  • 24В 1.5А
  • 48В 0.75А

Проводим нагрузочный тест и определяем время автономной работы
В UPS установлены АКБ GoPower на 2000 мА. Выходное напряжение 12В.К UPS подключено 3 устройства hEX PoE к которому, в свою очередь, через PoE-out подключены CSS106-5G-1S и951Ui-2HnD. Трафик в сети, на момент отключения входного питания продолжает бегать.

Итого суммарное потребление всех устройств составило порядка 0.55-0.65А (менялось в процессе измерений).CSS106-5G-1S 185мА,951Ui-2HnD 280мА плюс собственное потребление hEX. До отключения данная сборкапроработала 2 часа 15 минут, при этом остаточное напряжение на трех аккумуляторах составило 6.5В. Сильнее разрядить не получилось, сработала защита от глубокого разряда на модуле 3S. Температура аккумуляторов не изменилась, что говорит о несущественной нагрузке в процессе разряда.

Вывод


Таким образом я получил небольшое устройство, способное эффективно питать несколько роутеров при наличии PoE-out, ав случае отсутствия возможность разместить UPS непосредственно возле устройства и при этом при минимальных затратах.

Надеюсь данная статья будет полезна и вам!

Материалы из статьи
Макет схемы, печатной платы в формате DipTrace, а корпус в STL для печати на 3D-принтере

Подробнее..

Миниатюрный датчик качества воздуха на батарейке с e-ink экраном

21.06.2021 12:17:59 | Автор: admin
Приветствую всех читателей Habr! В своей сегодняшней статье, хочу рассказать вам о своем новом DIY беспроводном устройстве датчике качества воздуха. Помимо оценки качества воздуха, датчик может оценивать уровень освещенности в помещении, температуру, влажность и атмосферное давление, на основе данных атмосферного давления, устройство может предсказывать прогноз погоды. Это полностью открытый проект.



Внутреннее устройство


Датчик работает на микроконтроллерах nRF52, были разработаны 4 версии плат датчика под радиомодули nRF52 разных производителей. Одна основная и еще три расширенные версии (пояснения будут чуть ниже по тексту).

Используемые в проекте модели радиомодулей:

  • основной MINEW MS88SF3 (nRF52833, nRF52840)
  • дополнительные: MINEW MS50SFA1 (nRF52810, nRF52811), MINEW MS50SFA2 (nRF52832), EBYTE E73-2G4M08S1C (nRF52840) и EBYTE E73-2G4M08S1E (nRF52833)

Используемые в проекте сенсоры:

  • сенсор качества воздуха в помещении для измерения ЛОС SGP40
  • сенсор давления, температуры и влажности BME280
  • сенсор освещенности MAX44009

Позднее, из-за проблем с производством электронных компонентов и невероятном росте цен на многие компоненты, в проект были добавлены сенсоры BMP280 и SHTC3 которые по функционалу способны заменить сенсор BME280. По этой причине, были сделаны три дополнительные модификации плат, так же добавлена поддержка дополнительных радиомодулей, добавлена защита от переполюсовки, доработан дизайн плат.

Устройство может выводить данные на экране и передавать данные в системы Умного Дома, так же может работать в режиме без сети.

Для вывода информации использовался e-ink дисплей со сверхнизким потреблением и диагональю 2.13 дюймов компании WaveShare.



Характеристики дисплея:

  • Разрешение: 250x122
  • Диапазон рабочих температур: 0 50 C
  • Потребление в рабочем режиме: 3мА
  • Потребление в режиме глубокого сна: 1мкА
  • Минимальное время обновления экрана: 0.3 сек.

В ближайшее время в проект будет добавлена поддержка дисплея DES e-Ink 2.13 c рабочим температурным режимом -20C~60C (что такое DES).
..upd Пока статья писалась сделал драйвер, дисплей протестирован, в морозильнике работает :), из минусов разрешение 212х104, но зато морозов не боится, в общем рабочий вариант.


Основная версия PCB датчика:

Дополнительные версии:



Основным сенсором в данном проекте является сенсор качества воздуха в помещении SGP40. Можно сказать что это новинка на рынке от компании Sensorion c весьма неплохими характеристиками.


Сенсор измеряет общую концентрации летучих органических веществ (TVOC). В сравнении с предыдущим датчиком этой компании SGP30 потребление было значительно снижено, 48 мА при измерении у SGP30 и 2.6мА у SGP40. Правда предыдущий датчик мог отдавать уже готовые значения VOC и эквивалента СО2, в то время как новинка отдает сырые данные которые в дальнейшем надо обрабатывать на стороне МК при помощи поставляемой с датчиком библиотеки с алгоритмом расчета качества воздуха. Даташит на датчик SGP40.


Для работы в батарейном и низко потребляющем устройстве пришлось доработать библиотеку Adafruit_SGP40. Была добавлена работа с нагревателем сенсора, получение, сохранение, выгрузка текущих состояний алгоритма для быстрого старта датчика, например после замены батарейки, минуя режим обучения. Почему-то никто не озадачился этими моментами, найти готовую библиотеку поддерживающую полный функционал сенсора мне не удалось. Модифицированная библиотека находится на моем GitHub.

Схема устройства:



Передача датчиком данных с сенсоров в системы Умного Дома реализована на открытом проекте MySENSORS.




Функционал датчика


Устройство, при подаче питания, осуществляет попытку поиска сети, если сеть не найдена, то устройство переходит в основной режим работы без работы в сети (не шлет данные), но периодически делает короткие запросы на поиск сети(~раз в 2 часа). Интервал опроса сенсора SGP40 3 секунды, чтение остальных сенсоров, отправка данных, основное обновление экрана раз в 1 минуту. Обновление экрана и отправка данных(если сеть доступна) происходит при изменении данных уровня качества воздуха (TVOC) на 10 единиц, температуры на 0.5C, влажности на 5%, давления на 1 единицу, при изменении уровня освещенности на 10 люкс, при изменении прогноза по погоде. Интервал опроса батарейки задается пользователем в интервале от 1 часа до 24 часов, по умолчанию опрос один раз в 6 часов.
Так же есть дополнительная подпрограмма для обновления экрана и отправка данных при резком повышении уровня TVOC на 30 единиц, интервал проверки раз в 6 секунд.

При первом включении устройства, происходит цикл обучения алгоритма расчета качества воздуха, в моей реализации максимальное время обучения 12 часов. После обучения, датчик начинает сохранять в памяти МК текущие состояния алгоритма с четырехчасовым интервалом. При сбросе устройства, при возобновлении работы после выключения устройства, при замене батареек происходит проверка наличия записей состояний алгоритма в памяти, если они есть то эти данные выгружаются, и устройство минует период обучения. Для удаления сохраненных данных, необходимо нажать на кнопку меню на устройстве и выбрать соответствующий пункт меню. сброс устройства.

Доступный функционал кнопки меню:

  1. Инверсия экрана
  2. Отправка презентации
  3. Вход в режим конфигурации внешними командами по радио
  4. Поиск сети
  5. Сброс устройства

Так же, помимо кнопки меню, датчик может настраиваться внешними командами из интерфейса УД. Для этого необходимо активировать нужный пункт меню конфигурация датчика нажатием кнопки меню. После активации режима конфигурации, датчик перейдет в режим прослушивания на 20 секунд. В этот интервал необходимо отправить команду. Внешними командами можно настроить интервал проверки батарейки, изменить вывод информации на экран в инверсии, выбор режима работы: LP (чтение сенсора SGP40 раз в 3 секунды) или ULP (чтение сенсора SGP40 раз в 5 секунд).

Датчик умеет анализировать данные атмосферного давления и рассчитывать по ним прогноз погоды, выводить на экран данные о прогнозе погоды и отправлять эти значения в УД. Описание алгоритма расчета прогноза погоды (NXP Application Note 3914 | John B. Young)

На экране рядом с каждым типом данных выводится индикация направления изменения значений.



Для компиляции нужной версии ПО необходимо сконфигурировать файл aConfig.h.

//#define MY_DEBUG#define LANG_RU // If this is not used the English localization will be displayed.#ifndef LANG_RU#define LANG_EN#endif#define SN "eON Air Quality Sensor"#define SV "0.99"#define MY_RADIO_NRF5_ESB#define MY_NRF5_ESB_PA_LEVEL (0x8UL)//#define MY_PASSIVE_NODE//#define MY_NODE_ID 151//#define MY_NRF5_ESB_MODE (NRF5_1MBPS)#define MY_NRF5_ESB_MODE (NRF5_250KBPS)#define ESPECIALLY#define SEND_RESET_REASON#define MY_RESET_REASON_TEXT

Потребление датчика в режиме сна составляет в среднем 33мкА (смотрите даташит на SGP40), в режиме считывания сенсоров и обновления экрана 4мА(среднее), в режиме передачи данных 8мА(среднее), время передачи одного сообщения 10мc (идеальные условия).
Датчик работает от батарейки CR2477 (950мА), среднее расчетное время работы устройства 1 год(зависит от конфигурации прошивки, установленных сенсорах на устройстве, больше сенсоров больше данных нужно будет отправлять, а передача по воздуху это основной потребитель), данных о реальном сроке работы пока нет, устройство пока работает 2 месяца.



Модели разработанного корпуса датчика я печатал на FDM 3D принтере, что бы добиться более или менее приличного вида, корпус после печати шлифовался и полировался. На задней крышке корпуса можно установить магниты.



GitHub проекта github.com/smartboxchannel/

В файле readme находится инструкция по установке и настройке среды для редактирования и компиляции ПО для датчика.

OPEN SOURCE HARDWARE CERTIFICATION
OSHWA UID: RU000004


В завершении, уже как обычно, сделаю небольшой фото анонс проектов с которыми в скором времени поделюсь и о которых расскажу (Датчики влажности почвы Zigbee, Уличный датчик температуры и влажности Zigbee Long Range, Датчик качества воздуха bme680 c e-ink3.7).

Новые проекты на стадии тестирования












Если вам интересно все, что связано с DIY, вы являетесь DIY разработчиком или хотите только начать, вы заинтересованы в использовании DIY девайсов, а так же хотите узнавать первыми о моих проектах, то приглашаю всех в телеграм чат DIYDEV.

Если вы как и я, хотите понять что такое Zigbee, попытаться сделать свои первые DIY Zigbee устройства, то приглашаю вас в чат для разработчиков zigbee девайсов/прошивок ZIGDEV

Всем, кто хочет делать устройства, начать строить автоматизацию своего дома, я предлагаю познакомиться с простым в освоении протоколом Mysensors телеграм-чат MySensors

А тех кто смотрит в будущее IOT приглашаю в телеграм-чат Open Thread (Matter, Project CHIP). (что такое Thread?, что такое Matter?)

Спасибо за внимание, всем добра!


Подробнее..

Через тернии к звёздам или LILYGO TTGO T-Internet-POE ESP32 LAN8270A

15.03.2021 10:06:02 | Автор: admin
image
Попалась мне на глаза плата LILYGO TTGO T-Internet-POE ESP32 LAN8270A и конечно я не мог пройти мимо такой интересной новинки: ESP32, LAN8270A, POE, SD карта, Wi-Fi+Ethernet Было интересно пощупать это произведение сумрачного китайского гения своими руками и протестировать в реальной работе, ведь TTX платы сулили очень интересные перспективы для использования в IoT, DIY и вообще в области Wi-Fi+Ethernet и на что фантазии хватит.

Но, как всегда, путь от рекламных проспектов на сайтах продавцов и производителя до запуска платы и проведения на ней тестов оказался очень непростым и тернистым. Далее предлагаю вашему вниманию отчёт о моих увлекательных изысканиях по этой теме.

Камень в огород LILYGO


По моим наблюдениям (многие) производители железа страдают одной родовой болезнью полным отсутствием компетенции в маркетинге и вообще элементарного понимания того, что свои продукты они делают для людей.

Хорошим примером тут может служить LILYGO TTGO T-Internet-POE ESP32 LAN8270A (далее для краткости будем называть эту плату T-Internet-POE). Производитель сделал интересную плату, но не сделал больше ничего:

  • нет нормальной распиновки контроллера
  • нет принципиальной электрической схемы
  • нет вменяемого описания применения платы и типовых паттернов её использования
  • нет технических пояснений по работе отдельных составляющих платы
  • нет примеров кода (есть 1 (!) скетч на отвали, мальчик, не мешай работать)
  • нет сайта с документацией
  • нет форума с грамотными и мотивированными модераторами
  • нет популярных и мотивирующих статей для тех, кто интересуется этим контроллером, но не знает (не понимает) где он мог бы его применить для своих целей
  • и нет ещё множества вещей, которые должны были бы быть

Короче, нет вообще ничего и каждый, кто рискнёт купить T-Internet-POE, должен быть безупречным воином DIY, иначе у него нет ни одного шанса выстоять в этой битве с LILYGO. Много ли среди нас таких?

И как при таком подходе к делу они вообще умудряются что-то продавать? И насколько выросли бы их продажи, если бы они на минутку отложили в сторону паяльник и вспомнили о своих покупателях?

Вопросы риторические, но так или иначе далее мне придётся проделать всю работу за технический и маркетинговый отделы LILYGO.

В чём фишка?


Говоря простыми словами, на этой плате удалось более-менее удачно объединить в одном устройстве ESP32 (Wi-Fi), Ethernet, POE и ещё добавить к этому торту вишенку в виде microSD картридера. Из одного только сочетания этих составляющих сразу вытекает множество интересных вариантов применения этой платы:

  • работа по Wi-Fi с резервом в виде Ethernet канала
  • работа по Ethernet с резервом в виде Wi-Fi подключения
  • обслуживание одновременно и Wi-Fi и Ethernet линков
  • роутер между Wi-Fi и Ethernet в обе стороны
  • веб-сервер на два интерфейса
  • разные веб-сервера на разных интерфейсах
  • питание (удалённого) контроллера по POE

И множество других интересных вариантов (кстати, не нужно забывать, что кроме непосредственно сетевой составляющей, плата имеет GPIO выводы и может использоваться по своему прямому назначению, то есть в качестве IoT контроллера).

Как вы видите, сфера применения этой платы в IoT и DIY ограничена только вашей фантазией и вашими потребностями и в целом T-Internet-POE как устройство смотрится очень многообещающе.

Далее давайте попытаемся разобраться как со всем эти великолепием совладать, что, учитывая практически полное отсутствие информации по плате, является не такой простой задачей.

Технические характеристики


Мы здесь не будем приводить полный список всех технических характеристик платы вот с чем с чем, а с этим на сайтах продавцов и производителя проблем нет (проблема в том, что кроме этих характеристик там больше ничего нет). Приведём здесь только список ключевых элементов платы:

  • ESP32-WROOM (4 МБ)
  • LAN8720A (Ethernet PHY)
  • POE 802.3af
  • microSD картридер
  • 12 GPIO пинов для внешних подключений

О чём навскидку нам говорит такая конфигурация? О том, что при использовании этой платы в качестве веб-сервера, файлы можно хранить как на microSD карте памяти, так и во внутренней памяти модуля ESP32 (или и там и там сразу).

При этом 12 свободных GPIO производят двойственное впечатление с одной стороны это уже кое-что и значительно лучше чем на ESP8266, а с другой стороны после проектов на Mega 2560 с её десятками GPIO, 12 пинов смотрятся очень и очень скромно и сильно ограничивают возможности разработки тут нужно будет либо изобретать какие-то расширители портов, либо делать тандемные сборки с другими контроллерами.

Варианты контроллера


При ближайшем рассмотрении оказывается, что под одним названием существуют два разных контроллера один на ESP32-WROOM, а второй на ESP32-WROVER-B, что сходу и не разглядишь на вид платы практически одинаковые и можно играть в игру найди 10 отличий.

image

Мне достался контролер на ESP32-WROOM, поэтому дальнейшее повествование будет относится к нему.

Программатор


Инженеры LILYGO так далеко оторвались от своих пользователей, что их решения не всегда можно понять. К таким решениям относится создание ими отдельной платы программатора на чипе CP2104 для контроллера T-Internet-POE.

Зачем? Зачем нужен отдельный программатор, когда этот узел можно было интегрировать на саму плату контроллера или попросту использовать стандартные USB-TTL переходники (как делают все остальные производители железа)? Ответ, видимо, знают только разработчики LILYGO (но простим им этот маленький креатив).

image

Но мало того, что разработчики LILYGO сделали непонятную вещь, они ещё и умудрились сделать её криво:

  • во-первых они применили горячо любимые народом пины с шагом 2,0 мм
  • во-вторых они предусмотрели установку разъёма на обратную (!) сторону платы

(Разработчикам такого решения я бы порекомендовал иногда отвлекаться от работы и уделять время отдыху.)

В результате получился какой-то странный монстр. И всё бы ничего, если бы проблема ограничивалась только эстетической составляющей, но тут вылезают более серьёзные проблемы:

  • если устанавливать и крепить плату в нормальном положении, то пины программатора оказываются снизу платы и к ним невозможно подключиться без демонтажа контроллера;
  • если работать с платой без крепления то разъёмы с шагом 2,0 не обеспечивают должной жёсткости и вся конструкция грозит развалиться в любой момент и всё вокруг позамыкать.

В качестве нивелирования этого косяка разработчиков, можно порекомендовать припаивать линейку пинов с верхней стороны платы и сделать (или купить, если он продаётся) 6-пиновый 2,0 мм гибкий переходник.

Распиновка


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

image

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

Всего на ESP32 имеется 40 пинов (D0D39) из них 14 пинов

D6D11, D20, D24, D28-D31, D37, D38

мы исключаем из рассмотрения как практически неиспользуемые (по разным причинам, подробный разбор назначения этих пинов выходит за рамки этой статьи). Остаются:

Пины подключения Ethernet чипа LAN8720A


D18 ETH_MDIO_PIN
D19 ETH_TX_D0
D21 ETH_TX_EN
D22 ETH_TX_D1
D23 ETH_MDC_PIN
D25 ETH_RX_D0
D26 ETH_RX_D1
D27 ETH_RX_CRS

причём, D18 и D23 устанавливаются в скетче, а остальные 6 пинов чипа LAN8720A являются стандартными и задаются в библиотеке.

Поскольку производитель постеснялся предоставить принципиальную схему контроллера, то я здесь могу только привести аналогичную типовую схему подключения физики Ethernet на LAN8720A.

image

К LAN8720A также относится пин тактирования, который на плате T-Internet-POE подключён к D17 (тоже выбирается в скетче):

D17 ETH_CLOCK

и пин сброса

D5 NRST

microSD картридер


microSD картридер подключён на HSPI:

D2 SD_MISO
D12 SD_CS
D14 SD_SCLK
D15 SD_MOSI

и в случае своего использования забирает свободные для внешних подключений и выведенные на плату пины D2, D14, D15. Вопрос что выгоднее использовать картридер и потерять 3 из 12-и свободных пинов или сохранить 3 лишних GPIO и отказаться от картридера сродни вопросу что лучше: слон или конь? и вам каждый раз придётся отвечать на него при использовании платы T-Internet-POE.

Прочие пины


У нас остаются пины D0 (ETH_CLOCK, не задействован в этом качестве) и D1 (TX0) и D3 (RX0).

Свободные пины


Теперь переходим к самому интересному описанию свободных пинов, выведенных на плату контроллера.

Первой идёт группа D34, D35, D36, D39, работающая только на вход. Лучше конечно на вход, чем вообще ничего, но при таком дефиците GPIO было бы гораздо лучше, если бы эти четыре пина были полноценными GPIO.

И затем 8 полноценных GPIO, которые вы можете использовать в своих проектах. Тут нужно помнить, что хоть эти пины и являются полноценными GPIO, но некоторые из них работают весьма своеобразно (например меняют потенциал на старте контроллера и т.п.). Поэтому прежде, чем к ним что-то подключать, нужно специально выяснять и уточнять эти моменты.

D2 (SD_MISO)
D4
D12
D14 (SD_SCLK)
D15 (SD_MOSI)
D16
D32
D33

Как говорится, вот тебе, мой юный друг программирования и микроконтроллеров, 8 GPIO и ни в чём себе не отказывай.

POE


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

Здесь реализована полноценная поддержка стандарта POE 802.3af с развязкой и управлением питанием на чипе SI3404.

Меня дистанционная запитка контроллера не очень интересует, поэтому этот аспект работоспособности T-Internet-POE я не тестировал, но, судя по всему, с POE здесь проблем нет.

Программная поддержка


Как вы сами понимаете, работать с T-Internet-POE можно при помощи любых программных сред, имеющих представление об этом железе, в том числе в нативном SDK (и вероятно это наиболее правильный вариант), но мы попытаемся выяснить, что можно выжать из этой железки при помощи Arduino IDE.

В качестве программной среды для экспериментов использовались Arduino IDE версии 1.8.5 и ESP32-Arduino версии 1.0.5 (последняя сборка на момент написания статьи).

Сам процесс установки поддержки ESP32 в Arduino IDE я описывать не буду потому, что этому вопросу посвящено огромное количество материалов в интернете, во всех нюансах описывающих этот процесс.

Упомяну здесь только один момент: плюс ко всему, чего не имеет этот контроллер, он ещё не имеет и нативной поддержки в ESP32-Arduino версии 1.0.5. Поэтому в качестве контроллера в менеджере плат выбирался ESP32 DEV Module с настройками:

Flash Mode: DIO
Flash Size: 4MB (32 Mb)
Partition Scheme: 4MB (1,2MB/1,5MB)

Стандартный скетч


Ниже приведён скетч, которым нас порадовал производитель платы. Там особенно комментировать нечего, он просто инициализирует Ethernet интерфейс и посылает запросы к серверу в интернете.

Полный код скетча от производителя платы
/*    This sketch shows how to configure different external or internal clock sources for the Ethernet PHY*/#include <ETH.h>#include <SPI.h>#include <SD.h>#define SD_MISO         2#define SD_MOSI         15#define SD_SCLK         14#define SD_CS           13/*   * ETH_CLOCK_GPIO0_IN   - default: external clock from crystal oscillator   * ETH_CLOCK_GPIO0_OUT  - 50MHz clock from internal APLL output on GPIO0 - possibly an inverter is needed for LAN8720   * ETH_CLOCK_GPIO16_OUT - 50MHz clock from internal APLL output on GPIO16 - possibly an inverter is needed for LAN8720   * ETH_CLOCK_GPIO17_OUT - 50MHz clock from internal APLL inverted output on GPIO17 - tested with LAN8720*/// #define ETH_CLK_MODE    ETH_CLOCK_GPIO0_OUT          // Version with PSRAM#define ETH_CLK_MODE    ETH_CLOCK_GPIO17_OUT            // Version with not PSRAM// Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source)#define ETH_POWER_PIN   -1// Type of the Ethernet PHY (LAN8720 or TLK110)#define ETH_TYPE        ETH_PHY_LAN8720// IC-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110)#define ETH_ADDR        0// Pin# of the IC clock signal for the Ethernet PHY#define ETH_MDC_PIN     23// Pin# of the IC IO signal for the Ethernet PHY#define ETH_MDIO_PIN    18#define NRST            5static bool eth_connected = false;void WiFiEvent(WiFiEvent_t event){    switch (event) {    case SYSTEM_EVENT_ETH_START:        Serial.println("ETH Started");        //set eth hostname here        ETH.setHostname("esp32-ethernet");        break;    case SYSTEM_EVENT_ETH_CONNECTED:        Serial.println("ETH Connected");        break;    case SYSTEM_EVENT_ETH_GOT_IP:        Serial.print("ETH MAC: ");        Serial.print(ETH.macAddress());        Serial.print(", IPv4: ");        Serial.print(ETH.localIP());        if (ETH.fullDuplex()) {            Serial.print(", FULL_DUPLEX");        }        Serial.print(", ");        Serial.print(ETH.linkSpeed());        Serial.println("Mbps");        eth_connected = true;        break;    case SYSTEM_EVENT_ETH_DISCONNECTED:        Serial.println("ETH Disconnected");        eth_connected = false;        break;    case SYSTEM_EVENT_ETH_STOP:        Serial.println("ETH Stopped");        eth_connected = false;        break;    default:        break;    }}void testClient(const char *host, uint16_t port){    Serial.print("\nconnecting to ");    Serial.println(host);    WiFiClient client;    if (!client.connect(host, port)) {        Serial.println("connection failed");        return;    }    client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);    while (client.connected() && !client.available());    while (client.available()) {        Serial.write(client.read());    }    Serial.println("closing connection\n");    client.stop();}void setup(){    Serial.begin(115200);    WiFi.onEvent(WiFiEvent);    SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);    if (!SD.begin(SD_CS)) {        Serial.println("SDCard MOUNT FAIL");    } else {        uint32_t cardSize = SD.cardSize() / (1024 * 1024);        String str = "SDCard Size: " + String(cardSize) + "MB";        Serial.println(str);    }    pinMode(NRST, OUTPUT);    digitalWrite(NRST, 0);    delay(200);    digitalWrite(NRST, 1);    delay(200);    digitalWrite(NRST, 0);    delay(200);    digitalWrite(NRST, 1);    ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);}void loop(){    if (eth_connected) {        testClient("baidu.com", 80);    }    delay(10000);}


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

Походу получается, что ответ от LILYGO изучать программирование и создавать ПО самостоятельно (или искать готовые прошивки, хотя это и не спортивно).

Интерфейсы и пинг


Для сетевых профессионалов (и примкнувших к ним) скажу пару слов о скорости работы по интерфейсам Wi-Fi и Ethernet и их отзывчивости. Тестирование проводилось в ненагруженной гигабитной сети, зашумлённость Wi-Fi диапазона специально не контролировалась.

Первый скриншот это пинг контроллера по Wi-Fi интерфейсу. Минимум 24 мс, максимум 105 мс, среднее 67 мс.

image

Второй пинг контроллера по Ethernet интерфейсу. Минимум 0 мс, максимум 9 мс, среднее 2 мс.

image

Как вы видите, пинг по проводному Ethernet кардинально меньше, чем по Wi-Fi (что ожидаемо). Насколько хороши или плохи эти цифры предоставляю судить читателям самостоятельно, меня они вполне устраивают для моих целей.

Тестирование


Тестировать такую систему, как T-Internet-POE на скетчах, подобных предложенному производителем это несерьёзно, поэтому для тестирования контроллера применялась специализированная версия AMS, адаптированная специально для этой платы. Учитывая, что это сервер, который использует полноценные HTML, CSS, Javascript, Ajax, графические файлы и библиотеки, то успешная работа такого сервера на T-Internet-POE будет свидетельствовать о правильно спроектированном железе и возможности его использования в реальных проектах.

Примечание: тестирование производилось на внутренней, не публичной версии AMS для T-Internet-POE. Публикация и распространение этой версии не планируется, возможно это будет сделано позже, после соответствующих доработок.

Тест 1. Запускаем AMS сервер на T-Internet-POE


Запустить AMS на новом контроллере с новым чипом и сетевым интерфейсом это весьма нетривиальная задача, но тем не менее, при правильном подходе и понимании того, что ты делаешь, всё становится возможным.

Косяк номер 1


В процессе этой работы стали вылезать косяки самого контроллера T-Internet-POE и первое, что было выявлено это то, что контроллер отказывается прошиваться при вставленной microSD карте памяти. Не помогает ничего ни замена USB порта, ни питание от отдельного блока, ни нажимание кнопок, ни замена карты контроллер упорно не желает прошиваться при вставленной карте памяти.

Глюк это конкретного экземпляра или родовой дефект всех контроллеров T-Internet-POE сказать трудно (имея в своём распоряжении один экземпляр), можно только констатировать 100-процентную повторяемость и воспроизводимость проблемы.

Что это значит для нас? В практическом плане это значит, что на контроллере T-Internet-POE фактически нет картридера картридер, который блокирует прошивку контроллера это не картридер, а баг.

Что же делать? Остаётся только использовать 1,5 МБ SPIFFS, имеющийся на модуле ESP32. Да, это не очень много, но в принципе 1,5 МБ памяти для IoT устройства это более-менее приемлемо в большинстве случаев.

Косяк номер 2


Ок, от картридера мы отказались, теперь нам нужно подружиться с SPIFFS. Вроде бы задача несложная и даже привычная, но и тут нас ждёт засада: по какой-то причине утилита ESP32FS отказывается нормально работать на этом контроллере (в этой конфигурации). Перенос файлов в память модуля ESP32 приводит к последующей ошибке монтирования SPIFFS диска.

М-да В случае невозможности нормально перенести файлы (сервера) на SPIFFS диск, остаётся только один способ инициализация интерфейса через Serial соединение, и последующий перенос файлов на SPIFFS диск через веб-интерфейс. Способ конечно не очень удобный, но никак не влияющий на конечный результат файлы сервера были успешно перенесены на SPIFFS диск.

Описание самого процесса адаптации кода под новый контроллер я опускаю, поскольку это потребовало бы составления антологии наподобие полного собрания сочинений В. И. Ленина и сразу перехожу к демонстрации факта успешной работы AMS сервера на T-Internet-POE (а значит и работоспособности самой платы T-Internet-POE).

Загрузка страницы по Wi-Fi интерфейсу.

image

Загрузка страницы по Ethernet интерфейсу.

image

Выигрыш по скорости примерно в 4 раза, естественно, в пользу Ethernet. Здесь нужно ещё иметь в виду, что речь идёт о неоптимизированном коде и после проведения соответствующих работ результаты должны значительно улучшиться.

image

Работа сервера по Ethernet интерфейсу на LILYGO TTGO T-Internet-POE ESP32 LAN8270A.

Тест 2. Работа на двух интерфейсах


Тут мне придётся немного поработать разрушителем легенд. В интернете ходят упорные слухи, что одновременная работа Wi-Fi и Ethernet на связке ESP32 и LAN8270A невозможна. Это не так AMS сервер прекрасно работает на двух интерфейсах одновременно и отлично обслуживает запросы по Wi-Fi и Ethernet. Никаких проблем с зависаниями или перезагрузками ESP32 нет.

image

Вот это уже интересный результат, который открывает заманчивые перспективы: поскольку мы имеем собственный сервер, то можем как угодно управлять обслуживанием интерфейсов, например, по Wi-Fi отдавать одни сайты с одним контентом, а по Ethernet другие сайты с другим контентом. Образно говоря, бабушке по Ethernet отдавать сайт с кулинарными рецептами, а внуку по Wi-Fi сайт с избранными статьями из БСЭ.

Тест 3. Бан по одному из интерфейсов


Теперь давайте попробуем на практике реализовать идею с различным обслуживанием интерфейсов веб-сервером. В качестве примера попробуем реализовать отказ в обслуживании для подключений по одному из интерфейсов (Ethernet).

image

Клиент, подключённый к нашему контроллеру по Ethernet интерфейсу получил отказ в обслуживании.

Резервирование интерфейсов


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

Сетевой роутинг


Имея в своём распоряжении два рабочих сетевых интерфейса можно как угодно маршрутизировать пакеты в сети. Никто также не мешает в схему маршрутизации по Wi-Fi и Ethernet добавить маршрутизацию данных по nRF24 или LoRa или по любой другой беспроводной сети. Таким образом можно сделать любой роутер для вашей IoT системы.

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

Итоги


Теперь давайте подведём итоги этого небольшого исследования: в общем, несмотря на некоторые косяки и детские болезни, контроллер LILYGO TTGO T-Internet-POE ESP32 LAN8270A мне понравился это отличный инструмент для построения IoT систем, особенно если вы обладаете соответствующей квалификацией и не лишены фантазии и креативного подхода к своему творчеству.

Плюсы и минусы LILYGO TTGO T-Internet-POE ESP32 LAN8270A.

Плюсы:
  • Это работает!
  • Законченное интегрированное решение Wi-Fi + Ethernet + POE + GPIO
  • Хорошая работа без зависаний и перезагрузок (проблем при тестировании выявлено не было)
  • Возможность одновременной работы по двум интерфейсам

Минусы:
  • Тотальное отсутствие документации, примеров и пояснений
  • Относительно высокий порог входа
  • Детские болезни и мелкие косяки в реализации
Подробнее..

Маяк, ночник и конструктор для вашего ребенка (50 деталей, 3D печать)

16.03.2021 02:15:34 | Автор: admin
image

Добрый день, читатели.

Сегодня я хочу поделиться с вами своей разработкой, точнее не только своей, а сделанной совместно с моей 7-ми летней дочерью.

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

На что дочь ответила Я хочу ночник в виде маяка, и он должен проецировать звезды на потолок.

Для меня это было неожиданно, носказано сделанои на наш взгляд получилосьвполне достойно! :) Теперь мы хотим поделиться с вами всем этим. Задальнейшей историей прошу в статью

Сразу забегу вперед и скажу, что маяк проектировался по принципу конструкторов из 3 мм фанеры, поэтому обладает свойственными им нюансами, но зато его также легко и интересно собирать.

Цель ясна и надо приступать к реализации


Задача 1 выбрать образец
Перед каникулами, по вечерам, мы начали готовиться к предстоящей работе. Несколько вечеров просидели в google в поисках того единственного маяка, который мил сердцу и который хотелось бы взять за основу.
Среди огромного разнообразия Юле очень понравился этот маяк (ссылка на исходный сайт увы утеряна):

image

Задача 2 тест
Теперь перед нами встал вопрос хватит ли мощности у небольшого светодиода, для создания тени на потолке, с расстояния 2 метра? Для дочери это было самое увлекательное, одно только предложение поставить эксперимент её так вдохновило, что даже когда мы уже все узнали, она просила еще что-то проверить :)
Собственно с этим как раз и возникли нюансы. Классические светодиоды, коих огромное количество в любых магазинах и у меня в закромах, имеют направленный луч в 30 и чтобы тень создавалась, нужно опустить светодиод практически к основанию маяка. Но ведь у маяка источник света вверху! Благо у меня нашлась еще одна куча 3 миллиметровых светодиодов с углом 120 и теплым белым свечением это оказался самый подходящий светодиод.

Далее была поездка в Кронштадт, ведь нельзя проникнуться идеей создания маяка, если ты не увидел и не прочувствовал его. А в Кронштадте их аж 17! Поездка была отличная, мы погуляли по дамбе, но в самом городе замерзли, с трудом нашли место где купить чего-то теплого и на обратной дороге на КАД пробили колесо. Зато все точно запомнилось!

image

Задача 3 проектирование
Ну вот пришли каникулы и мы начали разработку. Я сидел в Solidworks и создавал детали, Юля сидела рядом и консультировала :) Выбирали оптимальную высоту, ширину основания и прочее. Процесс был очень увлекательный. Итого вышло 50 деталей.

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

Процесс сборки первых деталей
image
image
image
image


Задача 4 электронная начинка
Схему было решено сделать самой простой без транзисторов и всяких там переключателей. 2 готовых модуля модуль заряда литиевых аккумуляторов и сенсорная кнопка, которую мы решили спрятать под крышей входа.

Схема проще не бывает
image

Всё это, за исключением пайки, ребенок может собрать сам. Что касается электронной части, то я решил припаять только огрызки, а дальше дочь сама соединила элементы между собой на скрутку и маяк ожил на её глазах! Все модули размещаются в тамбуре модуль заряда приклеен на двухсторонний скотч на полу (есть отверстие для разъема micro-usb в задней стенке), а переключатель к крыше.


Макеты STL на thingiverse.com

Собственно мы и подошли к концу рассказа. Будем рады, если вы захотите повторить наш проект, а может даже раскрасите или сделаете экстерьер и выложите фотографии в комментариях.

Весь материал доступен для повторения и использования в личных, не коммерческих целях
Подробнее..

Перевод Делаем аппаратную кнопку выключения звука в Zoom

16.03.2021 10:10:28 | Автор: admin
Недавно Instagram показал мне рекламу специальной кнопки для выключения звука в Zoom, которая оказалась для меня уж очень актуальной.



Да, я каждый день на созвонах в Zoom. Да, у меня есть ребёнок, который часто вмешивается в эти звонки. Алгоритм выдачи рекламы Instagram, ты победил, мне нужна эта кнопка.

Но у меня есть предубеждения. В Instagram рекламируется проект с Kickstarter. К тому же, я не хочу делать свой вклад в доходы от рекламы Facebook, даже нажимая на этот ролик. Выражение Дженни Оделл Бесплатных часов не бывает полностью описывает мою точку зрения на качество продуктов в рекламе Instagram. Кроме того, мой лимит на финансирование проектов с Kickstarter практически исчерпался.

Я поддерживал множество проектов на Kickstarter, и иногда результат этих проектов напоминал мне гамбургер, который Майкл Дуглас получил в фильме С меня хватит!.


Так что давайте соберём такую кнопку сами.

Первое, о чём стоит задуматься: какую кнопку мне будет приятно нажимать?

Я люблю клавиатуры с переключателями Cherry MX. Существует три типа механических переключателей: линейные, тактильные и кликающие. Линейный простейший тип переключателя, перемещающийся вверх-вниз почти без обратной связи. У тактильных переключателей в середине хода есть выступ, позволяющий почувствовать, когда произошло нажатие клавиши. А кликающие переключатели имеют более сильную тактильную обратную связь И производят слышимый клик при нажатии.

В обычной ситуации мы бы купили тестер переключателей, чтобы разобраться, какой тип нам отзывается, а ещё опросили бы своих коллег, какой звук должна издавать клавиатура, чтобы они нас не убили. Но мы посередине пандемии COVID, поэтому коллег рядом нет! Выберем переключатель Cherry MX Blue с удобной тактильной обратной связью, который при этом чрезвычайно громкий. На сайте Cherry MX этот переключатель называют кликающим и заметным, но это ещё очень слабо сказано.


Выглядит красиво, но можно придумать и кое-что получше. Если мне приятно нажимать переключатель Cherry MX Blue, то не будет ли ещё приятнее нажимать комически большой Cherry MX Blue?

И это Novelkeys Big Switch.


Он в 4 раза больше по каждой из размерностей и в 64 раза больше по объёму, чем обычный переключатель. У него даже есть огромный колпачок!


К сожалению Большой Переключатель не продаётся в корпусе, поэтому мне пришлось воспользоваться 3D-печатью. Красивый корпус нашёлся на Thingiverse: NovelKeys Big Switch Case. Всегда стоит поискать ремиксы на случай, если кто-нибудь решил усовершенствовать исходный дизайн. В данном случае нашёлся ремикс, в который добавлен отсек для Pro Micro, а переключатель устанавливается более плотно, поэтому я напечатал его.


Теперь, когда у нас есть корпус, нужна плата, которую мы вставим в него и прикрепим к переключателю.

У Pro Micro есть чип ATmega32U4, позволяющий эмулировать устройство USB HID, например, USB-клавиатуру. К тому же, эта плата имеет маленький размер.


В нижней части Большого Переключателя есть два металлических контакта.


При нажатии клавиши внутри переключателя происходит замыкание цепи между этими двумя контактами.


Взглянем на расположение контактов Pro Micro:


Можно подключить GND к одному металлическому контакту, а Pin 2 ко второму. Pin 2 это контакт цифрового ввода-вывода, который считывает HIGH, когда клавиша нажата, и LOW, когда нет.

Было бы ещё здорово иметь какой-нибудь наглядный индикатор состояния Mute, поэтому можно добавить светодиод.

Я заказал светодиод размером 10 мм:


И резистор на 220 ом:


Длинная нога светодиодов подключается к PWR, а короткая к GND. Мы вставим резистор между длинной ногой и другим контактом, чтобы снизить величину тока. Я выбрал Pin 9 в нижней части платы. Короткую ногу я соединил с GND. Мне показалась полезной эта страница о светодиодах и резисторах.

Между платой и переключателем я припаял такой провод 20 AWG:


В результате получилась вот такая конструкция:


Просто запихнём всё это в наш напечатанный корпус:


Теперь нужно написать код.

Я начал с кода, который Sparkfun написала для создания огромной Кнопки Сохранения, и немного его изменил.

Принцип заключается в следующем: при нажатии клавиши она посылает сочетание горячих клавиш Zoom включения и отключения звука (на Mac это Cmd-Shift-A). Нужно будет изменить настройки Zoom, чтобы это сочетание клавиш распознавалось, даже когда Zoom находится не в фокусе. Поставим флажок Enable Global Shortcut:


Также мы хотим включать или выключать светодиод после каждого нажатия на клавишу. Я решил, что светодиод будет аналогом лампочки В эфире когда синий светодиод горит, звук у меня включен и люди слышат, что я говорю.

Но если просто включать-выключать светодиод при каждом нажатии на клавишу, то как сохранять синхронизацию с состоянием Mute в самом Zoom?

Удобство Pro Micro заключается в том, что она имеет и последовательное подключение. Обычно оно используется для печати отладочной информации в Arduino IDE, но мы можем использовать его для обеспечения синхронизации с состоянием включения звука в Zoom.

Вот код, который мы загружаем в саму Pro Micro:

#include "Keyboard.h"// OS parameterstypedef enum {  LINUX,  WINDOWS,  MAC} os_types;// Change this to your operating systemconst os_types OS = MAC;// Pinsconst int btn_pin = 2;const int led_pin = 9;// Constantsconst int debounce_delay = 50;              // ms// Globalsint btn_state = HIGH;int btn_prev = HIGH;unsigned long last_debounce_time = 0;int os_ctrl;int led_state = LOW;void setup() {  Serial.begin(57600); // opens serial port, sets data rate to 57600 bps    // Set up LED and button pins  pinMode(btn_pin, INPUT_PULLUP);  // Set the button as an input  pinMode(led_pin, OUTPUT);  digitalWrite(led_pin, led_state);  // Begin keyboard  Keyboard.begin();  // Switch to correct control/command key  switch(OS){    case LINUX:    case WINDOWS:      os_ctrl = KEY_LEFT_CTRL;      break;    case MAC:      os_ctrl = KEY_LEFT_GUI;      break;    default:      os_ctrl = KEY_LEFT_CTRL;      break;  }  // Get initial timestamp  Serial.println("started");  }void loop() {  // Read current state of the button  int btn_read = digitalRead(btn_pin);  // Remember when the button changed states  if ( btn_read != btn_prev ) {    last_debounce_time = millis();  }  // Wait before checking the state of the button again  if ( millis() > (last_debounce_time + debounce_delay) ) {    if ( btn_read != btn_state ) {      btn_state = btn_read;      if ( btn_state == LOW ) {        // Send cmd+shift+a        Keyboard.press(KEY_LEFT_SHIFT);        Keyboard.press(os_ctrl);        Keyboard.press('a');        delay(100);        Keyboard.releaseAll();        Serial.println("pressed");        if (led_state == LOW) {          led_state = HIGH;        } else {          led_state = LOW;        }        digitalWrite(led_pin, led_state);      }    }  }  // Remember the previous button position for next loop()  btn_prev = btn_read;  if (Serial.available() > 0) {    String incomingString = Serial.readStringUntil('\n');    if (incomingString == "muted") {      led_state = LOW;    } else if (incomingString == "unmuted") {      led_state = HIGH;          }    digitalWrite(led_pin, led_state);      }  }

Дальше мы можем добавить Applescript, сообщающий о текущем состоянии Zoom. Я нашёл Zoom-плагин для устройства Streamdeck, содержавший исходный Applescript, и изменил его так, чтобы он сообщал о том, открыт ли Zoom, и каково состояние его звука. Также я модифицировал скрипт, чтобы он выводил JSON.

set zoomStatus to "closed"set muteStatus to "disabled"tell application "System Events"if exists (window 1 of process "zoom.us") thenset zoomStatus to "open"tell application process "zoom.us"if exists (menu bar item "Meeting" of menu bar 1) thenset zoomStatus to "call"if exists (menu item "Mute audio" of menu 1 of menu bar item "Meeting" of menu bar 1) thenset muteStatus to "unmuted"elseset muteStatus to "muted"end ifend ifend tellend ifend tellcopy "{\"mute\":\"" & (muteStatus as text) & "\",\"status\":\"" & (zoomStatus as text) & "\"}" to stdout

Если теперь мы запустим его во время звонка в Zoom, то он будет выводить примерно такое:

$ osascript get-zoom-status.scpt{"mute":"muted","status":"call"}

Затем я написал небольшое приложение на Node, используемое в качестве посредника между Pro Micro и этим скриптом:

const { exec } = require('child_process');const SerialPort = require('serialport');const Readline = require('@serialport/parser-readline');const port = new SerialPort('/dev/tty.usbmodemHIDPC1', {    baudRate: 57600});var checkStatus = function() {    console.log('Checking status...');    exec('osascript get-zoom-status.scpt', (error, stdout, stderr) => {        if (error) {            console.error(`exec error: ${error}`);            return;        }        var status = JSON.parse(stdout);        if (status.mute == 'unmuted') {            port.write('unmuted');        } else {            port.write('muted');        }    });}const parser = port.pipe(new Readline({ delimiter: '\r\n' }))parser.on('data', function (data) {    if (data == "pressed") {        console.log('Button pressed.');        checkStatus();    }})checkStatus();setInterval(checkStatus, 30000);

Этот скрипт выполняет две задачи. При нажатии кнопки он отправляет плате Pro Micro через последовательный порт команду нажато, при этом запускается Applescript для определения текущего состояния звука в Zoom. Затем он отправляет плате Pro Micro команду звук выключен или звук включен, благодаря чему светодиод переключается в соответствующее состояние. Также я создал таймер, запускающий скрипт через каждые 30 секунд на случай, если я случайно отключу или включу звук через интерфейс Zoom, а не через кнопку, в противном случае состояние будет обновляться только при нажатии кнопки.

Вот как выглядит кнопка при использовании в звонке через Zoom:


Пожалуйста, поддержите мой Kickstarter шучу, у меня нет никакого Kickstarter, но, надеюсь, теперь вы сможете создать такую кнопку сами.



На правах рекламы


Закажите сервер и сразу начинайте работать! Создание VDS любой конфигурации в течение минуты. Эпичненько :)

Подробнее..

Моя первая Ардуинка переключатель USB

04.04.2021 20:17:04 | Автор: admin

Пару лет назад я обзавёлся топовым смартфоном одной южнокорейской компании. Среди его особенностей оказалась поддержка DeX - способа запуска на большом экране, подключаемом к док-станции через HDMI, отдельных приложений и даже целого Linux в контейнере (к сожалению, последнее ушло со свежей версией Android). Кроме того, порадовала поддержка переферийных устройств - так, внешняя звуковая карта Asus Xonar U7, с которой у меня пущен сигнал на ресивер с большими колонками, завелась без проблем. Отсюда возникло желание превратить телефон в мини-рабочее место, научив делить переферию с системником - напирмер, чтобы вой кулеров не мешал слушать музыку или смотреть видео. По сути, требовалось KVM-решение, удовлетворяющее ряду хотелок. Так я познакомился с Arduino.


Требования

До этого у меня на столе "жил" простой четырёхпортовый USB-хаб с клавишей отключения. К нему были подключены проводные клавиатура и мышь, а также Web-камера. Камеру я обычно физически отключал от хаба вне времени использования (паранойя), а клавиша отключения на хабе оказалась удобна тем, что позволяла с комфортом чистить клавиатуру и мышь, не выдёргивая разъёмы и не выключая компьютер. Кроме того, в хаб периодически включался аппаратный менеджер паролей. Звуковая карта и принтер были подключены напрямую к разъёмам на системном блоке, и этим набор USB-переферии ограничивается. Все перечисленные устройства работают по стандарту USB 2.0. На док-станции присутствуют два порта USB той же версии.

Заводить отдельную клавиатуру для телефона, конечно же, не хотелось. Кроме того, я очень привык к удобной мыши Logitech G600 с двенадцатью хорошо прощупываемыми дополнительными кнопками под большим пальцем, обладающими тем преимуществом, что назначенные на них комбинации работают под любой операционной системой и даже в BIOS без установки дополнительного ПО. Поэтому я решил использовать существующие клавиатуру и мышь, но делить их между устройствами. Кроме того, должен существовать способ отключить их совсем. Звуковая карта тоже должна переключаться между хостами и отключаться (чтоб не жрала энергию в отсутствие питания от сети). Отключение камеры решено было внести в ту же систему. Принтер остался в стороне, поскольку смартфон не захотел с ним работать.

Таким образом был сформирован следующий список требований к "умному" USB-переключателю:

  1. Клавиатура и мышь должны совместно переключаться между телефоном и системным блоком, а также отключаться.

  2. Звуковая карта должна переключаться между устройствами и отключаться независимо от клавиатуры и мыши.

  3. Камера должна подключаться к системному блоку и отключаться независимо от других устройств. Факт того, что камера сейчас подключена (даже если на ней самой не горит лампочка), должен привлекать к себе внимание (например, миганием светодиода).

  4. Переключения могут производиться вручную (кнопками) или автоматически (логикой хаба, например, при отключении или подключении устройств).

  5. Монитор переключается независимо от остальных устройств. Поскольку видеокарта и док-станция включены на разные его входы, это делается кнопкой на самом мониторе.

  6. Под рукой должен быть хаб или USB-разъём на гибком проводе для подключения менеджера паролей к системному блоку. Это может быть простой удлиннитель, уходящий под стол.

  7. Телефон может быть подключен к переключателю как через док-станцию с внешним питанием, так и напрямую (например, чтобы включать музыку во время мытья пола, когда на сетевом фильтре под столом и, соответственнно, на док-станции нет питания). Желательно иметь для подключения через док-станцию и напрямую разные интерфейсы, чтобы не выдёргивать каждый раз разъём из док-станции. Вместо телефона может также быть подключен ноутбук (если HDMI-кабель с док-станции вручную переключить на него же, получится полноценное рабочее место, пока стационарный компьютер на обслуживании).

  8. Питание на переключателе и на подключенных к нему подчинённых устройствах должно присутствовать, если включено хоть одно хост-устройство (системный блок, док-станция или телефон).

  9. Должна присутствовать индикация, показывающая текущее состояние коммутации.

  10. Вся конструкция должна занимать не слишком много места на столе.

Из имеющихся на рынке решений мне на глаза попались KVM-переключатели, а также специализированные переключатели USB вроде этого. Все встреченные мной модели работали по принципу "всё или ничего", коммутируя все подключенные к ним устройства совместно. Мне же хотелось иметь возможность, например, слушать музыку с телефона во время создания образа системного диска с использованием клавиатуры и мыши, а также отключать камеру независимо от остальных устройств. Кроме того, было желание поковыряться и попробовать собрать что-то самостоятельно. Друг посоветовал посмотреть в сторону Arduino, и я начал изучение.

Элементная база

Моё первое представление, составленное со слов друга, сводилось к тому, что для решения моей задачи достаточно будет подключить к контроллеру один или несколько шилдов с достаточным количеством USB-разъёмов, кнопок и индикаторов, а потом запрограммировать контроллер так, чтобы обеспечить коммутацию пакетов USB. Это оказалось неверным по нескольким причинам.

  1. Шилды с мастер-разъёмами USB предназначены для того, чтобы контроллер мог сам опрашивать подключенную к ним переферию, выступая ведущим устройством на шине. При этом непосредственно в формировании и разборе пакетов Arduino не участвует - это делает сторонняя микросхема.

  2. Слэйв-разъёмы предназначены почти исключительно для прошивки и отдалки контроллера, а за коммуникацию по ним отвечает не сам контроллер, а отдельная микросхема, обеспечивающая конвертацию серийных протоколов и определяющаяся как COM-порт. Заставить её вместо этого представиться USB-хабом и начать пропускать пакеты от других устройств невозможно.

  3. Сами контроллеры не применяются для коммутации пакетов, и я не уверен, что мне с моим нулевым опытом на этой платформе удалось бы решить эту задачу, равно как и что она вообще имеет решение.

В этот момент я понял, что придётся паять. Опыта самоделок такого уровня у меня не было - тем выше был соблазн попробовать.

Идея состояла в том, чтобы взять два обычных хаба USB 2.0 (в сборе либо в виде микросхем) и под управлением Arduino коммутировать связи между ними и внешними устройствами, добиваясь того же эффекта, как если бы я вручную перетыкал разъёмы. Прежде всего это касается пары сигнальных проводов, поскольку подачу питания можно организовать отдельно. Вооружившись каталогом одного из магазинов радиодеталей, я приступил к поискам подходящей элементной базы.

Найти контроллеры хабов USB в таком виде, чтобы их можно было распаять на плате, мне не удалось - возможно, потому, что я неправильно искал. Поэтому я просто зашёл в компьютерный магазин рядом с домом и купил два самых простых и дешёвых хаба. Дома я вскрыл корпуса, извлёк из них платы и удалил с них разъёмы. Остались небольшие (примерно 2 на 8 сантиметров) панели, которые можно спрятать в корпус устройства, соединив с остальными компонентами монтажным проводом.

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

FST3125FST3125

Подключив через него мышь, я с удовольствием обнаружил, что всё работает.

Несложный подсчёт показывает, что одной такой микросхемы достаточно для переключения пары выводов D+ и D- одного устройства USB между двумя источниками. Стало быть, для управления одним каналом коммутации требуется два бита (или два вывода ардуинки):

Прямое управление ключамиПрямое управление ключами

Тем не менее, напрямую подавать управляющий сигнал от контроллера к коммутатору мне не хотелось. Дело в том, что, помимо трёх нужных мне состояний ("отключено", "подключено к первому источнику", "подключено ко второму источнику"), такая схема подключения даёт возможность открыть все ключи одновременно (например, из-за ошибки в программе или во время загрузки, когда значения выходных сигналов ещё не выставлены), что приведёт к соединению шин данных сразу трёх устройств, два из которых являются ведущими. Чтобы избежать такого сценария, я вставил между ардуинкой и коммутатором аппаратную логику, исключающую возможность одновременного открытия всех ключей:

Подключение FST3125, исключающее одновременное открытие всех ключейПодключение FST3125, исключающее одновременное открытие всех ключей

Инвертор перед нижним элементом "или" позволяет сигналу "SIDE" выбирать группу ключей, которая будет открыта. В то же время, высокий сигнал на входе "ON" отключает все ключи сразу.

В качестве контроллера я взял Arduino Nano. Питание на него я подал через пин +5V, а вообще подачу питания организовал через пятивольтовые механические реле V23079A1001B301 (почему не через полупроводники - расскажу ниже). Светодиоды взял первые попавшиеся - убедившись, что через 220-омные резисторы ток и яркость получаются адекватными. Управление яркостью светодиодов взяли на себя встроенные ШИМы контроллера.

Поскольку ножек у Ардуинки не хватало, управление светодиодами (а также некоторой другой логикой на плате, см. ниже) я организовал через микросхемы серии AC32 (на макетке пробовал сначала DIP-исполнение, а потом перешёл на SOIC). Кроме того, в нескольких местах используются инверторы - модели LS04.

Дизайн

Теперь нужно было определиться с тем, как мой умный хаб должен выглядеть и управляться. Я начал с дизайна хаба, лежавшего у меня на столе, и мысленно дополнил его недостающими элементами. Этот процесс показан на рисунке ниже.

Готовый USB-хаб (слева) и проект "умного" хаба (справа)Готовый USB-хаб (слева) и проект "умного" хаба (справа)

Работать такое устройство должно было следующим образом. Пять разъёмов USB-A, расположенных столбиком, по проекту были объединены в четыре группы и управлялись четырьмя кнопками (на рисунке - справа). Первая группа (два разъёма) предназначалась для клавиатуры и мыши, вторая (один разъём) - для звуковой карты, третья (один разъём) - для камеры, четвёртая (один разъём) была оставлена про запас.

Под крышкой находились те самые два хаба, подключенные к ведущим устройствам через три разъёма USB-B, расположенные в верхнем торце устройства. Правый разъём предназначен для подключения к компьютеру и всегда связан с "правым" хабом. К левому и среднему разъёмам подключались телефон и док-станция: когда телефон подключен, "левым" хабом владел он, в противном случае хаб доставался док-станции. Верхний ряд светодиодов отображал состояние "сторон"-хабов: зелёный - подключено к постоянному устройству, оранжевый - подключено к портативному устройству (телефону), красный - отключено.

Светодиоды с правой и левой стороны от каждого разъёма показывали, к какой стороне он сейчас подключен (а также к какой стороне он подключится при изменении внешних условий, например, возвращении питания на данную сторону). Первые две группы устройств (клавиатуру, мышь и звуковую карту) можно было подключать к любой из сторон и отключать. Камеру - подключать только к правой стороне или отключать. Последний разъём подключался к порту, оставшемуся свободным на левом хабе, и тоже мог отключаться.

Этот проект был затем пересмотрен по нескольким параметрам.

  1. Я решил, что все группы должны вести себя полностью одинаково - меньше будет путаницы. Это подразумевало, что камера сможет, как и прочие каналы, подключаться к каждой из сторон, а пятый разъём исчезнет.

  2. Иллюминация было урезана - остались по два светодиода на группу, загорающиеся при подключении её к правой и левой стороне, соответственно. Цвета этих диодов хватает, чтобы отслеживать также статус сторон.

  3. Поскольку вся схема с ардуинкой, реле, коммутаторами и деталями обвязки значительно превосходила по размерам старый хаб, я решил спрятать её под стол, оставив наверху лишь маленький пульт с кнопками и светодиодами.

  4. Я добавил два "аварийных" светодиода, тлеющих и иногда ярко вспыхивающих красным светом: первый напоминает, что камера в данный момент подключена, второй указывает, что звуковой карте может не хватать питания (об этом - ниже). Эти светодиоды органично вписались в соответствующие кнопки.

Фотографию пульта в работе, а также его относительного размера к основной плате я привожу ниже.

Пульт управления крупным планом и вместе с печатной платой в процессе распайки деталейПульт управления крупным планом и вместе с печатной платой в процессе распайки деталей

Кнопки работают наиболее очевидным способом: одиночные нажатия последовательно переключают соответствующий канал между состояниями "подключен к компьютеру", "подключен к телефону", "отключен". Длинные или множественные нажатия не используются.

Светодиоды расположены над каждой кнопкой попарно и отображают состояние данного канала. Левый светодиод горит, когда канал подключен к системному блоку, правый - когда он подключен к телефону. Зелёный сигнал означает, что устройство, к которому выполнено подключение, активно, красный - что напряжения на этом направлении нет.

Макетирование

Проект пережил две макетки, в сумме прожившие у меня на столе более полугода. Их фотографии я прикрепляю ниже.

Первая макетка - питание через диодыПервая макетка - питание через диодыВторая макетка - добавились реле и дополнительные светодиоды в левом верхнем углуВторая макетка - добавились реле и дополнительные светодиоды в левом верхнем углу

Первый вопрос касался схемы подключения коммутирующих микросхем. Я использовал описанную выше аппаратную защиту от одновременного открытия ключей, причём клавиатура и мышь управлялись одной парой сигналов. Кроме того, я использовал эту же схему для переключения "левого" хаба между телефоном и док-станцией - правда, не по сигналу контроллера, а по наличию напряжения на разъёме подключения телефона.

Далее, нужно было выбрать схему подключения светодиодов. Поскольку 6 двуцветных светодиодов и 2 одноцветных - это 14 каналов, нечего было и думать подключить их напрямую к ардуинке - ног не хватило бы. Кроме того, мне хотелось поиграться с ШИМами, снизив яркость индикаторов каналов в простое, но зажигая их ярко при нажатии на любую кнопку. "Аварийные" светодиоды я решил заставить мигать - за 4.5 секундами тления должна была следовать яркая вспышка длительностью в полсекунды.

Arduino Nano предоставляет всего шесть ШИМов. Я распределил их следующим образом:

  • Управление яркостью красной компоненты "левых" светодиодов;

  • Управление яркостью зелёной компоненты "левых" светодиодов;

  • Управление яркостью красной компоненты "правых" светодиодов;

  • Управление яркостью зелёной компоненты "правых" светодиодов;

  • Управление светодиодом "камера включена";

  • Управление светодиодом "звуковой карте не хватает питания".

Таким образом, "аварийные" светодиоды подключены напрямую к контроллеру, а остальные - к выходам элементов "или", смешивающих сигнал яркости с сигналом подключения канала к соответствующей стороне.

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

Первая проблема была тривиальной и сводилась к нехватке питания. Как показал эксперимент, просто взять и подключить все четыре устройства к одному хабу нельзя: клавиатура и мышь в сумме потребляют до 300 мА, камера - до 440, звуковая карта - до 540, и это не учитываея питания самой схемы. (Напоминаю, что я решил ограничиться стандартом USB 2.0 с 500 мА на порт, пусть даже материнские платы обычно и разрешают чуть более высокое энергопотребление.) В итоге я решил подключить компьютер через два кабеля вместо одного, предоставив звуковой карте как самому прожорливому потребителю отдельную шину питания - это показалось проще, чем поднимать версию USB. Если же компьютер не выдаёт напряжения на USB-разъёмы, то питание предоставляется оставшимся хостом (телефоном или док-станцией): совместное использование всех устройств в такой конфигурации невозможно, но и юзкейза для подключения всей переферии при обесточенном компьютере я не придумал. Соответственно, "аварийный" светодиод звуковой карты должен мигать, если при питании не от компьютера включены она и что-то ещё.

Кстати, это освободило один интерфейс USB A на хабе, подключенном к компьютеру. Я использовал его для подключения генератора паролей.

Вторая проблема тоже была связана с питанием. "Плюс" с трёх различных источников я изначально планировал свести через диоды с общим катодом, но испытания на макетке показали, что те диоды, которые попались мне под руку, под максимальной нагрузкой давали просадку напряжения почти на целый вольт, что я счёл неприемлимым (стандарт USB допускает минимум в 4.75В). Вместо диодов я организовал подачу питания через механические реле - 30 мА "лишнего" тока на источник выглядели разумной платой за гарантированно равные потенциалы, хотя предполагаю, что опытные радиолюбители нашли бы решение получше.

Переход на реле, впрочем, вызвал другую, неожиданную проблему. Поскольку логика работы контроллера (как минимум, по части управления светодиодами) зависит от того, на какие из разъёмов типа B подано напряжение, эта информация должна быть каким-то образом подана на него. Не мудрствуя лукаво, я завёл эти напряжения на аналоговые входы ардуинки, подтянув к нулю через резисторы номиналом 33k. Это нормально работало с диодами, однако реле добавили задержку, равную времени срабатывания механики, между появлением напряжения на аналоговом входе и на пине +5V. В итоге контроллер получал питание от аналогового пина и зависал на старте. Для исправления ситуации оказалось достаточно поставить между вводом питания и аналоговым пином ещё один резистор, на 18k - теперь до подачи питания на пин +5V Arduino не хватало тока, чтобы включиться, и старт проходил нормально.

Первая макетка управляла коммутацией лишь сигнальных линий USB. Быстро выяснилось, что этого недостаточно: хабы "не замечали" перекоммутации, и переключение мыши, клавиатуры и звуковой карты на другое устройство затягивалось на десятки секунд (а иногда и вовсе не происходило). Стало очевидно, что нужно также отключать питание управляемых устройств, для чего на схему были добавлены ещё четыре реле: по одному на каждый канал и одно для обесточивания "левого" хаба при переключении между телефоном и док-станцией. В итоге алгоритм переключения стал выглядеть следующим образом:

  1. Отключаем линии связи со "старым" ведущим устройством.

  2. Отключаем питание.

  3. Ждём две секунды.

  4. Включаем питание.

  5. Включаем линии связи с "новым" ведущим устройством.

В таком режиме переключение стало происходить чётко и быстро - как при ручном подключении соответствующих разъёмов. Правда, для управления реле пришлось выделить отдельные пины на контроллере, чтобы светодиод, отображающий состояние коммутации, не гас на время принудительного отключения - такое поведение несколько дизориентировало. Это привело к тому, что остальные компоненты пришлось "втискивать" в оставшиеся свободными выводы ардуинки - сменив клавиатуру на аналоговую и даже сведя входные напряжения от обоих кабелей, ведущих к системному блоку, на один пин.

Ещё одной проблемой макеток были небольшие потери пакетов высокоскоростных устройств - изредка выпадали кадры с камеры, а в колонках при работе с телефона раздавались щелчки. Эти проблемы удалось нивелировать, сократив длину монтажного провода и, где возможно, подключив разрезанные USB-кабели напрямую к коммутаторам вместо распайки разъёмов USB-A и USB-B на макетке.

Итоговый проект

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

Линии передачи данных USBЛинии передачи данных USB

Здесь все переключатели с K1 по K5 представлены микросхемами FST3125. K1 и K2 управляются совместно, остальные - независимо. K1..K4 переключаются сигналами с контроллера, K5 - наличием напряжения на разъёме USB B, к которому подключается телефон.

Разводка питания выполнена по следующей схеме:

Разводка питанияРазводка питания

Земля (на схеме опущена) на всех разъёмах и на плате общая. Переключатели с K6 по K11 - это реле V23079A1001B301. Легко видеть, что питание схемы и большей части переферии обеспечивается системным блоком, если он выключен - то док-станцией, а в крайнем случае - телефоном. Для этого реле K6 и K7 управляются напрямую наличием питания на соответствующих разъёмах.

Реле K8..K11 управляются контроллером и используются для временного отключения устройств при переключении (переферии - между ведущими устройствами, первого хаба - между телефоном и док-станцией). Нагрузка подключена на их нормально замкнутые контакты, чтобы не увеличивать пиковый ток за счёт обмоток. Звуковая карта имеет приоритетное питание напрямую от системного блока.

Для создания финальной схемы и разводки дорожек я использовал EasyEDA, расположив элементы таким образом, чтобы минимизировать длину дорожек, по которым идут данные USB. Размеры платы я подогнал под пластиковый корпус, купленный в местном радиомагазине. Пульт собрал в отдельном маленьком корпусе и соединил с основной схемой жгутом монтажного провода, затянутом в термоусадочную трубку.

Плату я заказал в Китае. В готовом виде она выглядит следующим образом:

Готовые платыГотовые платы

Правда, тут вышла небольшая накладка: распределяя пины контроллера для упрощения разводки, я случайно поменял местами пин с ШИМом и пин без него. В итоге управление яркостью светодиодов на одном из каналов стало невозможным. К счастью, это была единственная крупная ошибка, и я решил проблему, перерезав пару дорожек и соединив их крест-накрест монтажным проводом. Кроме того, я несколько неверно разметил выводы для подключения светодиодов, но это решилось иной распайкой проводов с пульта заменой номера пинов в программе.

Неприятным сюрпризом стали проблемы с потерей пакетов с камеры. Вскоре выяснилось, что пакеты теряются, только если камера подключена к хабу, соединённому с компьютером без промежуточной логики. При подключении через второй хаб, соединённый с ведущими устройствами через коммутатор FST3125, потерь не было. Не было их также и при переключении камеры на разъём, предназначенный для звуковой карты и подключенный к системному блоку в обход хабов. Наконец, подключив хаб напрямую к компьютеру обрезком USB-кабеля (а не через разъём USB-B, распаянный на плате), я снова добился отсутствия потерь.

Таблица ниже содержит информацию о том, в каких случаях наблюдались потери пакетов.

Состав тракта

Потери пакетов

Компьютер - кабель - разъём USB B - дорожки на плате - провода между платой и хабом - хаб - провода между хабом и платой - дорожки на плате - микросхема-коммутатор - дорожки на плате - разъём USB A - кабель - камера

Да

Компьютер - кабель - хаб - провода между хабом и платой - дорожки на плате - микросхема-коммутатор - дорожки на плате - разъём USB A - кабель - камера

Нет

Компьютер - кабель - разъём USB B - дорожки на плате - микросхема-коммутатор - дорожки на плате - разъём USB A - кабель - камера

Нет

Компьютер - кабель - разъём USB B - дорожки на плате - микросхема-коммутатор - дорожки на плате - провода между платой и хабом - хаб - провода между хабом и платой - дорожки на плате - микросхема-коммутатор - дорожки на плате - разъём USB A - кабель - камера

Нет

Из этой таблицы становится ясно, что потери пакетов наблюдаются только в том случае, если после разъёма USB B, в который включен кабель, пришедший с компьютера, следует отрезок провода, ведущий на плату хаба, причём между двумя этими отрезками нет микросхемы-коммутатора. По-видимому, кабель USB и перемычка из монтажного провода обладают разными волновыми сопротивлениями, что ведёт к появлению отражений на их границе и, соответственно, к потере пакетов. Микросхема FST3125, включенная между этими отрезками, эффективно гасит подобные отражения.

Чтобы проверить эту теорию, я соединил хаб с основной платой не монтажным проводом, а отрезком того самого кабеля, которым он далее подключен к компьютеру через разъём USB B. Результат превзошёл все ожидания: потери кадров полностью прекратились, и всё заработало как часы.

Плату я разместил в пластиковом корпусе, закрепив двумя гайками и прорезав окошки для разъёмов. Контроллер поставил в колодки, чтобы иметь возможность извлечь его для обновления прошивки. Хабы подвесил на проводах - они прижаты к верхней крышке корпуса их жёсткостью, что не должно создавать проблем. Сам корпус я подвесил на шнурке к креплению настольной лампы, а пульт положил на стол. Разъёмы подписал белым маркером.

Основной модуль в сбореОсновной модуль в сборе

Программа написана на C++ и доступна по ссылке. Я постарался разделить сущности, отвечающие за взаимодействие с различными компонентами схемы, хотя и поленился выделить код методов в файлы cpp, рассудив, что система сборки Arduino Studio всё равно не извлечёт из этого какой-либо выгоды. За работу с кнопками (прежде всего, антидребезг) отвечает библиотека GyverButton. За тайминг (отключение устройств, мигание и снижение яркости светодиодов) - GyverTimer. И то, и другое достпно в пакете GyverLibs - пользуясь случаем, выражаю его автору свою благодарность.

Резюме

Задача оказалась хорошей в учебном плане - благодаря работе над проектом я обрёл новые навыки и знания. Это касается как работы с железом (раздача питания, коммутация потоков данных, управление индикацией, пайка микросхем в форм-факторе SOIC, отражения в высокочастотном тракте), так и представлений о современных контроллерах и способах их использования. Получившееся изделие прекрасно справляется со своей задачей - использование телефона в качестве рабочего места или источника музыки происходит теперь весьма просто.

В то же время, существующее железо для Arduino не позволило пойти по пути быстрого прототипирования, поскольку многое пришлось изобретать самому, что сильно затянуло проект. Надеюсь, следующую задумку - управление работой дистиллятора - удастся реализовать более прямым путём.

Подробнее..

MIDI браслет для управления синтезаторами (в основном для органично звучащего вибрато)

15.04.2021 00:12:17 | Автор: admin

Для нетерпеливых - ссылка на видео с демонстрацией и полным контентом поста в конце

Одной из распространенных привычек среди мультиинструменталистов, когда дело доходит до игры на стандартной фортепианной клавиатуре, является попытка применить выразительность других классов инструментов к простым вкл/выкл переключателем синтезатора, как правило, без какого-либо эффекта. Это распространяется и на другие музыкальные периферии, иногда более подходящие для таких манипуляций.

Обычно МИДИ клавиатуры оснащены питчбенд колесами, сенсорными полосками или джостиками, но они редко производят естественно звучащий результат и оккупируют одну из рук полностью. Именно по причине неестественности звучания одна из осей джойстика как правило привязана к вибрато.

Не удивительно, что на рынке полно устройств, которые преобразовывают это усилие в язык музыки. Первый это Roli Seaboard, мультиполифоническая MIDI-клавиатура которая позволяет сопоставлять жесты со звуковыми параметрами. Другая схожая интерпретация этой идеи это Хакен Континуум. Оба эти варианта поставляются с премиальным ценником, и по моему мнению - заслужено.

Следующий пример чуть мене комплексный. Genki Waves, насколько я понимаю, состоит в основном из кольца, которое может управлять программным обеспечением. Но сайт позволяет приобрести модуль eurorack и midi-адаптер 5din, что делает этот сетап вполне универсальным.

Другой вариант, если существует необходимость управлять железными синтезаторами Enhancia Neova ring. Полный комплект состоит из кольца, станции с современными 3,5 - мм MIDI входом и выходом и программного обеспечения для точной интерпретации жестов.

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

Запустив быстрый гугл поиск я нашел библиотеку ESP32BLEMIDI, которая позволяет отправлять миди-сообщения посредством беспроводной блютуз связи, и которую люди, судя по информации, использовали успешно, и начал составлять план.

План состоит в использовании двух плат esp32. Один-как наручный сервер, собирающий данные с акселерометра и преобразующий их в сообщения об изменении высоты тона и модуляции. Я привяжу тангаж к бендам и крен к модуляции. Кроме того, поскольку на борту модуля MPU6050 есть встроенный гироскоп, для бендов я также буду собирать информацию о горизонтальном смещении, поскольку оно также отображает это интуитивное движение. Три потенциометра будут контролировать чувствительность каждой оси к соответствующему параметру. Литиевая батарея будет поддерживать беспроводную работу устройства с помощью модуля управления зарядкой. Этот конкретный модуль поддерживает все средства защиты и не имеет никаких ограничений по минимальному току, что, наконец, отправило платы на базе tp4056 для меня в отставку. В таком случае у меня будет возможность подключить свой компьютер к наручному блоку для управления программными синтезаторами с, я надеюсь, низкой задержкой. Для управления любыми железными блоками я также построю стационарный хаб, который сможет конвертировать беспроводные BLEMIDI сообщения в аппаратные MIDI сообщения для взаимодействия с аппаратными синтезаторами. Для этого хаба я выбрал контроллер с OLED-экраном и с помощью поворотного энкодера смогу переназначить бенды и модуляцию как любую другую MIDI CC команду для управления громкостью, панорамированием, позиции уэйвтейбла и всем тем, что конкретный синтезатор сможет изменить на лету. Я не могу собрать простую сквозную схему, она неизбежно повредит данные, это должна быть полноценная смешивающая схема. Я также добавлю 2 CV-выхода для взаимодействия с модульным и полумодульным оборудованием.

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

Со стороны станции я припаял аппаратные MIDI входы и выходы и операционные усилители для усиления сигналов от ЦАПОВ до уровней CV, идущих на выходы 3,5 мм. Входящие BT-сообщения могут быть реорганизованы как любое MIDI СС-сообщение идущее через любой канал чтобы управлять несколькими синтезаторами одновременно, или переключаться между ними.

Первым делом стоит проверить работу напрямую с компьютером, для этого нужно выполнить сопряжение, выбрать режим драйвера в моей DAW-станции и установить флажок для прослушивания входящих сообщений. Данные с гироскопа создают много шума, все чувствуется слегка неконтролируемо, результаты намного чище когда на бенды влияют только данные с акселерометра. Тестирование показало, что существенной разницы между цифровым и аналоговым акселерометром нет.

Есть небольшая задержка, но так как выразительность-главная цель, на это стоит обратить внимание. Кроме того, устройство постоянно отключалось и подключение никогда не следовало одной и той же процедуре и требовало несколько перезагрузок и перезапусков DAW. Это очень неудобно и выбивает из колеи.

После отключения всех остальных беспроводных соединений на моем компьютере, включая Wi-Fi, задержка сократилась, и проблема отключения стала менее частой. Это привело меня к выводу, что слабым звеном в этой цепочке являются беспроводные возможности моего компьютера. Поскольку мой конкретный аудиоинтерфейс не имеет MIDI-портов, я схватил Arduino Due и быстренько собрал USB-MIDI-интерфейс, чтобы иметь возможность сопряжать устройство со станцией, подключать станцию к интерфейсу миди-кабелем, подключать интерфейс к ПК и получать MIDI-сообщения таким образом. И проблема отваливания от блютуз исчезла.

На данный момент все еще существует некоторая задержка, поэтому мне пришлось внести несколько коррективов в первоначальный план.

Поскольку прямое BT подключение к моему компьютеру немного медленное, и я все равно скован использованием MIDI-USB интерфейса, вместо того чтобы читать значения, преобразовывать их в BT midi и отправлять медленные BT MIDI сообщения для отправки обычных MIDI, я решил полностью лишить сообщения универсального протокола и отправлять необработанные значения и преобразовывать их на принимающем конце в MIDI, уменьшая количество шагов и объем отправляемых данных. Для этого я использовал протокол ESPNOW, который без каких-либо махинаций с рукопожатиями при наличии только mac-адреса может отправлять только 3 байта данных на устройство, которое ожидает только 3 байта данных. Я удалил все куски кода с подтверждением передачи, чтобы уменьшить задержку. И все заработало безупречно.

Эта конкретная сборка работает нормально, на этом этапе стоит просто минитюаризовать дизайн и закончить печать всех корпусов. Но некоторые мелочи меня не устраивали.

Во-первых, это конструкция из 3 контроллеров, где на самом деле требуется только 2. Прием данных, создание MIDI и преобразование в USB MIDI должны происходить в одном устройстве. И это, как минимум в теории, довольно легко реализовать, потому что более поздняя версия ESP32 под названием S2 способна быть нативным USB устройством, что делает адаптацию кода довольно легкой. Но мало того, что этой штуки у меня нет, существуют и другие проблемы.

В основном энергопотребление. Текущая установка убивает относительно жирную батарейку через полчаса. Именно по этой причине на всех кадрах был шнур, это не связь, это просто для питания. И проблема даже не в емкости, а в возможностях токоотдачи этой батареи примерно на 3,5 В она просто перестает быть способной питать прожорливый BT/WIFI чип. Это заставляет меня поменять аппаратное обеспечение и перепроектировать все с нуля.

Поскольку лучшая прошивка с точки зрения задержки использовала прямую передачу пакетов, не будучи завернутой в очень специфический протокол, я решил использовать модули nrf24l01+, которые очень похожи в этом отношении. Это означает, что я могу соединить этот модуль с DUE, которая раньше был просто MIDI USB интерфейсом, и использовать его в качестве хаба, который и делает все - прием данных, аппаратное midi, USB midi, CV-напряжение, реорганизацию сообщений и т. Д.

В качестве передатчика у меня было 2 варианта Pro Micro и STM32 blue pill. Второй вариант не только менее энергозатратен, но и имеет гораздо большее разрешение на входах АЦП, что позволит избежать потенциальных резких рывков при изменении уровня эффекта. Не говоря уже о том, насколько большими вычислительными способностями он обладает.

Таким образом, сетап меняется от сложного чтения данных об ускорении, обертывания этих данных в протокол BLE MIDI, отправки BLE MIDI, преобразования в MIDI и преобразования из MIDI в USB MIDI к гораздо более простому чтения данных об ускорении, отправки этих необработанных данных, а затем простого преобразования их в USB MIDI. И как всем известно, простое решение это надежное решение.

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

Я могу использовать встроенные в синтезатор бенды и модуляции. Я могу перенаправить разные CC на любой параметр VST на любом канале. Я могу использовать устройство для управления несколькими параметрами одного синтезатора. Я могу использовать устройство для управления параметрами нескольких VST одновременно. Можно во время или после записи прописать автоматизацию трека по параметру.

Так что в конце дня у меня было 3 версии одного и того же устройства. BT версия полезна в том случае, когда требуется только подключение к ПК. Будучи по своей сути BT сервером при переключении между ПК и хабом, я должен вручную прерывать соединение и каждый раз устанавливать новое. Поэтому, поскольку я не использую свой компьютер в качестве центра управления железными синтами (не то, чтобы мой аудиоинтерфейс это поддерживает) мне не хочется продолжать реализацию конкретно этой версии. Однако существует открытый проект умных часов, в которые встроен акселерометр. Сенсорный экран должен быть способен вместить в себя все меню, переключать каналы, номера CC сообщений и чувствительность и позволять хранить множество пресетов. Будучи проектом на базе ESP32, перенос проекта не должен вызвать много проблем, если когда-нибудь я заполучу его в свои руки. Я чувствую себя обязанным подчеркнуть, что я протестировал более одного модуля ESP32, и задержка колеблется от юзабельной до невыносимой, и я понятия не имею, как будет вести себя этот конкретный блок. Задержка также коррелировала с энергопотреблением более медленный модуль был способен жить от батареи гораздо дольше, разряжая ее должным образом.

То же самое устройство должно открыть возможность использовать версию на базе ESPNOW, которая показала наименьшую задержку, но я бы связал ее с ESP32-S2 в качестве хаба, чтобы иметь функционал нативного USB. В данный момент у меня нет ни того, ни другого, и я не собираюсь тратить на них деньги.

Тем более, что текущая рабочая версия, основанная на DUE и STM32, обеспечивает наилучший баланс между задержкой (она в принципе существует только в контексте версии ESPNOW) и простотой. Энергопотребление очень низкое и я не смог разрядить батарею во время тестирования. Станция поддерживает как USB, так и аппаратный MIDI одновременно, без необходимости ручного подключения, мне просто нужно щелкнуть переключатель и подать питание. Эту версию все еще можно сделать намного меньше, но в данный момент это не принципиально. Что можно поменять, так это железо. Либо поставить более мощную версию NRF24 в хаб, либо перенести весь проект на LORA.

Cсылка на видео (с демонстрацией игры)

Код

Подробнее..

Ненормативная схемотехника ATmega8 кто сказал, что выше головы не прыгнешь?

30.04.2021 12:16:20 | Автор: admin
Вот уж несколько лет, как я увлёкся микроконтроллерами, а именно семейством AVR. Ещё на этапе освоения Ардуино (в этот момент часть аудитории поплевались и ушли читать другие статьи) я пытался выдавить из неё больше, чем задумано. Меня всегда больше интересовали нестандартные решения обычных задач. Сейчас я знаю об AVR намного больше, чем ещё пару лет назад, и всё больше убеждаюсь, что знаю очень мало.

С чего начинает среднестатистический начинающий электронщик? Правильно, с часов! Как только научился пользоваться голыми контроллерами, а не платами Ардуино, захотел сделать часы на Атмеге, голой Атмеге без кучи ключей и буферных микросхем. И обязательно со статической индикацией, а не с динамической (ну не люблю я её). Собственно, статическая индикация программно гораздо проще, а ведь мы простых путей не ищем. Но зато возникают другие проблемы, которые несколько раз меня останавливали в самом начале пути. Понятно, что если взять Атмегу пожирней, задействовать в ней половину ножек и полпроцента памяти, задача упрощается донельзя, собственно, такие настольные часы на ATmega128 работают у меня на столе пару лет.

Но это не наш метод. Я с самого начала хотел именно ATmega8, как самую доступную и самую дешёвую (в том числе в дип-корпусе). Всё то же самое можно и на ATmega48, но её попробуй ещё найди, разве что у Вас в ящике стола валяется их много с незапамятных времён.
Посмотрим на картинку, известную всем, кто недавно интересуется AVR.

Глядя на неё, легко посчитать, что мы можем задействовать на часовой индикатор 20 ножек, ещё на двух у нас будет кварц (куда от него денешься, внутреннее тактирование не прокатит, нам ведь от часов нужна точность какая-никакая). Ну и сброс. На четыре семисегментных индикатора нужно 28 ног, ну даже 27, ведь десятки часов можно отображать цифрами 1 и 2, а ноль не отображать. Ещё когда идея только зарождалась, я это количество сократил до 22 ножек, ведь для отображения десятков часов можно обойтись цифрой 1, и оба её сегмента зажигать от одной ноги контроллера. Но как ни крути, пары ног мне всё же не хватало, даже при том что я давно знал о возможности использования как ввода-вывода ножки Reset, но так ещё ни разу и не попробовал (если не считать ATtiny13, её не так жалко было), ведь параллельного программатора у меня нет, а любая отладка это минимум несколько итераций прошивки, вряд ли всё идеально выйдет с первого раза. Так и лежал этот замысел в закромах мозга, и ждал своего времени, пока как-то мне не пришла в голову ещё одна интересная идея.
Посмотрел я однажды на светодиодную ленту (120 светодиодов на метр) и понял, что можно легко и просто сделать электронные часы любого размера с её использованием. Просто нарезаем сегменты желаемой длины и наклеиваем их на подходящее основание, для больших размеров сегмент может складываться из двух и более лент по ширине. В моём случае отрезаем сегменты по шесть светиков, таким образом длина сегмента составляет 50 мм, высота цифры 100, для моей задумки офисных часов вполне достаточно.

Но вот незадача, напряжение питания ленты 12 вольт, а AVR хочет не больше 5 вольт (люди утверждают, что и 8 вольт выдерживают, но я проверять пока не буду, да и не поможет). То есть нужно ставить 22 ключа для включения всех сегментов. Если применить драйвер ULN2003, хватит (почти) трёх штук, это копейки, но, как я писал выше, это не наш метод, хотя этот вариант можно приберечь для часов побольше. Ну никак это не вписывается в концепцию голая Атмега.
И вот тут-то начинается самое интересное. Напряжение питания ленты 12 вольт, первые признаки жизни белые светодиоды (три штуки последовательно) начинают подавать при более чем 7.5 вольт, и, что очень важно, до этого напряжения ток через ленту практически равен нулю (можете проверить). На ножке контроллера, работающей в режиме выхода, может быть уровень 0 вольт или 5 вольт (третий вариант рассмотрим позже), и если подключить сегмент анодом к +12 вольт, а катодом к выходу контроллера, напряжение на сегменте будет равняться соответственно 12 вольт (светит) или 7 вольт (не светит). Даже если бы через погасший сегмент протекал мизерный ток, он ушёл бы к плюсу питания контроллера через защитный диод, которые в AVR гораздо более выносливые, чем нас пугали в обучающих статьях. Третий вариант ножка в режиме входа, напряжение на сегменте 7 вольт благодаря защитному диоду, стало быть сегмент не светит. Конечно, как только я обдумал всё это в теории, сразу же проверил на практике, залив в контроллер простой блинк для одной из ног.

А так как сейчас в силу некоторых обстоятельств мои возможности для экспериментов слегка ограничены, напряжение питания для сегмента случайно оказалось более 18 вольт, и сегмент гас не полностью, так что я успел разочаровано подумать, что подпалил выход. Когда уменьшил напряжение (на тот момент даже нечем было померить), всё стало на свои места, так что, благодаря нелепой случайности, теперь я точно знаю, что для схемы не смертельно небольшое повышение напряжения выше 12 вольт. С напряжением определились, а что с током? На моей ленте (и скорей всего на вашей тоже) стоят резисторы по 150 ом, ток через сегмент не более 20 мА, только сегмент в данном случае это три светика, а каждый сегмент моих часов состоят из двух сегментов ленты, так что 40 мА. Вроде даже вписываемся в даташит, но на 20 выходов это уже 800 мА, что намного выше дозволенных 200 мА на корпус. Ток через ленту очень зависит от напряжения на ней, и нелинейно падает даже при небольшом снижении, что является большим минусом при обычном использовании ленты, и плюсом в данном случае, ведь реальное напряжение на сегментах равно 12 вольт минус падение на ключе (около 0.6 вольт), а ещё при желании можно снизить напряжение питания, понизив тем самым яркость часов. Так что страшные 800 мА несложно снизить раза в два. В любом случае, я был уверен, что это не станет проблемой, да и приобретённый опыт ценнее, чем возможность потери одной Атмеги. Вот так просто ATmega8 коммутирует индикатор с напряжением в два с лишним раза выше, чем её собственное напряжение питания. Именно это я имел ввиду в заголовке статьи. Хотя способ совсем не нов, по такому же принципу работает советская микросхема К155ИД1 высоковольтный дешифратор управления газоразрядными индикаторами, где сравнительно низковольтные выходы (до 60 вольт) коммутировали индикаторы с напряжением зажигания 150 вольт и выше.

Дальнейшие эксперименты я продолжил с обычным четырёхсимвольным семисегментным индикатором с общими анодами и раздельными катодами, как раз припасён был для такого случая.

Аноды к +5 вольт через один на всех резистор, для отладки прошивки этого за глаза. Первоначально я остановился на варианте использования в качестве двух недостающих ног пинов подключения кварца (итого 22 выхода), а тактировать контроллер от внешнего генератора минутных импульсов через (внимание!)

вход сброса. Это ещё один занимательный лайфхак, который описан здесь Как сохранять переменные arduino, при reset
Можете попробовать залить в Ардуино простой код и посмотреть результат работы в Мониторе порта, периодически сбрасывая её кнопкой или с клавиатуры:
пробник
#define NO_INIT __attribute__((section(".noinit")))void setup() {    static unsigned NO_INIT nonInitCounter;    nonInitCounter=nonInitCounter+2048;    Serial.begin(9600);    Serial.print("Setup counter: ");    Serial.println(nonInitCounter);}void loop(){}

Не буду приводить свой код, дабы не подвергаться критике лишний раз (я не самый лучший
программист), но если в двух словах, можно создать глобальную переменную, которая сохраняется при перезагрузке контроллера. Раз в минуту под воздействием внешнего импульса сброса Атмега перезагружается, и начинает заново отрабатывать прошивку: считывает переменную, преобразует её в показания часов и минут, выводит на индикатор, увеличивает переменную на одну минуту. Дальше опять сброс, и всё по-новой. Пришлось порыться в интернете и опробовать два вида программного сброса, ведь внешнего генератора у меня пока не было, а жмакать сброс всё время вручную не сильно удобно.
пример функции
void softReset() {  //программный сброс //http://kazus.ru/forums/showthread.php?t=13540&page=3#  asm volatile ("rjmp 0x0000");//Sketch uses 2412 bytes  //программный сброс //https://www.cyberforum.ru/post11307314.html  //((void(*)(void))0)();//Sketch uses 2416 bytes}

Что интересно, эта переменная может сохраняться даже после отключения питания (не всегда). И это не EEPROM, если кто подумал. По мере отладки я пришёл к использованию нескольких таких переменных.
Кто-то скажет: какой внешний генератор, а как же концепция голой Атмеги? На момент опытов я был уверен, что в качестве генератора выступит некая козявка размером с рисинку и ценой в пару копеек. Но когда всё заработало в теории и пришло время с козявкой определиться, меня ждал облом. Единственное, что меня могло бы устроить, это старая добрая К176ИЕ12, кто бы мог подумать! На дворе двадцать первый век, а в природе нет простого доступного аппаратного генератора минутных импульсов.
Не беда, подумал я. Можно и раз в секунду. Немного переписал код, проверил работу, отлично. Но опять же, для внешнего генератора я нашёл только DS1307 (и её аналоги). Да, стоит копейки, для обвязки достаточно кварца (и ещё несколько необязательных элементов). Вот только чтобы она генерировала секундные импульсы, ей нужно подать команду по шине I2C. Чем подать? И какую? (Теперь я уже знаю, но на тот момент не было с чем пробовать). Короче, не подходит. Ладно, последняя надежда. Некоторые западные часы 90-х тактировались частотой сети 50 гц. Возможно, сейчас у нас частота стабильней, чем была 30 лет назад. Попробовал сымитировать работает. Если бы воплотил в жизнь, было бы оригинально контроллер, перезагружающийся 100 раз в секунду. Но я пока отмёл этот вариант и стал искать другие.
Итак, я мог использовать 22 выхода (что мне достаточно) и пин сброса в качестве входа. Но не срослось Вернёмся к варианту с кварцем. Минус две ноги на кварц получаем 20, даже если ножку сброса сделать портом ввода-вывода, получим 21, всё равно не хватает одного, хоть ты тресни! Но недавно я нашёл способ, о котором задумывался ещё два года назад, что-то не получилось тогда. У нас есть пин AREF для опорного напряжения, относительно которого происходят аналоговые измерения. И на этот пин мы можем программно подать напряжение питания в качестве опорного или встроенное опорное напряжение 2.56 (для ATmega8). Проверил, измерил, действительно можно получить на ножке AREF напряжение 0 вольт, 2.56 вольт, или 5 вольт.
превращаем AREF в ещё один выход
// превращаем AREF в ещё один выходvoid setup() {}void loop() {  ADMUX = 7 + 64; // уровень 1 (5 вольт) // 7-номер аналогового входа//почему 7 аналоговый вход? А потому что физически у Атмеги входы от 0 до 5,//и назначение аналоговым входом входа 7 не помешает работе остальных в качестве выходов  delay(3000);  ADMUX = 7 + 64 + 128; // уровень 2.56 вольт // 7-номер аналогового входа  delay(3000);  ADMUX = 7; // уровень 0  delay(3000);}

Нюанс: это если замерять относительно общего провода. Если мерить относительно +5 вольт, во всех трёх случаях получаем ноль. То есть нагрузку можно подключить между AREF и общим. Экспериментально установил, что можно получить ток до 20 мА при 2.56 вольт на ноге и до 40 мА при 5 вольт на ноге, этого вполне достаточно, чтоб зажечь светодиод, к примеру. Вот он, заветный двадцать второй выход! Конечно, напрямую управлять двенадцативольтовым сегментом не получится, нужен транзистор. Под руку попался легендарный КТ315, сколько лет я к нему не прикасался, как по мне, это одно из лучших произведений советской электроники, наряду с микрухой К155ЛА3. Когда-то я КТ315 и КТ361 даже в качестве ключей импульсного трансформатора питания применял, при напряжении порядка 60 вольт, и неоднократно. Здесь же нагрузка для него плёвая, и я принципиально даже резистор в базу не поставлю (20 мА вполне себе допустимый ток базы).
Ну что ж, думал я, 22 выхода есть, отлажу код с 21 выходом, а 22-й на ножке сброса оставлю напоследок, когда всё остальное уже заработало. Ещё ведь и кнопки установки времени нужно куда-то приткнуть, а ног не осталось вовсе. Если б Атмега была в SMD-корпусе, можно было бы воспользоваться входами А6 и А7, выходами они всё равно не умеют. Но у меня корпус DIP, так что такой роскоши позволить себе не могу. Зато ведь можно выходы сделать входами, правда, в это время придётся погасить индикацию, но для опроса кнопок достаточно нескольких миллисекунд, никто и не заметит (как я ошибался!). Значит, перевожу ножки кнопок в режим входов, подтягиваем программно к питанию, и ждём пару миллисекунд. Если в это время какая-то из кнопок замкнута на минус, ждём ещё 20 миллисекунд, убеждаемся, что кнопка всё ещё нажата, и производим соответствующее действие в программе. Кнопки: минуты плюс, минуты минус, часы плюс, коррекция плюс. Коррекция подстройка значения секунд раз в сутки в зависимости от суточного ухода показаний. Всё заработало почти с первого раза. Нюанс: при замкнутой кнопке сегмент, подключенный к той же ножке, оказывается включён, такой вот побочный эффект, что поделать. Поэтому кнопки изменения минут подключаю к выводам контроллера, которые управляют сегментами единиц часов, а кнопки изменения часов подключаю к выводам контроллера, которые управляют сегментами единиц минут. Выставляя минуты, совсем не обращаешь внимания, что с показаниями часов что-то не так, и наоборот.
Ну вот всё и получилось в макете с семисегментными индикаторами. Но параллельно я пытался накопать информации по поводу применения ноги сброса в качестве порта ввода-вывода. А там всё довольно туманно и неопределённо. Основное, что об этом пишут: 1 выход с открытым коллектором (не точно), 2 выход чрезвычайно слаботочный (тоже не наверняка). Даже если использовать внешний транзистор, нужно точно знать, открытый коллектор (сток) или нет, ведь тогда состояние выхода нужно инвертировать. А перепрошить я уже не смогу. В общем, опять двадцать пять! Вернее, двадцать один. Двадцать один гарантированный выход вместо 22. Опять одного не хватает. Опять я мечусь в поисках решения.
Возвращаюсь к AREF. Я могу получить три разных уровня на нём. Значит можно зажечь один сегмент, или два одновременно, или ни одного. Я обратился к своей же прошлой публикации (как давно это было!):Ненормативная схемотехника: семисегментный индикатор на ATtiny13
Чтобы попробовать использовать решение с совместным включением двух сегментов. Перебирая возможные пары сегментов, и осознавая, что подобное усложнение портит всю картину, я внезапно додумался, что для цифры десятков минут поле поиска значительно сужается цифра ведь может быть только от 0 до 5. И тут пришло озарение:

во всех этих цифрах сегменты А и D или вместе светятся, или вместе погашены! Не нужно никаких трёх состояний, достаточно просто соединить сегменты А и D вместе и подключить к одному выходу. И теперь 21 выхода хватит всем. Довожу код, проверяю на макетке с семисегментным индикатором, бинго!
Всё, пора делать финальный вариант. Нарезаю светодиодную ленту, наклеиваю сегменты на подходящее основание, которым оказался кусок пластиковой вагонки (примерно 150х350 для цифр высотой 100). К каждому сегменту нужно подвести +12 вольт и проводник от соответствующего выхода контроллера.

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

Сегменты цифр разведены по контроллеру именно в таком порядке для упрощения кода.
Первая цифра (единица, напоминаю) состоит из цельного куска ленты длиной 10 см. Подключаю 5 вольт питания контроллера и 12 вольт питания индикации, включаю. Вот он, торжественный момент, всё красиво светится, часики работают. Кстати, на КДПВ в начале статьи в качестве светофильтра на индикаторах лежит лист обычной бумаги для принтера, яркости хватает с избытком.
Мне не очень нравится американская система отображения времени, когда часы дважды в сутки считают до двенадцати. Я применил свою: с нуля часов до 19, и затем 8, 9, 10, 11. А с учётом того, что часы офисные, в 8 вечера их редко кто увидит.

В такие моменты ощущаешь некоторое разочарование, что прям вот так сразу заработало, даже как-то неинтересно. Поначалу я упорно не хотел замечать некое мерцание индикаторов, пока мне на него не указали коллеги. В макете этого мерцания не было видно совсем, а тут прям бросается в глаза. Выше я писал, что при опросе кнопок после перевода ножек в режим ввода сделана пауза в пару миллисекунд, без этой паузы остаточный потенциал на ножке воспринимался как нажатие. Так вот тих двух миллисекунд, в течение которых индикаторы потушены, оказалось достаточно для мерцания индикации. И это при том, что опрос происходит два раза в секунду. То есть глаз замечает двухмиллисекундную паузу дважды в секунду, чего я никак не ожидал. Было подозрение, что вследствие переходных процессов контроллер каждый раз перепроверяет, действительно ли нажаты кнопки (а это по 20 мсек на каждую). Я внёс некоторые изменения в код, временно отключив все лишние функции, но подозрения не подтвердились. В результате помогли следующие изменения: для опроса кнопок перевожу те выходы, которые задействованы под кнопки, в высокий уровень, тем самым погасив соответствующие сегменты, только после этого перевожу те же ножки в режим входа. Таким образом от паузы в 2 мсек можно избавиться совсем, но я оставил на всякий случай 300 микросекунд, проблема исчезла полностью.
Что мы имеем в итоге? Ножка сброса контроллера работает по прямому назначению и используется только при заливке прошивки, ножки кварца подключены к кварцу, как и положено. Двадцать ног работают как порты ввода-вывода, и нога AREF управляет ключевым транзистором, как раз на него и навешена цифра десятков часов (1). Ещё четыре ножки питания, никто не отлынивает, все ноги задействованы. По поводу кварца: я всерьёз рассматривал вариант применения часового кварцевого резонатора на 32768 Гц (считал его более точным), но отказался от идеи, побороздив интернет. Оказывается, запустить Атмегу с часовым кварцем не так-то просто и нет никаких гарантий работоспособности, а плюсов от применения не особо. Экономичность нас не интересует в данном случае, основное потребление индикация. С точностью тоже всё неопределённо. А суточный уход вполне компенсируется программно. Зато большим плюсом является простота подключения, кварц на 8 или 16 МГц без проблем работает даже без конденсаторов. В результате вся схема состоит (если не считать индикаторы и питание) из Атмеги, кварцевого резонатора, и транзистора, припаянных прямо к панельке. Питание контроллера обеспечивается малогабаритным стабилизатором из серии 7805, ток через него мизерный, но на всякий случай я припаял его теплоотводом к кусочку оцинковки примерно 30х30 мм. В целом же часы питаются от внешнего блока питания на 12 вольт, который, по сути, дороже всех комплектующих. Фактический ток потребления часов 560 мА при показаниях часов 18-08 (это максимальное количество сегментов, которые можно засветить одновременно), получается около 28 мА на сегмент. Это при напряжении питания часов 11.7 вольт, ещё 0.3 вольта падает на диоде, включенном для защиты от неправильного подключения и чтоб немного снизить напряжение и ток соответственно. Падение на выходных ключах Атмеги около 0.56 вольт. Все токовые режимы превышены, но Атмега справляется, честь и хвала творцам! Запаса яркости избыточно, напряжение питания можно ещё снижать. Если тактировать Атмегу от внутреннего генератора, то можно ножки кварца отдать индикатору, а время считывать по I2C с DS1307. Опять же будут заняты все ноги, но зато питание часов можно будет отключать хоть на неделю, а время продолжит тикать. Хотя точность DS1307 совсем не радует, и по моему опыту, и по отзывам в интернете. Зато на ней есть дополнительный выход с открытым коллектором, которому можно дать команду мигать с частотой 1 Гц, и навесить на него разделительную точку. В моих часах разделительных точек пока нет, можно разрезать ту же ленту на отдельные светодиоды и подключить постоянно к напряжению питания. Мигать не будет, но я думаю над этим. Может, кто подскажет, как выжать ещё каплю из Атмеги?
И, напоследок, код для тех, кто захочет повторить. Компилировал и прошивал в ArduinoIDE. Я не программер, так что примите как есть, если кто предложит лучше, с удовольствием выложу.
Особо чувствительным не смотреть
Я предупреждал
bool Flag;uint8_t TimS;uint16_t TimH = 12; // время при включении 12-34uint16_t TimH_;uint16_t TimM = 34;uint16_t TimH0;uint16_t TimH1;uint16_t TimM0;uint16_t TimM1;uint16_t TimKorr = 7; // коррекия по умолчанию 7 - это 0 секунд, если 0 - это -28 сек, если 14 - это +28 сек// массив для цифрint semisegm_[10] = {B01011111, B00000110, B01101011, B01100111, B00110110, B01110101, B01111101, B00000111, B01111111, B01110111};void setup() {                                                         //  PORTB = 0;  PORTC = 0;  PORTD = 0;  // инициализация Timer1  cli();  // отключить глобальные прерывания  TCCR1A = 0;   // установить регистр в 0  TCCR1B = 0;   // установить регистр в 0  // Таймер переполняeтся каждые 65535 отсчетов при коэффициенте деления 1024 или за 4,194с  OCR1A = 62499; // установка регистра совпадения (4 секунд)  TCCR1B |= (1 << WGM12);  // включить CTC режим > сброс таймера по совпадению  TCCR1B |= (1 << CS10);   // Установить биты CS10 CS12 на коэффициент деления 1024  TCCR1B |= (1 << CS12);  TIMSK |= (1 << OCIE1A);  // для ATMEGA8  sei(); // включить глобальные прерывания}   void loop() {  if (TimM > 59) {    TimM = 0;    TimH++;    Flag = 0;  }  if (TimH > 23)TimH = 0;  if (TimM < 0) {    TimM = 59;  }  if (TimH == 0) {    if (TimM == 0) {      if (TimS == 7) {        if (Flag == 0) {          TimS = TimKorr;          Flag = 1;        }      }    }  }  TimH_ = TimH;  if (TimH > 19)TimH_ = TimH - 12;  TimH0 = TimH_ / 10;  TimH1 = TimH_ % 10;  TimM0 = TimM / 10;  TimM1 = TimM % 10;  Led(TimH0, TimH1, TimM0, TimM1);  Key();}// функция индикацииvoid Led(uint16_t TimH0, uint16_t TimH1, uint16_t TimM0, uint16_t TimM1) {  DDRB = semisegm_[TimM1];  DDRC = semisegm_[TimM0];  DDRD = semisegm_[TimH1];  bitWrite(DDRD, 7, bitRead(semisegm_[TimM1], 6));  ADMUX = 199 * TimH0; // уровень 2.56 на AREF  PORTB = 0;  PORTC = 0;  PORTD = 0;  delay(500); // полсекунды просто отображаем время}// функция опроса кнопокvoid Key() {  bitWrite(PORTB, 2, 1);  bitWrite(PORTD, 2, 1);  bitWrite(PORTD, 1, 1);  bitWrite(PORTD, 0, 1);  bitWrite(DDRB, 2, 0);  bitWrite(DDRD, 2, 0);  bitWrite(DDRD, 1, 0);  bitWrite(DDRD, 0, 0);  delayMicroseconds(300);   if (bit_is_clear(PINB, 2)) {      delay(20);    if (bit_is_clear(PINB, 2)) {      TimH++;    }  }  if (bit_is_clear(PIND, 1)) {    delay(20);    if (bit_is_clear(PIND, 1)) {      TimM++;    }  }  if (bit_is_clear(PIND, 0)) {    delay(20);    if (bit_is_clear(PIND, 0)) {      TimM--;    }  }  if (bit_is_clear(PIND, 2)) {    delay(20);    if (bit_is_clear(PIND, 2)) {      TimKorr++;      if (TimKorr > 14)TimKorr = 0;      Led(0, 8, TimKorr / 10, TimKorr % 10);      delay(500);    }  }}ISR(TIMER1_COMPA_vect) // Выполняем 1 раз в 4 секунды.{  TimS++;  if (TimS > 14) {    TimM++;    TimS = 0;  }}


Подробнее..

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

30.04.2021 20:15:00 | Автор: admin

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


Задача

Представьте, что вы прогуливаетесь по своему кварталу мимо красивых зелёных лужаек. Что такое?.. Вода же должна литься на газон, а не на тротуар рядом! Здесь люди ходят! Слева от вас большой газон орошается из-под земли десятком спринклеров. Но, хоть вся трава и поливается обильно, на газоне тут и там заметны проплешины. Многие не видят в этом проблемы эка невидаль! и безмятежно прыгают через лужи. Но проблема здесь не только в лужах, а в том, что, несмотря на использование такого количества воды, газон всё равно не растёт нормально. И проблема эта более серьёзная, чем можно подумать. В Америке от 30 до 60 % городской пресной воды используется для полива газонов, и самое печальное, что приблизительно 50 % этой воды тратится впустую из-за небрежно или неправильно установленной системы полива.

Уход за газонами недешёвое занятие. Чтобы газоны росли так, как нужно, необходимо правильно подобрать удобрения, компост и, самое главное, правильно их поливать. В этой статье я расскажу о разработанном мною решении какие шаги я предпринял при планировании, создании прототипа и внедрении.

Первоначальные соображения

В начале этого проекта у меня не было ни опыта работы с методами машинного распознавания образов, не говоря уже о каком-никаком плане.

Сухие проплешины.Сухие проплешины.

Разница в цвете между светло-коричневыми участками и зеленью здоровой травы сразу бросается в глаза. Я начал решать задачу так: проанализировал RGB-значения различных областей изображения. Если бы я мог выявлять "менее зелёные" области и найти критерий, по которому такие участки можно было выделять, я мог бы их точно определить. Однако всё оказалось не так просто, как я думал.

Главной проблемой было множество внешних факторов, на которые я повлиять не мог, но они могли сами повлиять на результаты. Например, RGB-значение участка изображения может быть изменено ночным электрическим освещением. При таком количестве посторонних факторов система была бы просто нежизнеспособна. Мне определённо нужно было искать лучшее решение.

Сегментация изображений

Новое решение оформилось в виде концепции, называемой сегментацией изображения. Сегментация изображений это процесс машинного распознавания образов, разделяющий изображения на "сегменты" на основе сходства пикселей. В основном он используется, чтобы обнаруживать на изображении объекты (в таком случае он называется методом обнаружения объектов), и применяется в автономных транспортных средствах, при обработке медицинских изображений и спутниковой съёмке.

Сегментация изображений.Сегментация изображений.

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

Я обнаружил замечательную библиотеку под названием ImageAI, написанную Олафенвой Мозесом. Библиотека ImageAI позволяет обнаруживать объекты с использованием набора данных, созданного пользователем. С помощью ImageAI мне удалось подобрать оптимальный набор данных, наиболее подходящий для моей модели.

Первый набор данных / Тестовый

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

Бесплатные общедоступные наборы данных можно найти на множестве веб-сайтов и во многих приложениях. Эти данные, в частности, могут использовать инженеры при работе над проектами. Однако для моего проекта никаких наборов данных не было, и поэтому мне пришлось создавать свои собственные. Как выяснилось, создание набора данных оказалось чуть ли не самой сложной проблемой во всём проекте.

Набор данных для сегментации изображений состоит из двух частей: изображений и аннотаций. Существует множество способов аннотирования изображений, то есть пометок места расположения объекта на изображении. Я использовал формат Pascal VOC, сохраняющий аннотации в файлах .xml. То есть, если мой набор данных содержит 50 изображений, мне пришлось бы аннотировать каждое отдельное изображение и создать 50 xml-файлов с аннотациями соответствующих изображений.

Вначале у меня было много вопросов о наборе данных: сколько изображений нужно иметь, как аннотировать изображение, как использовать аннотацию в коде, как узнать, подходит ли для модели то или иное изображение, и так далее. Тут мне здорово помог Олафенва Мозес, который, к счастью, написал очень информативную статью о том, как создавать пользовательский набор данных и использовать его в библиотеке ImageAI.

Первым шагом было получение изображений, и он оказался значительно сложнее, чем предполагалось. Как я ни старался, я не смог найти в сети нужные мне высококачественные изображения. Я погуглил строку "трава с проплешинами", и для первого набора данных мне удалось загрузить всего 65 изображений. Чтобы вы понимали большинство наборов данных содержат тысячи изображений, и только тогда их имеет смысл использовать для обучения модели.

После сбора изображений я закомментировал их с помощью программы Label IMG. Я создал каталог с изображениями и каталог для аннотаций. Затем я поставил аннотацию к каждому изображению, обведя в рамки все проплешины. Привожу ниже скриншот программы Label IMG, которую я использовал для аннотирования изображений.

Программа Label IMG.Программа Label IMG.

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

Набор данных 1. Результаты.Набор данных 1. Результаты.

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

Наборы данных 24 / Последующие тесты

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

Полистав Интернет, я обнаружил такую вещь, как парсеры (web scrapers). Парсер это инструмент, способный извлекать данные и содержимое с веб-сайтов и загружать эти файлы на локальный компьютер. Это было как раз то, что мне нужно, и после изучения краткого руководства я создал элементарный парсер, загружающий изображения, содержащие ключевые слова "трава с проплешинами", "плохая трава" и "плохой газон". С помощью этого парсера я собрал папку из 180 изображений, и это был мой второй набор данных.

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

Я обратился кое к кому за помощью, поизучал ещё теорию и вычитал, что есть такой хитрый приём аугментация изображений (image augmentation), то есть процесс, с помощью которого набор данных может быть расширен посредством внесения изменений в существующие изображения. Количество изображений меняется за счёт того, что меняются их ориентация и RGB-значения пикселей. Пример аугментации изображений.

Пример аугментации изображений.Пример аугментации изображений.Пример дополненных и реальных данных.Пример дополненных и реальных данных.

Для нас, людей, все приведённые выше изображения одинаковы, если не считать крохотных изменений; однако для компьютера, который рассматривает изображения как массивы значений пикселей, эти изображения совершенно разные. Попробуем использовать эту идею и создадим больше обучающих данных. И вот, я, страдавший от нехватки изображений, сразу получил их много больше, чем значительно улучшил свой набор данных. Для пополнения всего каталога изображений я использовал библиотеку Keras с определёнными параметрами и граничными значениями. Мой четвёртый набор данных содержал 300 изображений. Теперь я был уверен, что модель, наконец, заработает. Но неожиданно возникла ещё одна серьёзная проблема.

Проблема совместимости библиотек

В большинстве проектов по программированию, особенно проектов в области анализа и обработки данных, для работы определённых функций и инструментов требуется ряд библиотек и зависимостей. В этом конкретном проекте библиотека ImageAI потребовала установки определённых версий различных библиотек, в том числе tensorflow-gpu 1.13 и keras 2.4.

Разные версии библиотеки отличаются одна от другой, причём использование разных версий может повлиять на взаимодействие между библиотеками. В моём случае это было особенно актуально, так как обучение и работа модели были возможны только при использовании определённых версий библиотек.

В январе вышло обновление библиотеки ImageAI, и оно сразу поставило крест на работе других библиотек, которые я использовал в проекте, оно было просто несовместимо с ними. И вот, время обучения, обычно составлявшее около 5 минут на эпоху, стало составлять более 14 часов. Кроме того, модель постоянно перестраивалась под данные, а это свидетельствовало о том, что она была неспособна генерализовывать новые данные.

Сначала я подумал, что такое длительное время обучения обусловлено большим количеством изображений в наборе данных, но скоро стало очевидно, что проблема кроется не в этом и она более серьёзная. Я ещё раз обратился к учебникам, но ничего путного найти не смог. Если бы вы знали, сколько различных вариантов я перепробовал, чтобы устранить проблему!.. Я пробовал менять способы извлечения набора данных, менять аппаратный ускоритель, менять размер пакета... Ни один из этих вариантов не снизил время обучения модели.

Но тут я наткнулся на недавно опубликованный пост в разделе проблем и вопросов на Github, в котором кто-то жаловался на такую же точно проблему, как и у меня. Олафенва Мозес, создатель библиотеки, ответил на это пост и объяснил проблему, предложив собственное решение. Суть этого решения была такой: три основные библиотеки Tensorflow, Keras и ImageAI должны иметь чётко определённые версии.

Окончательный набор данных / Модель

После избавления от предыдущей проблемы я сначала протестировал набор данных из 300 изображений. Результаты улучшились, но ненамного, им не хватало стабильности. На некоторых изображениях газона с разных углов моя модель вообще не смогла обнаружить проплешин.

Набор данных 4. Результаты.Набор данных 4. Результаты.

Я решил добавить ещё больше данных и в итоге получил набор из 1738 изображений. Чтобы обучить модель, мне пришлось аннотировать каждое изображение, вручную очерчивая участки на каждом из них. К счастью, этой работой я занимался не один, а с друзьями. Менее чем за два часа нам удалось аннотировать все изображения.

Окончательный набор данных был разделён на 1400 тренировочных и 338 тестовых изображений. После обучения модели за 5 эпох я провел валидацию и получил впечатляющий результат 0,7204, что, безусловно, стало моим лучшим результатом с начала проекта.

Набор данных 5. Результаты.Набор данных 5. Результаты.

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

Создание спринклера

Схема системы.Схема системы.

Чтобы контролировать полив, мне нужно было обеспечить вращение спринклера по двум осям так я мог бы контролировать расстояние и направление разбрызгивания воды. Я использовал два шаговых двигателя NEMA с разными характеристиками мощности и крутящего момента. Нижний двигатель NEMA-23 использовался для управления направлением разбрызгивания воды. Верхний двигатель NEMA 14 вращал стержень с закреплённым на нём с помощью трубки из ПВХ спринклером, чтобы можно было управлять расстоянием, на которое разбрызгивается вода. Для управления этими двигателями я использовал Arduino, два регулятора частоты вращения двигателя A4988 и два адаптера питания 12 В.

Если бы я мог выяснить, на какое расстояние разбрызгивается вода и на какой угол поворачивается спринклер за определённое количество шагов, я мог бы рассчитать коэффициенты преобразования шагов в углы и шагов в расстояние. Для того чтобы можно было использовать такие коэффициенты преобразования, мне потребовался скрипт, определяющий фактическое расстояние до проплешины и угол, на который надо повернуть спринклер для полива.

Я рассчитал угол, на который необходимо повернуть спринклер от начального места до центра проплешины, определил приблизительное количество пикселей/футов на моём изображении и после этого вычислил приблизительное расстояние до центра проплешины.

Результат работы скрипта управления двигателем.Результат работы скрипта управления двигателем.

На рисунке выше показаны результаты работы скрипта управления двигателем. Их них следует, что спринклер должен повернуться на 42, а расстояние до проплешины составляет примерно 3 м 89 см.

Согласно скрипту угол до проплешины составляет 42.Согласно скрипту угол до проплешины составляет 42.

Длина рулетки 3 м (10 футов); от центра проплешины до спринклера примерно 12 футов 9 дюймов (3,8862 м), как и предсказал скрипт.

Я выполнил несколько тестов для определения коэффициентов преобразования шагов в углы и шагов в футы, и это позволило мне создать скрипт Arduino для ориентирования спринклера на проплешину с использованием данных скрипта управления двигателем.

Готовность к окончательному тестированию

К сожалению, всю систему в итоге мне протестировать не удалось.

Перед окончательным тестом я стал проверять готовую конструкцию, чтобы убедиться, что она способна держать спринклер и поворачивать его. Но я был очень неосторожен: в моторы попала вода, и они сгорели. Двигатели были довольно дорогими, а покупать новые было непрактично.

Анализ кода / Краткий обзор

Google Colab PatchDetector

PatchDetector на Github

!wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutLawn.jpg!wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutLawn_Detected.jpg!wget https://github.com/fazalmittu/PatchDetection/releases/download/v3.0/detection_model-ex-04--loss-25.86.h5!wget https://github.com/fazalmittu/PatchDetection/releases/download/v3.0/detection_config1700_v1.json!wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutFullLawn.jpg!wget https://github.com/fazalmittu/PatchDetection/raw/master/BlackedOutFullLawn_Detected.jpg!wget https://github.com/fazalmittu/PatchDetection/raw/master/SprinklerPOV.jpg!wget https://github.com/fazalmittu/PatchDetection/raw/master/SprinklerPOV_Detected.jpg!wget https://github.com/OlafenwaMoses/ImageAI/releases/download/essential-v4/pretrained-yolov3.h5

Этот код используется для импорта модели и изображений (для тестирования), которые я хранил на Github, чтобы их можно было легко извлечь с помощью Google Colab. Последняя строка импортирование предварительно обученной модели YOLO-v3, которая, в свою очередь, использовалась для обучения модели (трансферное обучение).

!pip uninstall -y tensorflow!pip install tensorflow-gpu==1.13.1!pip install keras==2.2.4!pip install imageai==2.1.0!pip install numpy

Этот код импортирует определённые версии библиотек, необходимых при проектировании. Используемые библиотеки: tensorflow-gpu, keras, imageai и numpy.

%load_ext autoreload%autoreload 2  from google.colab import driveimport sysfrom pathlib import Pathdrive.mount("/content/drive", force_remount=True)base = Path('/content/drive/MyDrive/PatchDetectorProject/')sys.path.append(str(base))zip_path = base/'AugmentedDataSetFinal.zip'!cp "{zip_path}" .!unzip -q AugmentedDataSetFinal.zip!rm AugmentedDataSetFinal.zip

Этот код используется для получения набора данных из места, которое я определил для него на Google-диске. Для сохранения на Github набор данных был слишком велик, поэтому мне пришлось использовать альтернативный источник.

from imageai.Detection.Custom import DetectionModelTrainerfrom __future__ import print_functiontrainer = DetectionModelTrainer()trainer.setModelTypeAsYOLOv3()trainer.setDataDirectory(data_directory="AugmentedDataSetFinal")trainer.setTrainConfig(object_names_array=["patch"], batch_size=4, num_experiments=5, train_from_pretrained_model="pretrained-yolov3.h5")trainer.trainModel()

В этом коде осуществляется обучение модели. В нём указывается объект для поиска ("patch" (проплешина)), количество эпох (5), размер пакета (4) и используется трансферное обучение.

from imageai.Detection.Custom import DetectionModelTrainertrainer = DetectionModelTrainer()trainer.setModelTypeAsYOLOv3()trainer.setDataDirectory(data_directory="AugmentedDataSetFinal")trainer.evaluateModel(model_path="AugmentedDataSetFinal/models", json_path="AugmentedDataSetFinal/json/detection_config.json", iou_threshold=0.5, object_threshold=0.3, nms_threshold=0.5)

Этот код используется для валидации модели. С окончательной моделью я получил оценку 72,04 %. Я считаю этот результат очень хорошим, учитывая, что обнаруживаемые мною объекты представляют собой проплешины без определённой формы, цвета или размера.

from imageai.Detection.Custom import CustomObjectDetectionfrom PIL import Image, ImageDrawimport numpy as npdetector = CustomObjectDetection()detector.setModelTypeAsYOLOv3()detector.setModelPath("/content/detection_model-ex-04--loss-25.86.h5")detector.setJsonPath("/content/detection_config1700_v1.json")detector.loadModel()detections = detector.detectObjectsFromImage(input_image="SprinklerPOV.jpg", output_image_path="SprinklerPOV_Detected.jpg", minimum_percentage_probability=30) i = 0coord_array = []for detection in detections:    coord_array.append(detection["box_points"])    print(detection["name"], " : ", detection["percentage_probability"], " : ", detection["box_points"])    i+=1print(coord_array)detected = Image.open("SprinklerPOV_Detected.jpg")box = ImageDraw.Draw(detected)for i in range(len(coord_array)):  box.rectangle(coord_array[i], width=10)detected

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

!wget https://github.com/fazalmittu/PatchDetection/raw/master/FeetToPixel.JPGimg_ft = Image.open("FeetToPixel.JPG")ft_line = ImageDraw.Draw(img_ft)ft_line.line([(175, 1351), (362, 1360)], fill=(0, 255, 0), width=10)ft_distance = np.sqrt(9*9 + 187*187)print(ft_distance)img_ft

С этого кода начинается скрипт управления двигателем. Код импортирует изображение, на нём разложенная на траве рулетка. Я использовал это изображение для определения примерного количества пикселей в футе.

Пиксели/футы.Пиксели/футы.
from PIL import Image, ImageDraw#TOP LEFT = [0, 1]#BOTTOM LEFT = [0, 3]#TOP RIGHT = [2, 1]#BOTTOM RIGHT = [2, 3]img = Image.open("SprinklerPOV_Detected.jpg")middle_line = ImageDraw.Draw(img)avg_1Line = ImageDraw.Draw(img)avg_2Line = ImageDraw.Draw(img)avg_1 = (coord_array[1][1] + coord_array[1][3])/2avg_2 = (coord_array[1][0] + coord_array[1][2])/2middle_line.line([(2180, 0), (2180, 3024)], fill=(0, 255, 0), width=10)# avg_1Line.line([(coord_array[1][0], coord_array[1][1]), (coord_array[1][0], coord_array[1][3])], fill=(255, 0, 0), width=10)# avg_2Line.line([(coord_array[1][0], coord_array[1][3]), (coord_array[1][2], coord_array[1][3])], fill=(255, 0, 0), width=10)def find_angle():  line_to_patch = ImageDraw.Draw(img)  line_to_patch.line([(avg_2, avg_1), (2180, 3024)], fill=(255, 0, 0), width=10)  length_1_vertical = 3024 - avg_1  length_2_horizontal = 2500 - avg_2  print("Distance = ", np.sqrt(length_1_vertical*length_1_vertical + length_2_horizontal*length_2_horizontal)/ft_distance, "ft")  angle_radians = np.arctan(length_2_horizontal/length_1_vertical)  angle = (180/(np.pi/angle_radians)) #Convert radians to degrees  return angleprint(avg_1, avg_2)print(find_angle())img

Этот код используется для определения угла до проплешины. Я нарисовал треугольник от центра проплешины до места, где вначале находился спринклер. Для определения угла до центра проплешины я воспользовался тригонометрическими формулами и координатами каждой из точек. Для определения расстояния до центра проплешины в футах я также использовал тригонометрические функции и коэффициент пересчёта пикселей в футы.

/* *  * Fazal Mittu; Sprinkler Control *  */const int ROTATEstepPin = 3; const int ROTATEdirPin = 4; const int ANGLEstepPin = 6;const int ANGLEdirPin = 7;const int ROTATEangle = 42.25191181;//TODO: Find Conversion: Steps --> Angle 1000 steps = 90 degreesconst int ANGLEangle = 12.76187539;// pixels --> ft: 187 pixels = 1 feetbool TURN = true;float angleToSteps(float angle){  float steps = 1000/(90/angle);  return steps;}float ftToSteps(float feet) {  float steps = 100/(8/feet);  return steps;}void setup() {  Serial.begin(9600);  pinMode(ROTATEstepPin,OUTPUT);   pinMode(ROTATEdirPin,OUTPUT);  pinMode(ANGLEstepPin,OUTPUT);   pinMode(ANGLEdirPin,OUTPUT);}void loop() {  int ROTATEsteps = angleToSteps(ROTATEangle); //Angle was determined using Python Script  int ANGLEsteps = angleToSteps(ANGLEangle);  delay(7000);  if (TURN == true) {    for(int x = 0; x < ROTATEsteps; x++) {      digitalWrite(ROTATEstepPin,HIGH);       delayMicroseconds(500);       digitalWrite(ROTATEstepPin,LOW);       delayMicroseconds(500);     }    delay(5000);    for (int x = 0; x < 100; x++) { //100 steps = 8 ft, 0 steps = 14.5 ft      digitalWrite(ANGLEstepPin,HIGH);       delayMicroseconds(500);       digitalWrite(ANGLEstepPin,LOW);       delayMicroseconds(500);    }  }  TURN = false;}

Приведённый выше код использовался для управления обоими двигателями. Перед использованием любого кода сначала нужно определить взаимозависимости шаги/градусы и шаги/футы, что я и сделал посредством проведения тестов и измерений. В итоге у меня появился рабочий скрипт, который мог управлять работой двигателей в соответствии со значениями, полученными в результате работы скрипта управления.

Заключение

Даже несмотря на печальную судьбу двух двигателей, работа над этим проектом доставила мне истинное удовольствие. Я узнал, как собирать данные, как увеличивать количество изображений, как строить модели. Я понял, как интерпретировать результаты, как создавать систему управления, как подключать механические части, а также научился разгребать подводные камни на пути к успеху.

А если вы хотите научиться работать с данными и обрабатывать их помощью машинного обучения обратите внимание на наш курс по ML или на его расширенную версию Machine Learning и Deep Learning, партнером которого является компания Nvidia.

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Перетягивание диода или устраиваем соревнование между CANNY 3 TINY PRO и Arduino

08.06.2021 02:17:27 | Автор: admin
Arduino vs CANNY перетягивание диодаArduino vs CANNY перетягивание диода

В предыдущей статье, посвящённой моим попыткам погрузится в увлекательный мир программирования микроконтроллеров, я грозился сделать обзор на "обновку". К сожалению, мне сейчас не хватает навыков и времени чтобы сделать, что-то достойное полноценного обзора. Однако, я всё-таки решил подготовить забавы ради, короткую статью на тему игрушечного соревнования CANNY 3 TINY PRO и неоригинальной Arduino Nano. Соревноваться контроллеры будут в своеобразном аналоге перетягивания каната, на роль которого был выбран двухцветный светодиод марки BL-L2519EGW.

Итак в сегодняшнем материале мы подключим оба контроллера к светодиоду и будем подавать случайный сигнал на его выводы. Правила простые кто большее напряжение подаст у того и кристалл в светодиоде загорится ярче. Попутно мы воспользуемся ЦАП на контроллере CANNY и доработаем стандартный ГСЧ с помощью составного функционального блока.

В статье не будет сложной электроники или мудрёного программирования, так что она вполне подойдет новичкам.

Оглавление:

  1. Введение

  2. Схема

  3. Программа

  4. Заключение

Введение

Я намерено не буду разбирать технические характеристики нового (для меня) контроллера CANNY. Скажу только одну вещь. Несмотря на то, что они оба контроллера внешне чем-то похожи сравнивать их совершенно не уместно и мы этого делать не будем.

Для того, чтобы повторить "дуэль века" вам потребуется:

  1. Двухцветный светодиод - я использовал BL-L2519EGW, но марка не особо критична.

  2. Контроллер CANNY 3 TINY PRO именно у этого контроллера есть ЦАП, к тому же он самый доступный по цене в линейке контроллеров CANNY.

  3. Совместимый с Arduino контроллер - я использовал неоригинальную Nano, но можно было и UNO.

  4. Пара резисторов 100 Ом, - я не силен в электронике, но решил подстраховаться и использовать их как ограничители тока (может это и неверное решение). В любом случае думаю, что у контроллеров есть свои встроенные ограничители тока и схема может работать и без резисторов.

  5. Соединительные провода и макетная плата.

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

Предвосхищая некоторую критику, сразу скажу, что само собой раз контролеры Кэнни стоят в "Дакаровских" Камазах, наверное и CANNY 3 TINY PRO явно предназначен для чего-то большего, чем просто моргать светодиодом. Собственно Arduino Nano тоже может намного больше. Просто я ничего сложнее в этот раз собрать не смог, а поделится впечатлением хотелось.

Ну и на всякий случай остальные статьи цикла размещу под спойлером.

Другие статьи цикла

Схема

Схема соединенийСхема соединений

Питать контроллеры мы будем через USB-порты, поскольку оба контроллера имеют USB-VCP мы при необходимости сможем еще и передавать данные. Но в принципе контроллеры можно питать и от двух USB зарядных устройств, схема всё равно будет работать.

Первым делом объединим "Землю" у двух контроллеров соединив выводы "GND".

Затем, от каждого из контроллеров "подведем" к светодиоду выводы от канала ЦАП.
У Arduino - "D5", у CANNY - "C2" (это единственный выход с ЦАП).
В нашем случае светодиод имеет два вывода и работает он примерно так: если на левой ноге напряжение больше, чем на правой то загорается красный кристалл. Чем больше разница потенциалов, тем ярче он загорится. И наоборот, если на правой ноге напряжение больше, чем на левой, то загорится зеленый. При примерном равенстве потенциалов светодиод вообще не будет светится.

Мы будем "перетягивать канат" 2.5 секунды, нам важно, чтобы контроллеры подали сигнал более-менее синхронно. Для этого (а также для нашей тренировки) контроллеры подадут друг другу сигналы. Выход "D7" Arduino подаст логическую единицу на вход "C6" CANNY. В свою очередь, CANNY с выхода "C4" подаст логическую единицу на вход "D3" Arduino. В программе каждого из контроллеров предусмотрим проверку наличия сигнала, при успешном прохождении которой подается напряжение на светодиод.

Для того, чтобы узнать какое напряжение подали оба контроллера, мы с помощью АЦП CANNY померим напряжение поданное Arduino. Для этого подсоединим выход "C10" CANNY к резистору.

Кстати лично я очень рад что у Canny 3 TINY PRO для того, чтобы включить режим АЦП канала не нужно паять перемычку, как в случае с обычным CANNY 3 TINY.

В итоге должно получится примерно вот-так:

Фото схемыФото схемы

Я правда использовал специальные резисторы из набора, но в остальном схема как на картинке.

Ещё важно напомнить, что у кристаллов внутри светодиода немного разные электрические параметры, поэтому возможно, что будут светится одновременно оба кристалла, также возможны другие непредвиденные мелочи, которыми мы можем пренебречь.

Перейдем к программной части.

Программа

Обе программы можно скачать с GitHub.

Программа для Arduino очень простая, думаю нет смысле её комментировать:

/*Synhronized Randomize DAC.See more http://personeltest.ru/aways/habr.com/ru/post/561148/*/int ADC_pin = 5;int input_pin = 3;int output_pin = 7;int synch_signa = 0;int v_min = 10;int v_max = 2550;int synch_signal = 0;float rand_voltage = 0;// the setup function runs once when you press reset or power the boardvoid setup() {  pinMode(ADC_pin, OUTPUT);  pinMode(output_pin, OUTPUT);  digitalWrite(output_pin,HIGH);  pinMode(input_pin, INPUT);  Serial.begin(9600);}// the loop function runs over and over again forevervoid loop() {synch_signal = digitalRead(input_pin);      // read signal from another deviceif (synch_signal) { rand_voltage=random(v_min, v_max) / 10; analogWrite(ADC_pin, rand_voltage); Serial.println(rand_voltage);  delay(2500);   // wait for seconds}else{ delay(500);   // wait for seconds}                }

Программа для контроллера CANNY:

Функциональная диаграммаФункциональная диаграмма
  • При включении контроллер устанавливает на выходе "С4" логическую "1" для синхронизации с Arduino.

  • Канал "C10" в режиме АЦП измеряет напряжение от Arduinio и с помощью функции MAP переводит его в удобный для чтения вид.

  • ШИМ-генератор в сочетании с детектором переднего фронта раз в 2.5 секунды дают сигнал для записи случайного значения в канал "C2".

    • Значение при этом запишется, только если на входе "С6" есть логическая "1" от Arduino.

    • Значение напряжения для подачи на светодиод генерируется случайным образом. Поскольку у CANNY нет встроенного блока для сброса ГСЦ, "случайность" сигнала обеспечивается, сложением "истории" сигналов, поступивших от Arduino.

    • Для уменьшения количества элементов на основной диаграмме, реализация функции "Random" перенесена в одноименный составной блок (об этом чуть позже).

  • Значения напряжений на выводах светодиода от обоих контроллеров передается в виртуальный COM-порт ПК. Данный порт мы можем мониторить в любой программе, например в Hterm, но я для простоты решил использовать Arduino IDE.

    • Чтобы не "заморачиваться" с лишними символами, напряжение контроллеров выводится без точки, например, "c=45" значит, что напряжение на выводе ЦАП CANNY = 4.5В, соответственно "a=27" значит, что на ЦАП выводе Arduino = 2.7В.

Рассмотрим составной блок "Random (min...max)":

Составной блокСоставной блок

В данном блоге мы используем встроенный ГСЧ и функцию MAP для того чтобы выводить не просто числа от 0 до 65000, а в нужном нам диапазоне. Данный блок можно использовать, как библиотечный элемент и повторно использовать в других схемах. Более подробно о том, как работать с составными функциональными блоками, я писал в этой статье.

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

Заключение

Если вы все собрали верно, то получится примерно такой результат:

Различные варианты поданного на СИД напряженияРазличные варианты поданного на СИД напряжения

Слева направо:

  1. У контроллеров ничья, напряжение примерно равно.

  2. CANNY немножко выигрывает.

  3. CANNY ощутимо выигрывает.

  4. Arduino ощутимо выигрывает.

Пример вывода данных из монитора COM-порта (несвязанный с картинкой выше):

Монитор COM-портаМонитор COM-порта

Если честно изначально, я хотел сделать крестики-нолики на светодиодах, но потом понял, что для меня это тяжело, но, если кто-то вдруг сделает поделитесь пожалуйста ссылкой в комментариях.

Ну и еще под конец хочу сказать, что чертовски любопытно иногда погрузится в другую парадигму программирования. Я получил удовольствие, когда своими руками из функциональных блоков собрал простенький аналог функции "Random". Сейчас подумываю сделать еще несколько "библиотечных" элементов реализующих распространенные функции, которых порой не хватает среди готовых блоков CANNY и набросать об этом статью.

На этом всё. Надеюсь, что статья была для вас если уж не особо полезна, то хотя бы просто любопытна.

Подробнее..

DIY регистратор молний

15.06.2021 20:16:32 | Автор: admin

Автор: Alex Wulff (из-за глюков хабраредактора не получилось оформить как перевод)

К старту курса о разработке на С++ мы перевели статью о персональном регистраторе молний небольшом устройстве, сообщающем об ударах молнии поблизости. Оно даже сообщает, на каком расстоянии ударила молния; при этом, по словам автора, собрать его самому обойдётся дешевле, чем купить в магазине. Ещё один очевидный плюс вы сможете отточить свои умения в схемотехнике.

В основу устройства положен детектор молний AS3935 с ВЧ-каналом производства DFRobot. Детектор обнаруживает электромагнитное излучение молнии и с помощью специального алгоритма преобразовывает эту информацию в информацию о расстоянии до удара.


Датчик может обнаруживать удары молнии на расстоянии до 40 км (25 миль) и определять расстояние до места удара молнии с точностью до 4 км (2,5 мили). Сам датчик довольно надёжен, но может срабатывать неверно, если устройство находится на открытом воздухе. Самодельное устройство может работать не так надёжно, как коммерческий регистратор молний.

Материалы
  • микроконтроллер-жучок (beetle) DFRobot #DFR0282. Это плата Arduino Leonardo очень малых размеров;

  • Gravity: датчик расстояния до молнии DFRobot #SEN0290;

  • зарядное устройство для литиевых аккумуляторов DFRobot #SEN0290;

  • аккумулятор LiPo, 500 мАч Amazon #B00P2XICJG;

  • пьезодинамик 5В, например Amazon #B07GJSP68S;

  • маленький скользящий переключатель;

  • монтажный провод (одно- или многожильный).

Инструменты
  • компьютер с бесплатным ПО Arduino IDE.

  • паяльник и припой;

  • пистолет для горячего клея;

  • машинка для зачистки концов провода от изоляции;

  • 3D-принтер (не обязательно).

1. Разработка схемы соединений

Схема устройства проста. Информация с датчика молнии передаётся по линиям SCL и SDA, плюс к этому одно соединение предусмотрено для звукового сигнала. Устройство питается от литий-ионного полимерного аккумулятора (LiPo), поэтому я решил встроить в схему зарядное устройство для такой батареи.

Рисунок AРисунок A

Схема устройства показана на рисунке A. Обратите внимание, что аккумуляторная батарея LiPo соединяется с зарядным устройством через штекерно-гнездовые разъёмы JST и не требует пайки.

2. Сборка схемы

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

Подсоедините жучок к зарядному устройству

Отпаяйте зелёные клеммы от зарядного устройства LiPo. Они бесполезны, но занимают пространство. Соедините положительную (+) и отрицательную (-) клеммы зарядного устройства аккумуляторной батареи LiPo с положительной (+) и отрицательной () клеммами на лицевой части жучка. По этим проводам первичное напряжение батареи LiPo будет подаваться непосредственно на микроконтроллер. Технически жучку требуется 5В, но от напряжения 4В батареи LiPo он всё равно будет работать.

Подключение датчика молнии

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

  • положительную (+) клемму на датчике молнии соедините с положительной (+) клеммой на жучке;

  • отрицательную () клемму на датчике молнии соедините с отрицательной (-) клеммой на жучке;

  • контакт синхронизации (C) на датчике молнии соедините с колодкой SCL на жучке;

  • контакт данных (D) на датчике молнии соедините с колодкой SDA на жучке.

Контакт IRQ на датчике молнии также должен быть соединён с колодкой RX на жучке. Соединение должно подходить к аппаратному прерывателю на жучке; колодка RX (контакт 0) единственный оставшийся контакт, поддерживающий прерывание.

Подключение зуммера

Подключите короткий провод зуммера к отрицательной () клемме на жучке (земля), а длинный провод к контакту 11. Сигнальный вывод зуммера должен быть подключён к выводу PWM (для обеспечения максимальной гибкости), здесь идеально подходит контакт 11.

Подсоединение переключателя

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

Рисунок БРисунок Б

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

Окончательная компоновка

Рисунок ВРисунок В

Последний шаг избавляемся от беспорядочного скопления проводов и компонентов и приводим устройство в более презентабельный вид (рис. В). Это нужно делать аккуратно, чтобы не переломить провода. Приклейте горячим клеем зарядное устройство LiPo к верхней части батареи LiPo, затем сверху приклейте жучок. И последнее действие: приклейте к самому верху датчик молнии. Зуммер я вывел на сторону, как показано на рисунке В. В результате получилось несколько скреплённых между собой плат с торчащими из них проводами. Выводы переключателя я также оставил свободными, чтобы позже вставить их в корпус, распечатанный на 3D-принтере.

3. Программирование микроконтроллера

Запустите на компьютере Arduino IDE и убедитесь, что в меню ToolsBoard (ИнструментыПлата) выбрано значение Leonardo. Загрузите и установите библиотеку для датчика молнии. Затем скачайте код проекта и загрузите его на жучок. Программа предельно проста и очень легко настраивается.

Обнаружив молнию, устройство сначала подаст несколько звуковых сигналов, чтобы предупредить об ударе молнии поблизости, а затем подаст определённое количество звуковых сигналов, соответствующее расстоянию до молнии в километрах. Если молния находится на расстоянии менее 10 км (6,2 мили), детектор подаст один длинный звуковой сигнал. Если расстояние превышает 10 км (6,2 мили), расстояние будет поделено на 10, округлено, и устройство подаст соответствующее полученному числу количество сигналов. Например, если молния ударит на расстоянии 26 км (16 миль), то сигнала будет три.

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

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

4. Распечатка корпуса на 3D-принтере (не обязательно)

Рисунок ГРисунок ГРисунок ДРисунок ДРисунок ЕРисунок Е

Корпус для устройства разработал я сам. Файлы для 3D-печати можно загрузить здесь. (рис. Г, Д). Верхняя часть корпуса прищёлкивается к нижней, никакого специального оборудования не требуется. Корпус достаточно просторный, чтобы в нём могло поместиться и ваше устройство, если вы будете собирать его по-другому (рис. Д). В любом случае вам ничего не мешает спроектировать аналогичный корпус самому:

  • определите габариты устройства;

  • спроектируйте устройство в программе CAD (мне нравится Fusion 360 студенты могут получить её бесплатно);

  • создайте корпус, перетащив профиль из модели устройства. Допуска в 2 мм будет вполне достаточно.

Обнаружение ударов молнии

Поздравляем, теперь у вас есть работающий регистратор молний! Как проверить, работает ли устройство? Ответ очевиден дождитесь грозы. Не знаю, насколько надёжен датчик, но мой сработал с первого раза.

Заряжать устройство очень просто достаточно подключить microUSB-кабель к зарядному устройству LiPo и дождаться, когда индикатор зарядки загорится зелёным цветом. Во время зарядки устройство должно быть включено, иначе энергия не будет поступать в аккумулятор!

Внесение изменений

Регистратор молнии можно сделать более полезным и удобным в использовании, если внести в программное обеспечение определённые изменения:

  • другие звуковые сигналы: чтобы устройство звучало приятнее, используйте библиотеку звуков Tone.h;

  • спящий режим: микроконтроллер ATmega32u4 (чип, на основе которого работает жучок) поддерживает аппаратные прерывания в спящем режиме. Устройство можно перевести в спящий режим, и любое поступившее от датчика молнии, событие заставит датчик реагировать. Спящий режим может значительно продлить срок службы батареи.

Этот материал показывает, что умение разрабатывать программы на С++, работа с электроникой, даёт широкие возможности и может быть полезна в самых разных сферах: представьте, например, что вы часто бываете на природе тогда о грозе лучше знать заранее и даже за километры, но не нужно дорогого оборудования. Если вам нравится чувствовать, как вы управляете железом, идущим по микросхемам током, то вы можете присмотреться к нашему курсу о разработке на С++, где студенты готовятся к началу карьеры разработчика ПО на этом сложном и мощном языке.

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Recovery mode Светодиодный куб

09.04.2021 10:09:31 | Автор: admin

Электронное устройство, которое применяется в декоративных инсталляциях. Светодиодные кубы бываю размерами 3x3x3, 4x4x4, 5x5x5 и т.д. Изменяя скорость загорания и затухания светодиодов в кубе, мы создаём различные визуальные эффекты: бегущие огни, эквалайзер, 3d световая инсталляция.

Материал:

- плата для пайки или беспаечная плата

Инструменты:

- инструмент для снятия изоляции

- линейка или штангельциркуль

- паяльная станция

Электрокомпоненты

- arduino

- 64 светодиода

- соединительные провода

Рассмотрим схему данного куба

На рис. Представлена одна из сторон куба. Все четыре стороны соединяются по выводам плюсовой ножки светодиода в каждом ряду. В результате для всех ножек с полюсом + ,будет четыре вывода. В результате с помощью этих выводом можно управлять рядами светодиодов. Ножки с полюсом - соединяются между собой по вертикальным рядам куба. В результате мы получим 16 выводов, которые можно запитать на GND arduino.

Сборка модели.

Соберём конструкцию с использованием паяльной станции и платы для монтажа. Можно воспользоваться как платой для пайки, так и без пайки. Плату для пайки, рекомендую использовать только, если вы уверены в правильности сборки

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

Для начала, соберём вертикальный ряд из четырёх светодиод. У короткой ножки светодиода (знак - ) подогнём конец с помощью плоскогубец. Длинную ножку светодиода сдвинем перпендикулярно короткой.

Используя держатель Третья рука, спаяем данные светодиоды

Как видно из рисунка, короткие ножки мы спаяли, а длинные ножки остались свободными. Так необходимо проделать ещё четыре раза. В итоге, мы получим четыре ряда светодиодов

Приступим к процессу их соединения. Соединяться они должны с помощью длинных ножек (знак + ). Соединение получается с помощью перекрестия. Постарайтесь уместить на одной длинной ножке светодиода четыре другие длинные ножки светодиодов

Так необходимо проделать для трёх сторон. С каждой стороны должно быть не больше четырёх вертикальных рядов.

Перед тем как поставить четвёртую стену куба, необходимо припаять четыре провода к плюсовым выводам светодиодов каждого ряда.

После этого, припаяем четвёртую сторону куба.

Для того чтобы куб был устойчив нужно закрепить его ножки минуса на монтажной плате, как предназначенный для пайки, так без пайки. В данном случае для надёжности конструкции я применил плату для пайки.

Минусы подключим к GND, а плюсы к пинам 8, 9, 10, 11 arduino. И напишем простую программу.которая поочередно посылает сигналы на ряды данного куба.

Процесс управления, а точнее, усложнения управления, можно воспользоваться сдвиговым регистром 74HС595. Данная микросхема способна управлять восемью светодиодами, т.е. может посылать сигналы на восемь выводов и при этом сама занимает три вывода на arduino. Если все шестнадцать выводов GND светодиодов подключить к двум регистрам, совместно с питанием плюсовых выводом, то можно регулировать свечение конкретного светодиода в кубе.

Для начала рассмотрим управление восьмью светодиодами через регистр.

Пример программы по управлению светодиодами. Подключим 16 минусовых выводов на два регистра.
Четыре плюсовых вывода куба подключим к пинам 2,3, 4 и 5

Загрузим на плату программу, которая вызовет эффект бегущих огней в кубе.

Как видно из рисунка, присутствует третий сдвиговый регистр, он может предназначаться для подачи сигналов на плюсовые контакты. В данной инструкции это было не сделано и все плюсовые контакты выведены напрямую на пины arduino.

Пример работы

Подробнее..

Recovery mode Проект электронного мультитула QUARK

19.04.2021 06:22:01 | Автор: admin

Еще в 2018 наткнулся на довольно известный в своих кругах проект Пультоскоп. Если кратко, то это крайне примитивный осциллограф, построенный на arduino 328 серии. Учитывая его простоту, я его повторил за несколько часов на макетке и тут меня понесло... Но обо всем по порядку.

Итак. Повторенное устройство оказалось настолько нужным и удобным, что сама-собой возникла идея дополнить его базовыми функциями мультиметра, в том числе измеритель емкости конденсаторов и индуктивности катушек. В результате я начал работу над созданием идеального "под себя" устройства. Эмпирически прикинув функционал, который так или иначе задействую при проектировании своих устройств, я исключил ненужные мне функции и определил обязательные. В первую очередь, исходил из того, что в большинстве своем я не использую напряжения свыше 24 вольт и токи свыше 3 ампер. Обычно это низковольтное оборудование, IoT, ESP32, arduino и схожие по идеологии устройства. Соответственно и при измерении сопротивлений, емкостей и индуктивностей важна не столько точность, сколько понимание номинала и, желательно, автоматическое определение цветовой и кодовой маркировки. Обычно измерение этих параметров требуется при проектировании питающих схем устройств. Обязательна хотя бы минимальная проверка наличия данных на порту UART, а в идеале и их чтение. Здесь же я стал размышлять над формфактором устройства.

Собственно список того, к чему я пришел в итоге:

  • Вольтметр с точностью измерения не выше 0.01 вольта. Обычно достаточно даже десятых долей. При этом, обязательно необходимо отображение значений логических уровней для CMOS1.8, TTL и CMOS5.0 вольт.

  • Амперметр до 3 ампер с возможностью отображать график изменения значений.

  • Измерение номиналов пассивных элементов. Одна из наиболее необходимых для меня вещей, оказалась возможность на лету отображать цветовую и SMD маркировку деталей. То же самое при измерении индуктивности и емкости, за исключением цветовой маркировки. Разумеется автовыбор диапазонов.

  • Осциллограф обязателен. Как правило используется для измерения ШИМ сигналов, при проектировании питающих частей схем и при работе с данными для АЦП/ЦАП. Частоты как правило не выше 100кГц. Желательно что бы устройство само определяло триггер и настраивало масштаб графика.

  • UART логгер с автоопределением скорости.

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

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

Звучит слишком идеально, но это хотя бы обозначенная цель.

ПРОЕКТИРОВАНИЕ

После того как с функциями устройства стало более-менее понятно, я сосредоточился на его внешнем виде. Буквально брал в руки модельный пластилин и лепил то, что должно удобно лежать в руке, отображать информацию и при этом легко управляться. В результате я пришел к такому дизайну:

Это рендер. Первая игла щупа торчит из кончика корпуса, второй щуп втыкается в "попку" - любой подходящий с бананом.

Что касается железной части, то здесь пришлось сильно поломать голову. Первые версии были построены на ATMEGA32U4. Его выбрал из-за в встроенного USB и достаточной скорости. Но самым главным критерием была arduino совместимость. Я принципиально хотел использовать платформу arduino, поскольку сразу зародилась мысль выложить ПО в открытый доступ и при этом оно должно было быть понятным ардуинщику. В качестве датчика тока решил использовать ACS712. Остальное на резистивных делителях, там ничего интересного.

Одна из последних тестовых версий плат, собранных на коленке:

В правом нижнем углу видна микрорелешка, которая замыкает щупы между собой через датчик тока.

А это уже первый заводской прототип:

Виден не распаянный в верхней части блютуз модуль JDY-08. Использовал его потому, что был. В качестве встроенного зонда, использовал иглы для тестирования плат методом летающего щупа. Сам зонд выглядит так:

Игла немного подпружинена и не дает поцарапать медь или лак на плате.

Косяков было не так много, все довольно легко смог исправить кинув "сполю", но пришлось отложить проектирование из-за нехватки времени. Собственно это позитивно сказалось на проекте, поскольку удалось много поработать с ESP32, на него я и перевел устройство. Попутно заменил старый, 0,96 дюймовый дисплей с разрешением 80x160, на 1,14 дюймовую матрицу 135*240 пикселей.

Должен сказать, что я не сторонник сенсорных кнопок, и в первой версии устройства у меня были физически нажимаемые 3 кнопки, но пришлось себе изменить. Шутки ради собрал прототип с 3-х контактным сенсорным интерфейсом и воткнул его в отпечатанный на 3D принтере корпус. Оказалось, что проще и быстрее не искать пальцем нужную кнопку, а банальными свайпами переходить в нужный режим. Сразу возник соблазн использовать встроенные в ESP32 пины емкостного сенсора, однако их чувствительности оказалось недостаточно для работы в корпусе. Потому пришлось перейти на использование букашек от ttp223. Из-за катастрофической нехватки пинов, три сенсора я подключил через резистивный делитель на один аналоговый вход. Еще один пришлось вешать на отдельный пин для реализации выхода из сна по прерыванию. С аналоговым входом, на котором висят 3 сенсора возникла неожиданная проблема. Оказалось, что при включении режима bluetooth или WiFi , некоторые пины не могут читать аналоговые данные. На практике, при подключении к смартфону, устройство просто переставало реагировать на сенсоры. И все бы ничего если бы я хотя бы мог переразвести, но функции были раскиданы по пинам с учетом их специфики, и получалось, что любой пин к которому можно подключить сенсоры, оказывался именно тем, который не мог работать при включении радиомодуля. Но интернеты, таки помогли.

Немного пораскинув мозгами, пришел к выводу, что вместо ACS712, лучше использовать INA219. Во-первых управление по I2С, во-вторых возможность измерять напряжение до 26 вольт. При измерении сопротивления, обычно используют коммутируемые резистивные делители для разных диапазонов, эта же функция необходима при измерении ёмкости конденсаторов. Вариант использовать ограниченное число пинов для коммутации резисторов такой себе, вместо этого я поставил цифровой потенциометр на 100К AD5245. Таких в устройстве два. Второй регулирует чувствительность ОУ на входе. Второй щуп перенес в разъем для зарядки TYPE-C и несколько видоизменил корпус.

Внеся все эти изменения я заказываю плату на JLCPCB и сходу понимаю, что уже есть косяки. Но не смертельно. Вот что у меня получилось на этом этапе:

Ниже небольшой видеообзор:

Тут важно понимать, что этот прибор даже не пытается претендовать на высокую точность измерений. Речь идет о тех параметрах, которые минимально необходимы без упрощения до уровня пробника. Для меня здесь принципиальна простота и возможность кастомизации на уже готовом железе. Даже приложение для смартфона я собрал в App Inventor.

На сегодняшний день, у меня написан основной базис ПО. Пришлось повозиться с корпусом, зато смог максимально удешевить стоимость пресс-формы. Для понимания порядка цен, стоимость матрицы $5600, ресурс 300к отливок. Стоимость 1 отливки, включая заглушку на дисплей и подсветку рабочей зоны $1,53. Размеры ~120x22мм. Корпус цельнолитой из ABS с SoftTouch покрытием.

Но даже это для меня довольно дорого. возможно попробую обратиться к краудфандингу. Если тема будет интересна, готов периодически выкладывать статьи.

Подробнее..

Приручение nRF пульта для ПК с потерянным приемником

10.05.2021 16:07:24 | Автор: admin

В этой статье я расскажу, как мне удалось заставить работать nRF пульты для ПК, для которых были утеряны приемники. Не обошлось без Arduino, множества попыток бросить это дело, долгого безуспешного гугления, радости маленьким победам, разочарования от неудач и наконец новой жизни для nRF пульта, но обо всем по порядку...

В далекой-далекой галактике...

Для начала, расскажу зачем мне вообще понадобился такой пульт. Будет много и длинно, кому это неинтересно, может сразу перейти к следующей главе. Дело, в том, что я все еще отношусь к той устаревшей модели людей, которые привыкли видеть компьютер центром всего мультимедиа в доме (как это было в середине 2000х) и хоть, теперь для каждой задачи уже давно есть свой гаджет, мне все равно так привычнее и удобнее. Поэтому фильмы я смотрю исключительно через ПК. У меня довольно древний 42' ЖК телевизор подключенный по HDMI, который я не вижу смысла менять на что-то новее. Если мне нужен большой экран - для этого у меня есть проектор и экран с диагональю в 2 метра (так же по HDMI к ПК). Но я уже давно на нем ничего не смотрел, он для чего-то такого эффектного, красивого, вроде Аватара, но что-то за последние пару лет я ничего такого интересного для себя не находил. А простые сериальчики можно глазеть и на экране поменьше, к чему эти огромные головы крупным планом? И вот, уже, наверное, лет 10 назад, попался мне первый пульт для ПК, шел он в комплекте к одной из материнок от ASUSа.

Он был маленький простой и удобный, и я тут же заценил, что больше не надо подрываться и нажимать кнопки на клавиатуре, чтобы поставить на паузу, прибавить громкость, увеличить скорость или мотнуть. Сейчас можно, конечно, использовать для этого Bluetooth клавиатуру или мышку, но я по прежнему вижу это менее удобным, чем использовать пульт. Клавиатура здоровая, на ней куча ненужных кнопок, ей не место на диване. Мышь надо по чему-то возить и еще высматривать там на экране курсор, а это бывает трудновато, когда курсор-то на экране, только вот на другом. А пульт просто взял в руку и нажал нужную кнопку, к которой уже привык и которую найдешь наощупь. Да можно еще поднять DLNA и использовать SmartTV, но там надо думать схавает ли телек этот формат, настраивать транскодинг, если нет (а транскодинг вообще зло, зачем так мучать видео). Поэтому, я очень долго использовал этот пульт (точнее не этот, это запасной, а тот который я использовал, уже слишком истерся и выглядит неприглядно, да, я не из тех людей, которые держат пульты в целлофане, в целлофане ощущения не те). И всем этот пульт был вроде хорош, но со временем мне стало не хватать на нем кнопок. И тогда я заказал с Али вот такой:

Его я использовал вместе с программой EventGhost для Windows, которая позволяет назначать на разные кнопки разные действия и поддерживает некоторые пульты, включая этот. Но вот был один недостаток - для того, чтобы этот пульт нормально работал внутри EventGhost и не делал больше ничего лишнего, для него нужно было поставить специальный драйвер, а драйвер этот был не подписан. Как известно Майкрософт это любит не очень и хоть и оставляет такую возможность, но приходится немного поплясать с бубном, перезагружаясь в тестовый режим, где этот драйвер надо ставить. При этом, во время крупных обновлений 10ки он зачастую слетал и приходилось проделывать это снова. Этот пульт служил мне еще несколько лет, но в какой-то момент, после очередного слета драйвера, мне это надоело и я решил попробовать что-то еще. Тогда я заказал с Али вот такое чудо:

Он уже работает на 2.4Ghz и не требует прицеливания, что конечно большой плюс, а вот минусом было то, что для него не было уже какого-то специального драйвера, который позволил бы мне назначить на каждую его кнопку именно те комбинации клавиш, которые мне нужны. Т.е. я конечно мог назначить на кнопку "домой" какое-то действие в EventGhost и оно выполнялось, но помимо этого кнопка "домой" срабатывала еще и как кнопка "домой" и открывала мне браузер с домашней страницей. Я даже нашел какую-то программу, которая позволяла мне заблокировать прямое назначение некоторых кнопок, на которые у меня были назначены макросы в EventGhost и это улучшило картину. Но я все еще не мог назначить действие на кнопки с цифрами, иначе они выполнялись, когда я нажимал эти цифры на обычной клавиатуре, и заблокировать я их не мог по той же причине. Позже я нашел древнюю программу HidMacros которая могла вешать действия на клавиши с какого-то конкретного устройства, и она даже работала под 10кой, но че-то программ стало слишком много для такой простой задачи и я снова стал бояться, что с очередным обновлением что-то из этого отвалится. К этому времени я как раз увлекся Arduino и понял, что могу сделать, чтобы любой ИК пульт работал у меня, как пульт для ПК. Я снова вернулся к предыдущему пульту, но теперь он передавал сигнал в ИК-приемник Arduino, а тот в свою очередь отдавал команду в EventGhost через ком порт. Единственное, что после 2.4Ghz пульта, использовать снова ИК, которым надо хоть не много, но прицеливаться было шагом назад, но я смирился. И все шло себе тихо-мирно, но вдруг, внезапно, мне достались эти красавцы:

Посмотрев на них и на их набор кнопок, я понял, что хочу чтобы хоть один из этих ребят работал на меня. Я вставил батарейки и радостно начал нажимать кнопки, но на ИК приемник ничего не приходило. И вот тут я понял - они не ИК, они такие же, как и VONTAR на картинке выше, работают на 2.4Ghz и без приемника с ними делать нечего, а приемников от них то у меня и нет. Можно было, конечно, заказать такой же пульт с приемником на Али, но я уже предвидел какие проблемы меня ждут: я снова не смогу нормально назначать действия на кнопки, они будут эмулировать те клавиши которые в них зашиты и только их. Снова надо как-то хитро блокировать прямое назначение этих клавиш, снова все не просто Plug и не просто Play, опять какие-то трудности. А я не люблю, когда трудности. Я люблю когда ахренительно-невероятно-пипец, какие трудности. Поэтому я заказал для Ардуино модуль nRF24L01+ и раз уж нам подарили с барского плеча столько выходных на майские, а погода как-то не все дни обещает быть хорошей, я решил потратить часть этого времени, чтобы хакнуть протокол пультов!

Этап принюхивания

Итак, мой модуль nRF24L01+ пришел, я достал одну из Ардуино нано и был готов перехватывать пакеты!

Это не моя картинка, но подключал я по этой схеме на те же пины с поправкой на их другое расположение в наноЭто не моя картинка, но подключал я по этой схеме на те же пины с поправкой на их другое расположение в нано

Ну вот теперь я точно был готов к перехвату пакетов, но вот пакеты оказались не готовы быть перехваченными. Это было первое разочарование. Вообще модуль nRF24L01+ я брал наугад, типа тут 2.4Ghz, там 2.4Ghz, ну... давайте... работайте вместе как нибудь! Ну пожалуйста! Но, как выяснилось, протоколов этих очень много, те же модули WiFi работают на этих частотах, но пакеты от пульта получать в большинстве своем не могут. И если пульт шлет свои пакеты не по тому протоколу, по которому работает nRF24L01+, то тоже ничего не выйдет. Я понадеялся на удачу и для начала стал искать канал, на котором должны идти данные. Для этого я скачал какой-то нагугленный скетч в интернете, который смотрит на каких каналах есть сигналы. Как оказалось сигналы есть много на каких, но нажатия кнопок на пульте никак на них не влияет. Сигналов больше не становиться ни на одной из частот, а они хаотично появляются на разных частотах, не зависимо от того, нажимаю я что-то на пульте или нет. У nRF24L01+ есть 3 скорости 250Kbit, 1Mbit и 2Mbit. Ни на одной из них и ни на одном из каналов, я пульта не нашел, сколько бы не давил не его кнопки. "Ну что ж", сказал я себе, значит не судьба, и лег спать. Но на утро интерес снова проснулся, и я решил разобрать один пульт и посмотреть, что там все-таки за чип. К моей радости пульт, хоть и собран без единого винтика, но разобрался очень легко:

И что же я вижу на плате?

Именно! Там чип nRF24LE1G, внутри которого сидит nRF24L01. Значит все верно, и протокол тот. Но почему же, я не могу понять на какой частоте он работает? Пульт точно рабочий (когда я нажимаю кнопку, на нем моргает лампочка. А раз лампочка моргает - значит и пульт работает. И не говорите, мне что это не обязательно так!). Я потратил на это еще пару часов, но никаких результатов не добился и тогда я понял:

если уже больше ничего не помогает - прочти наконец этот чертов код, который ты скопировал из интернета и бездумно вставил в свой проект!

И я стал смотреть код и понял в чем причина. Модуль не умеет одновременно случать все частоты, поэтому код написан так, чтобы модуль постоянно переключался с одной частоты на другую слушая каждую по 128мкс. Но частот много, и получается, что те сигналы, которые генерит пульт, не успевают попадать под сканирование или попадают, но в очень малом объеме, не отличимом от общего шума. В результате я переписал скетч, чтобы частоты переключались вручную ('w' в COM порт - следующая, 's' - предыдущая), и о чудо! Уже на первом же канале, я увидел изменения при нажатии кнопок пульта. На втором канале, сигналов при нажатии стало еще больше, на 3м еще, а к 7му все прекратилось. Значит золотая середина - это канал номер 3, по нему и идут данные. Сканер, который получился в итоге выложил сюда:

https://github.com/CodeName33/NRFRemote/blob/main/NRF24Scanner.ino

Итак, пол дела сделано (я так думал), пульт работает по нужному протоколу и частота найдена, осталось только получать данные и использовать их! Как все просто в ожидании. Теперь реальность. Все не так! Как оказалось, nRF24L01 это не вай-фай и в нем нельзя сказать "получай все". Он требует задания скорости, канала и адреса, и без этого ничего получать не будет. Канал я уже знаю, осталось две переменные, скорость и адрес, и если первое можно подобрать (их всего три), то на подбор второго (адрес от 3х до 5 байт) уйдут всего лишь, миллиарды лет. Как хорошо, что они у меня, есть, погнали! (нет). Путем гугления выяснилось, что модуль можно немного обмануть. Адрес может быть от 3х до 5байт, но если передать ему, что длина адреса 2 байта, а само значение 0x55 или 0xAA, то можно таким образом получать все! В одном из случаев данные будут сдвинуты на 1 бит (в зависимости от того, как они передаются передатчиком). Ну что ж, начнем с адреса 0x55 и скорости в 2Mbit и к моему удивлению, это сработало с первого раза, я тут же стал получать кучу пакетов, а зажав кнопку на пульте, я заметил, что среди этих пакетов стали появляться пакеты с однотипным началом:

Естественно, я тут же поставил фильтр по этим 4 первым байтам и о чудо! Пакеты начали появляться, только при нажатии кнопок с пульта:

Успех был так близко, осталось только запомнить какие данные идут от каких кнопок и все решено, но вот тут возникла проблема. При нажатии на одну и ту же кнопку, каждый раз приходили разные данные, точнее если отсеять мусор в конце, я заметил 2 варианта и по началу я решил, что добавлю их оба, но позже, уже начав добавлять коды всех кнопок, я понял, что вариантов уже не 2, а 4. И добавлять на каждую кнопку все 4 варианта кодов было не круто. Да и вообще, не круто распознавать кнопку по данным сырого пакета, надо этот пакет хотя бы расшифровать. Возможно я в нем найду неизменные данные, по которым гораздо проще смогу определять, какая кнопка был нажата. И если формат самой секции данных в пакете знает только производитель пульта (HP), то формат пакета nRF24L01 секретом не является, вот он:

По этой схеме я и стал пытаться разобрать данные:

И все бы тут хорошо и адрес постоянный и доп адрес (5й байт адреса) меняется в зависимости от группы нажатой кнопки, но вот размер данных, я честно пытался взять его из чисел 13, 12, 159 и 130 извлекая 6 бит. Но выходил полный бред, 12 и 13 давали число 3, что явно слишком мало, а 159 - это 39, что явно нарушает все правила протокола, допускающего не более 32 байт данных. Притом, что данные внутри пакета дальше шли даже вроде и не плохо. Чертов Packet Control Header занимает именно 9 бит, и это значит, что все байты дальше надо сдвигать на 1 бит, что я и делал. И вроде все похоже. Но не совсем. Все равно на одну и ту же кнопку, я получал разные данные, странные данные, хотя часть из них выглядела очень правдоподобно. Но времени было уже около 3х ночи, и еще через 3 часа первые петухи начнут петь о том, какой я лошара, и мне нечего будет им ответить. Совсем нечего. На этом я плюнул, и лег спать. Утро вечера мудренее, я уже не раз в этом убеждался и решил, поверить этой пословице снова.

Этап вязки

Мое утро настало позже, чем я ожидал, но все таки подкинуло еще пару идей, я снова начал изучать эти цифры, пытаться крутить биты туда-сюда, понять что я упустил, но все подтверждало то, что у меня все было правильно, а картина все равно не сходилась. Я потратил еще пару часов и результат был нулевой. Черт, что же не так? Я же вроде не дурак? У меня даже справка есть! Мне её выдавали, когда я права менял. С тех пор не должно было ничего сильно измениться. Я еще раз понажимал две соседние кнопки на пульте и кажется начал кое-что понимать. Одна кнопка давала что-то типа последовательности 247 0 где-то в середине данных, другая 246 128 на тех же позициях. 247 и 246 это наверное коды кнопок, они рядом, логично, что соседние кнопки имеют отличие на кода единицу. Но вот следующий байт это 0 в одном случае и 128 в другом. Но ведь 0 это 00000000 по битам, а 128 это 10000000. Такое ощущения что эта единица заехала сюда зря, она из предыдущего байта. Но я точно все правильно смещаю, на 1 бит, как и должно быть, без смещения было еще хуже, было вообще 01000000, что равно 64... Стоп! Все если и правда все смещено еще на 1 бит! Ведь именно этим и отличаются адреса 0x55 и 0xAA которые используются для "хакерского" приема всех пакетов.

Флешбэк:

Адрес может быть от 3х до 5байт, но если передать ему, что длина адреса 2 байта, а само значение 0x55 или 0xAA, то можно таким образом получать все! В одном из случаев данные будут сдвинуты на 1 бит (в зависимости от того, как они передаются передатчиком)

Я определенно дурак, я ведь уже пробовал менять 0x55 на 0xAA до этого, но в этом случае у меня вообще переставали приходить мои пакеты... А они так и должны были сделать! Все сдвинулось на 1 бит, и адрес тоже, а я продолжаю фильтровать пакеты по первым байтам 65, 223, 152, 111, а они тоже меняются! Я отменил фильтр и снова нашел адрес пульта в море сигналов, он и правда стал другим:

И наконец-таки, поле с размером данных стало адекватным, теперь пакеты можно расшифровать:

Но самое главное, теперь при нажатии одной и той же кнопки, данные всегда приходят одни и те же (на самом деле не всегда, а почти всегда, но это уже ошибки связанные с загруженностью 2.4Ghz канала, по идее должно отсеиваться, если проверять CRC). Далее я забил данные всех кнопок в массив, чтобы их распознавать, и при нажатии кнопок в порт стали выводиться адекватные данные, с которыми, в свою очередь можно работать в EventGhost:

Я научился понимать, какие коды соответствуют нажатию клавиши, а какие тому, что все клавиши в группе отпущены. Это важно, для того, чтобы можно было делать авто-повтор нажатия для некоторых клавиш при их зажатии на пульте (перемотка, например или громкость), а для некоторых не делать (Play/Pause, например). В EventGhost все настраивается очень просто, для начала добавляется плагин ком-порта:

Дальше все что приходит из этого ком-порта можно видеть в логе программы:

И назначать макросы на эти события:

Итоговый результат скетча здесь:

https://github.com/CodeName33/NRFRemote/blob/main/NRF24Remote.ino

CRC, я все же решил не проверять, т.к. при включении его проверки (вариант с 1 байтом CRC) почему-то отсеивается довольно приличная часть пакетов, которая на самом деле имеет вполне себе валидные данные внутри. Может быть что-то еще можно подкрутить, но пока сойдет и так. Еще у пульта выявился еще один неприятный момент: Часть его кнопок работает довольно странно (крестовина и цифры). После нажатия одной из этих кнопок, пульт довольно долго шлет еще какие-то команды и ту команду, которую я посчитал за "кнопка больше не нажата", он может присылать с задержкой до 1 сек. Это очень много и можно поставить крест на быстрой навигации стрелочками (она стала медленная). Вероятно это как-то связано с особенностями его работы, может быть приемник ему, что-то должен отвечать, а может я что-то неверно понял, но на данный момент мне не удалось это победить. Возможно, еще поковыряю.

В будущем хочу отказаться от EventGhost и перевести проект на Arduino Pro Micro, которая умеет прикидываться USB клавиатурой и сразу отправлять нужные нажатия клавиш, работая без посредников. В этом случае пульт сможет работать не только в разных ОС, без доп. программ, но и с телевизорами и Андроид устройствами. Но пока все так, как есть. Спасибо за внимание!

Подробнее..

Recovery mode Очередной Wi-Fi Jammer на Очередной ESP8266

17.05.2021 18:06:47 | Автор: admin

Предупреждение ( некий АХТУНГ, так сказать)

Я не являюсь автором ПО и, тем более, не зазываю Вас повторять подобные устройства, так как это может быть запрещено законом и преследуется наказанием. Спасибо.

Вступление

Я в свои практически 20 лет (на момент написания статьи - через 3 дня) уже как года 4 слежу за всякими интересностями на Ардуино и околоАрдуинных платах для разработки. Сначала купил Нанку, с которой не понимал, что делать, потом поступил на разработку ПО и начал понимать, шо да как. От этого мой интерес увеличился настолько, что это стало моим хобби. Да, я не силён в программировании до сих пор, так как я банально прогуливал пары, но зато у меня есть база, так сказать основа, с помощью которой я снова вхожу в программирование через визуализирование этого во всяких поделках на Ардуино и им подобных. Мне не нравилось программирование из-за того, что результат ты увидишь далеко не сразу, а с помощью микроконтроллеров этапы готовности можно посмотреть прямо на глазах, да и потрогать, пощелкать, попереключать.

Перейдем к железу

По железу все банально и просто: Китайский клон Wemos D1 Mini на базе ESP8266, I2C дисплейчик 128х64 и две кнопки, которые я вырвал с китайской магнитолы. В оригинале их 3, но у меня не влазило в корпус, поэтому решил оставить только кнопку "ок" и "вниз", так как если долистать меню до конца, то указатель начнет с самого начала. Да, больше времени уходит на листание менюшек, но зато компактнее .

Прошивка

Прошивку можно скачать по ссылочке ( ТЦ )

Так же там имеется подробная инструкция для таких, как я XD

Я не буду заостряться на подробностях настроек до прошивки, в конфиге все банально ясно. Есть два вида файлов: .bin, который шьется NodeMCU Flasher и исходный код со скетчем ардуино. Я использовал скетч, что бы настроить подключение дисплея, переназначить кнопки и изменить названия.

Корпус

Изначально я раскурочил старый 3G модем от МТС (который сейчас в Украине Vodafone), вырезал отверстия под дисплей и кнопки. Ровно после финальной сборки я понял, что выглядит не очень: кривые вырезы, лишние размеры для дисплея, болтающиеся кнопки, корпус плохо закрывался, питание подключалось путем разгибания нижней части корпуса. Короче, не комильфо. Надо думать что-то новое.

Новый корпус и формфактор.

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

По размерам устройство получилось 3х4см с учетом вылета кнопок с корпуса. И это меня очень радует. У меня не было конкретной цели собрать джаммер, я просто хотел своими руками сделать какое-то крутое устройство, да и еще в подобных размерах.

Возможности

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

  • Сканирование сетей и устройств ( если они подключены к сетям) с последующим просмотром количества отправляемых пакетов, MAC-Адреса и мощность сигнала.

  • Атака путем деаутентификации как полностью всей сети, так и конкретного устройства по MAC-адресу

  • Режим "Бекон", который создает до 80 точек доступа, названия которых можно скопировать с существующих сетей, записать свои или создать с помощью встроенного генератора.

  • Режим "Probe" с которым я так и не разобрался, да и фиг с ним )

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

Выводы

Хоть моей целью не было воспроизведение конкретно этого устройства - результатами я очень доволен, так как это моё первое самодельное устройство, размеры которого не превышают распределительную коробку из строй магазина за 15 гривен

P.S. Чуть позже запишу видео, как сие чудо техники работает на примере своей точки доступа и ноутбука

Подробнее..

Проект электронного мультитула QUARK. Часть 2

11.06.2021 16:11:37 | Автор: admin

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

QUARKQUARK


Для начала напомню, что собой представляет устройство. QUARK это электронный мультиинструмент, в первую очередь, ориентированный под разработку микроконтроллерных устройств, Arduino, ESP32, STM32, IoT, домашняя автоматизация и тому подобные девайсы.

Че определяется такая ориентированность? Во-первых, набором функций. И если первая часть стандартна для типичного мультиметра:

Вольтметр

Амперметр

Измерение сопротивления

Измерение емкости

Измерение индуктивности

то UART логгер и UART плоттер вещи необходимые ардуинщикам и иже с ними. Осциллограф конечно не блещет скоростью 400 килосемплов, однако проверки ШИМ сигналов и сигналов с различных датчиков, его более чем достаточно.
Во-вторых идеологией работы с выводимыми значениями. Скажем, ардуинщику практически никогда не требуется знать напряжение с точностью в одну тысячную процента, зато значение логического уровня параметр всегда необходимый:

ВольтметерВольтметер

Точно так же мгновенное потребление тока, при разработке IoT, параметр в себе. Гораздо удобнее проследить изменение в динамике при различных режимах работы устройства:

АмперметерАмперметер

Калькулятор цветовой и СМД маркировки компонентов вещь полезная и нужная, но, согласитесь, так удобнее:

СопротивлениеСопротивление

А сейчас опишу свой личный опыт работы с осциллографом. В свое время приобрел себе DS203. Вполне себе, по характеристикам, годный девайс, с жутко неудобным управлением:

Стандартный сценарий работы примерно такой:
Необходимо снять форму (частоту, амплитуду) сигнала с/на пина ноги устройства. Подключаешься к контактам, включаешь осциллограф, отключаешь не используемые входы, настраиваешь триггер, амплитуду, положение графика на экране. Да, я знаю, что прошивками это кое-как решается, но мой DS203 больше не шьется, да и возня с прошивками Но поскольку свой девайс я делал в первую очередь для личного удобства, то и дефолтный режим, это полностью автоматическая настройка развертки сигнала на лету. Тыкаю в нужный пин и, практически сразу вижу сигнал:

ОсциллографОсциллограф

UART данные, конечно, удобнее смотреть на телефоне чем на дисплее устройства. Не скажу, что я прям мучаюсь при подключении UART-TTL моста к компу, но в поле не всегда имеется такая возможность:

Теперь пару слов о схемотехнике. Вся система построена на ESP32 со всеми вытекающими из нее ништяками (bluetooth, Wi_fi). Для измерения напряжения и тока я использовал готовый чип INA219. Подключается по I2C шине, имеет малый размер и вполне достойные, для моих задач, параметры. Сопротивление измеряю стандартным делителем напряжения, но в качестве известного сопротивления использую цифровой потенциометр AD5245, что освобождает пины контроллера, а учитывая тот факт, что AD5245 управляется по I2C, так и вообще нет нужды в дополнительных пинах. Тем же способом измеряю емкость конденсаторов по известному методу заряда до 63.2%. На больших емкостях AD5245, подключенное к питанию имеет низкое сопротивление, а при низких, заряд идет через 1 мегаомный резистор. Таким образом, минимальная измеряемая емкость определяется пикофарадами.
Индуктивность меряю резонансным методом при известной ёмкости по срабатыванию компаратора.
Тракт осциллографа реализован на Rail-to-Rail ОУ AD8541, усиление сигнала регулируется вторым AD5245. Соответственно, сигналы как с высоким, так и с низким размахом амплитуды, поступают на вход АЦП в максимальном разрешении. Для оцифровки использую аппаратный I2S, складываю весь буфер в DMA и вывожу на LCD и, при необходимости, отсылаю по bluetooth.

UART вход реализован аппаратно. Предварительно определяется Baud rate, после чего происходит инициализация драйвера UART с определенными параметрами.
На плате присутствует датчик ускорения LSM6DS3TR. Вообще я его планировал использовать для автовыключения, но ничто не мешает вывести с него данные на экран.


А теперь хотелось бы сказать пару слов о тех нововведениях, которые были реализованы на основе предложений к предыдущей статье.

Во-первых, универсальный прикручиваемый щуп:

Такие будут как в корпусе, так и во втором щупе. Довольно универсальное решение на стандартной резьбе М2.
Во-вторых, расширен функционал: поиск компонентов по заранее введенному значению и удержание значений с записью в лог.
И в-третьих, вариант без корпуса, этакий кит-набор, но распаянный.

Ну и самое главное. По-совету читателей я таки запустился на краудфандинговой платформе Crowdsupply. Некоторое время вел переговоры, совместно настраивали страницу и готовили описание. Платформа ориентирована на железные open source проекты, а значит и мое устройство будет выложено в открытый доступ. Всех, кому проект интересен приглашаю поддержать старт и тут я снова сделаю упор на том, что это open source.

Подробнее..

Как подключить содержимое любых файлов для использования в коде C C

08.03.2021 02:20:33 | Автор: admin

Привет, Хабровчане!

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

О чем речь?

Задача состояла в подключении файлов: HTML, JS, CSS; без специальной подготовки. Так же неудобно подключать бинарные файлы (например картинки) конвертируя их в HEX. Так как не хотелось конвертировать в HEX или разделять на строки, искал способ подключения файла в адресное пространство программы.

Как обычно это выглядит

Пример, c разделением строк:

const char text[] =    "<html>"            "\r\n"    "<body>Text</body>" "\r\n"    "</html>";

Пример, с HEX (больше подходит для бинарных данных):

const char text[] =    {        0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C,        0x62, 0x6F, 0x64, 0x79, 0x3E, 0x54, 0x65, 0x78,        0x74, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E,        0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E,        0    };

Видел даже такое:

#define TEXT "<html>\r\n<body>Text</body>\r\n</html>"const char text[] = TEXT;

Все #define располагались в отдельном .h файле и подготавливались скриптом на Python. С аннотацией, что некоторые символы должны бить экранированы \ вручную в исходном файле. Честно немного волосы дыбом встали от такого мазохизма.

А хотелось, чтобы файлы можно было спокойно редактировать, просматривать и при компиляции всё само подключалось и было доступно, например так:

extern const char text[];

Оказалось всё просто, несколько строчек в Assembler.

Подключаем файл в Arduino IDE

Добавляем новую вкладку или создаём файл в папке проекта с названием text.S, там же размещаем файл text.htm.

Содержимое файла text.htm:

<html><body>Text</body></html>

Содержимое файла text.S:

.global text.section .rodata.myfilestext:    .incbin "text.htm"    .byte 0

Не забываем нулевой символ \0 в конце, он здесь в строке сам не добавится.

Сам скетч:

extern const char text[] PROGMEM;void setup(){    Serial.begin(115200);    Serial.println(text);}void loop() { }

Компилируем, загружаем и смотрим вывод:

Отлично, когда-то бы я от радости прыгал до потолка, от того что всё получилось.

Код работает в AVR8, но например в ESP8266 получим аппаратный сбой. Всё потому, что чтение из Flash доступно по 32 бита и по адресам кратным 32 бит. Чтобы было всё хорошо, каждому файлу требуется делать отступ для кратности, код будет выглядеть так:

.global text.section .rodata.myfiles.align 4text:    .incbin "text.htm"    .byte 0

Загрузить можно в секцию кода: .irom.text, если не хватает места в .rodata.

Для STM32 так же рекомендуется выравнивать по 32 бита, но не обязательно.

А как записать размер данных во время компиляции? Например, для бинарных данных не получится остановится по нулевому символу. Так же просто:

.global text, text_size.section .rodata.myfilestext:    .incbin "text.htm"    text_end:    .byte 0text_size:.word (text_end - text)

Объявление:

extern const char text[] PROGMEM;extern const uint16_t text_size PROGMEM;

Осталось написать макрос, для удобства подключения файлов:

.macro addFile name file    .global \name, \name\()_size//  .align 4    \name:        .incbin "\file"        \name\()_end:        .byte 0//  .align 4    \name\()_size:        .word (\name\()_end - \name).endm.section .rodata.myfilesaddFile text1   1.txtaddFile text2   2.txtaddFile text3   3.txt

И макрос для объявления:

#define ADD_FILE(name) \    extern const char name[] PROGMEM; \    extern const uint16_t name##_size PROGMEM;ADD_FILE(text1);ADD_FILE(text2);ADD_FILE(text3);void setup(){    Serial.begin(115200);    Serial.println(text1);    Serial.println(text1_size);    Serial.println(text2);    Serial.println(text2_size);    Serial.println(text3);    Serial.println(text3_size);}void loop() { }

Вывод:

Таким образом можно подключить любой файл и представить его любым типом, структурой или массивом.

Подключаем любой файл и не только, в GNU toolchain

Принцип тот же самый, ни чем не отличается для Arduino. В принципе в Arduino используется тот же toolchain от Atmel.

Только здесь у нас в руках Makefile и мы можем до компиляции и сборки запустить какой-нибудь скрипт.

Для примера возьму код из готового моего проекта на STM32, где автоматически при компиляции увеличивается версия сборки. Так же включаются в проект WEB-интерфейс для последующего использования в LWIP / HTTPD.

Скрипт version.sh:

#!/bin/bash# Version generator# running script from pre-buildMAJOR=1MINOR=0cd "$(dirname $0)" &>/dev/nullFILE_VERSION="version.txt"FILE_ASM="version.S"BUILD=$(head -n1 "$FILE_VERSION" 2>/dev/null)if [ -z "$BUILD" ]; thenBUILD=0elseBUILD=$(expr $BUILD + 1)fiecho -n "$BUILD" >"$FILE_VERSION"cat <<EOF >"$FILE_ASM"/*** no editing, automatically generated from version.sh*/.section .rodata.global __version_major.global __version_minor.global __version_build__version_major: .word $MAJOR__version_minor: .word $MINOR__version_build: .word $BUILD.endEOFcd - &>/dev/nullexit 0

Создаётся файл version.S в который из version.txt загружается номер версии предыдущей сборки.

В Makefile добавляется цель pre-build:

######################################## pre-build script#######################################pre-build:bash version.sh

В цель all надо дописать pre-build:

all: pre-build $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin

Объявление и макросы для printf у меня в macro.h:

extern const uint16_t __version_major;extern const uint16_t __version_minor;extern const uint16_t __version_build;#define FMT_VER             "%u.%u.%u"#define FMT_VER_VAL         __version_major, __version_minor, __version_build

В HTTPD из LWIP немного был удивлён когда увидел, что содержимое файлов надо хранить вместе с заголовками HTTP. Чтобы не менять архитектуру, загрузку делал как это организовано в примере fsdata.c. Использовал fsdata_custom.c, для этого установлен флаг HTTPD_USE_CUSTOM_FSDATA.

Код в fsdata_custom.c:

#include "lwip/apps/fs.h"#include "lwip/def.h"#include "fsdata.h"#include "macro.h"extern const struct fsdata_file __fs_root;#define FS_ROOT &__fs_root

Сборка файлов fsdata_make.S:

.macro addData name file mime\name\():.string "/\file\()"\name\()_data:.incbin "mime/\mime\().txt".incbin "\file\()"\name\()_end:.endm.macro addFile name next\name\()_file:.word \next\().word \name\().word \name\()_data.word \name\()_end - \name\()_data.word 1.endm.section .rodata.fsdata.global __fs_root/* Load files */addData __index_htm         index.htm           htmladdData __styles_css        styles.css          cssaddData __lib_js            lib.js              jsaddData __ui_js             ui.js               jsaddData __404_htm           404.htm             404addData __favicon_ico       img/favicon.ico     icoaddData __logo_png          img/logo.png        png/* FSDATA Table */addFile __logo_png          0addFile __favicon_ico       __logo_png_fileaddFile __404_htm           __favicon_ico_fileaddFile __ui_js             __404_htm_fileaddFile __lib_js            __ui_js_fileaddFile __styles_css        __lib_js_file__fs_root:addFile __index_htm         __styles_css_file.end

В начале каждого файла загружается заголовок, пару примеров из папки mime.

Файл html.txt:

HTTP/1.1 200 OKContent-Type: text/html; charset=UTF-8Connection: close

Файл 404.txt:

HTTP/1.1 404 Not foundContent-Type: text/plain; charset=UTF-8Connection: close

Нужно обратить внимание на пустую строку, чего требует спецификация HTTP для обозначения конца заголовка. Каждая строка должна заканчиваться символом CRLF (\r\n).

P.S. Код проекта из ветхого сундука, так что в реализации мог забыть чего ни будь уточнить.

В завершении

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

Спасибо за внимание, удачных разработок!

Подробнее..

Управление системой NooLite через голосового помощника Алиса с помощью умного пульта Яндекса

21.04.2021 12:06:56 | Автор: admin

Я хочу рассказать о одном из способов управлять беспроводной электрикой NooLite с помощью голосового помощника и смартфона (плюс как бонус с компьютера или любого ИК-пульта без Интернет-шлюза).

Вся электрика в квартире и на даче у меня построена на системе NooLite. Почему именно NooLite? Начну издалека. С продукцией фирмы "Ноотехника" я познакомился еще в прошлом веке. Это были блоки защиты галогенных ламп. Они мне очень понравились - свет включался плавно и лампы служили намного дольше. Но вскоре на смену галогенным лампам пришли люминисцентные и блоки защиты стали неактуальны. Потом в квартире был ремонт, стоивший мне немало седых волос и когда через некоторое время возникла необходимость перенести и добавить выключатели, одна мысль о штроблении стен, пыли, грязи и переклейке обоев просто ввергала меня в ужас. Именно тогда я и познакомился с системой беспроводного управления освещением от NooLite. В то время еще не было Xiaomi, Sonoff, Tuya и других недорогих альтернативных решений. Были системы умного дома от европейских серьезных производителей, но там цена вопроса была просто неадекватной. Я решил все свои проблемы с переносом выключателей, разбиением освещения на зоны, сценариями освещения, проходными выключателями, включением-выключением вентиляции и удаленным управлением светом в сараях и гараже на даче с помощью самых первых NooLite, без шифрования и обратной связи.

Все что я сделал много лет назад работает до сих пор, батарейки в пультах менял 1 или 2 раза, в зависимости от интенсивности пользования. Потом добавился беспроводной датчик движения на двери в туалете, позволяющий маленькому ребенку без страха ходить туда (свет включается уже при начале открывания двери) и автоматически выключающий свет и таймеры в туалете и ванной, включающие вытяжку через заданное время после зажигания света и поддерживающие ее включенной некоторое время после выключения. Одно время я крепко задумался о настоящем "умном доме", купил несколько силовых блоков, пультов, датчики температуры и влажности, продумывал структуру. Но потом передумал, так как понял что в не такой уж большой двухкомнатной квартире мне это не нужно. Я так и остался верен системе NooLite, хотя сейчас хватает альтернатив и некоторые из них дешевле и выглядят, возможно, современнее чем изделия Ноотехники. Но тут у меня есть определенные условия. Во-первых, управление моим освещением и электронными устройствами не должно зависеть от китайского облака и вообще от наличия/отсутствия Интернет, тем более что в последние месяцы у нас в городе практикуется периодическое его отключение или замедление (Интернет и wi-fi только как бонус в управлении). Во-вторых, я не хочу держать постоянно включенными узкоспециализированные шлюзы и компьютеры, и так хватает устройств, которые включены постоянно. В-третьих, для меня очень важны надежность и гарантия, больше чем цена. У меня сами по себе перестали функционировать две розетки SmartPlug от Хiaomi и я не смог их починить. Пришлось выбросить. Вышедшие из строя силовой блок и таймер для санузлов в Ноотехнике мне просто поменяли на новые, не уточняя кончилась ли гарантия и не спрашивая при каких условиях они перестали работать (при проведении экспериментов бывает всякое). Это Lifetime warranty в том виде, в котором она мне нравится. Ну и в-четвертых, дополнять уже работающую и хорошо зарекомендовавшую себя систему, проще и легче чем городить что-то другое.

Сейчас уже вовсю используется новое поколение NooLiteF с обратной связью и шифрованием, но для пользователя мало что поменялось, монтаж, привязка и отвязка такие же простые, надежность тоже вроде на высоте. А обратная связь, прошивка "по воздуху" и возможность считать состояние устройства это бонус, кому-то нужный, кому-то нет.

Вроде все хорошо, но сейчас мне уже хочется, как дополнительную опцию, иметь иногда возможность управления NooLite через Интернет. Такая опция у Ноотехники есть. И даже существуют приложения для смартфонов под Android и iOS. Но для этого нужно докупать Интернет-шлюз PRF-64 или контроллер PR-1132, которые стоят больше $100 и должны быть все время включены. Это еще одно постоянно включенное в розетку устройство с весьма узкими возможностями. А с появлением дома умной колонки с голосовым помощником Алиса, захотелось "подружить" Алису с NooLite.

Раз хочется сделаем. Для начала я забил в поиск Гугла " NooLite и Алиса". Зачем изобретать велосипед, вдруг уже давно все решено? И да, мне выдало несколько уже готовых решений, но все они показались мне излишне сложными. Вот например:

На Хабре есть статья "Обход noolite роутера через mtrf64+esp8266+MQTT Buddy Android app".

Там сказано что модуль mtrf64 подключен по UART к esp8266, которая в свою очередь выходит в интернет через ваш роутер и подключается к MQTT бесплатному брокеру. Вы, как пользователь, через мобильное приложение так же подключаетесь к этому облачному брокеру и начинаете посылать команды в MQTT каналы, которые в свою очередь разбираются на лету и в зависимости от команды передаются по UART MTRF64 модулю. Проблему управления через Интернет без дорогостоящего и узкоспециализированного интернет-шлюза от Ноотехники это решает. Но "бесплатный облачный брокер" в связке с ESP8266 почему-то не вселяет в меня уверенности в надежности. Да и голосовое управление прицепить будет непросто (или невозможно?). А значит мне не подходит.

Второе решение реализовано через цепочку навык "Домовенок Кузя"-IFTTT-IHC-шлюз Broadlink (то есть все равно покупка шлюза)-NooLite.

Перспектива регистрации на всех этих сайтах и прописывания настроек меня как-то не воодушевила. Надежность работы такой дли-и-и-нной цепочки тоже не внушает мне доверия. Да и задержка исполнения 3 сек. и более напрягает. Хочется более простого и изящного решения без такой длинной цепочки.

Я начал думать и ставить себе задачу. Покупать какие-то шлюзы без уверенности что это мне нужно и я буду этим пользоваться не хочется. Значит нужно делать из того что есть в наличии. А что у меня есть?

  1. Колонка IRBIS с голосовым помощником Алиса.

  2. Несколько силовых блоков первой серии без обратной связи.

  3. Модули MT1132 и MTRF-64 для управления NooLite и NooLite-F c помощью контроллеров.

  4. Несколько плат Arduino.

Не густо. Логическая цепочка не просматривалась до тех пор пока мне на глаза не попал умный пульт Яндекса. И сразу все встало на свои места. Яндекс напрямую работает со своим пультом, а тот умеет записывать любой ИК-сигнал и передавать его по команде. К Arduino подключены ИК-приемник и модуль управления системой NooLite. По-моему, гениально проще некуда. Умный пульт от Яндекса стоит меньше чем $20 и это устройство универсальное, может использоваться для управления другой техникой (кондиционер, телевизор, ресивер и т.п.), а значит покупка его не бессмысленна. Вероятно, точно также будет работать и универсальный пульт от Tuya, который стоит еще дешевле, но после знакомства с умной колонкой IRBIS (звук и микрофоны у нее довольно посредственные а часть сервисов Яндекса не работает) я убедился что лучше заплатить дороже но взять оригинал, есть вероятность что будет выше качество и меньше глюков. Поэтому пульт выбрал оригинальный от Яндекс, не хочется взять стороннее решение, сэкономить пару долларов и узнать что снова часть функций не работает.

Теперь о модулях управления NooLite. У меня в наличии есть несколько вариантов модулей, которые можно подключить к контроллеру (Arduino).

О модулях MTRF-64 и MTRF-64-USB

По сути MTRF-64 и MTRF-64-USB это одно и то же. Просто у MTRF-64 незапаяна часть деталей и отсутствует корпус и USB разъем, но присутствуют пины.

Модуль MTRF-64, как видно из названия, 64 канальный, может отправлять команды старой системе без обратной связи и отправлять команды и принимать ответ новой системе с шифрованием и обратной связью.

MTRF-64MTRF-64

Технически сделано так, что именно с Arduino MTRF-64 использовать неудобно. Arduino запитывается напряжением 5В а MTRF-64 - 3,3В. Потребуется отдельное питание (на плате не запаян стабилизатор питания 3,3В, хотя место под него есть), отстутствует согласование уровней UART (это ведь не сложно предусмотреть и пара транзисторов практически не увеличила бы цену модуля).

MTRF-64-USB то же самое с запаянной на плате микросхемой переходника USB-UART и еще кое-какими деталями.

MTRF-64-USBMTRF-64-USB

Смысл существования данного контроллера мне вообще малопонятен. Я слабо себе представляю как его реально можно использовать.

Казалось бы, отличная вещь, позволяющая упростить и ускорить процесс отладки проектов. Подключил в USB, посылай из терминала в COM порт последовательности... Но у меня так сделать не получилось. В техдокументации на контроллер такая возможность тоже не описана. Чтобы работать с контроллером есть специальная программа nooLite_ONE. Ее можно скачать с сайта Ноотехники. Но это если найдете, потому что со страницы самого контроллера ссылки на нее на данный момент нет.

Теперь про саму программу. Я не знаю кто ее написал, но она ужасна. Внешний вид и цветовые решения наверняка вызовут у больного эпилепсией приступ. Внутри - куча несуразностей. Такое чувство что просто взяли сервисную программу, которой пользовались разработчики и сообщения которой нужны и понятны только им и прилепили сверху малоинформативную и путаную часть для обычных пользователей. Может поэтому нумерация каналов в "лоховской" части начинается с единицы а в сервисной "профи" с нуля? Да, программой можно кое-как пользоваться приловчившись, но если вы думаете что она поможет вам при написании своей программы, подскажет код отправки контроллеру и посчитает контрольную сумму, то нет.

Документирована возможность отправки команд через API программы из командной строки. Но... при этом программа должна быть уже запущена и, да, из командной строки команды отправляются. Но когда я попробовал записать последовательность команд (или одну команду) в BAT-файл у меня ничего не получилось. Может быть это я такой криворукий...

Про программу nooLite_ONE и ее недостатки можно написать много, но лучше от этого она не станет и смысла в ее существовании не прибавится, поэтому не буду больше тратить на это время.

Мысли вслух и хотелки...

Мне вообще непонятен смысл существования двух недомодулей MTRF-64 и MTRF-64-USB. Зачем плодить сущности? Гораздо больше смысла было бы производить и продавать одну полную версию со всеми запаянными деталями и USB-разъемом, пинами и корпусом в комплекте и любой человек, приобретя его, смог бы использовать его по своему усмотрению без "допиливания".

Помечтаем:

Хорохо было бы, если бы существовала внятная инструкция как настроить терминал для отправки команды на блок управления без спецсофта, если это вообще возможно...

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

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

Теперь про более старые версии контроллеров (уже сняты с производства).

О модулях MТ1132 и МР1132

MТ1132 - 32 канальный, может только отправлять команды системе без обратной связи.

MT-1132MT-1132

Питание 3 ... 5В, к Arduino подключается напрямую, ничего согласовывать не нужно. Управление модулем осуществляется через стандартный интерфейс UART. Скорость передачи данных - 9600 бит/сек., 8 бит данных, 1 стартовый бит, 1 столовый бит, бит четности - отсутствует. Передача от младшего к старшему биту. Для управления модулем необходимо передать через UART пакет из 12 байт. Описание отправляемых данных есть в техдокументации (не идеальной, но какая есть) к модулю.

МR-1132 - 32 канальный, может только принимать данные от датчиков NooLite.

MR-1132MR-1132

Чтение документации на модуль MTRF-64 и готовых библиотек навеяло на меня печаль. 64 канала для эксперимента мне не нужны, шифрование и обратная связь тоже, так как силовых блоков NooLiteF у меня нет, буду использовать те что были куплены ранее, без обратной связи, в частности SU-111-200. Поэтому выбор был сделан в пользу MT1132, пусть он уже снят с производства, но он у меня-то он есть в наличии. На том же принципе совсем несложно сделать и управление с шифрованием и обратной связью, было бы желание (просто вместо 12 байт, как для MT1132, отправлять 17 байт на MTRF-64).

Наверно основным плюсом для меня было то что на GitHub обнаружилась библиотека ardunoo для управления MT1132 с помощью Arduino от zhum (Сергей Жуматий), за что ему огромное спасибо! Эта библиотека сводит написание программы управления к нескольким строкам. А умеет библиотека все немало: привязывать и отвязывать силовые блоки, включать и выключать свет, записывать и исполнять сценарии, плавно менять яркость источника света.

В комплекте с библиотекой есть пример скетча с комментариями, который при запуске позволяет выполнять все эти действия вводя буквы в штатный Serial Monitor среды Arduino.

О грустном...

Вот если бы Ноотехника ВСЕ свои изделия сопровождала понятной документацией, примерами и библиотеками, как это сделал для них Сергей Жуматий...

Мало сделать отличное "железо", это "железо" нужно продать, убедив покупателя что купив NooLite он не встретит трудностей с внедрением и настройкой! Чтение документации на MTRF-64 и знакомство с программой nooLite_ONE меня в этом не убедили.

Что ж, определились, будем использовать модуль MT1132. Подключаем Arduino к модулю в соответствии со схемой из документации.

Я использовал контактную макетную плату с набором проводов, это очень ускоряет монтаж. TX модуля подключаем к 10 пину а RX к 11 пину Arduino. Для первых экспериментов взял свой "боевой" китайский клон UNO, уже паленый, с усиленным стабилизатором питания (от него же будет питаться и MT1132), когда все заработало заменил UNO на NANO, его удобно разместить прямо на макетной плате. Для приема команд нам понадобится IR приемник. У меня нашелся TSOP2836, если не ошибаюсь (пробовал и другие, разницы в работе особо не заметил, важно только соблюдать распиновку). Подключаем его в соответствии со схемой включения Vcc к 5В, GND к общему проводу а OUT к 2 пину Arduino.

Берем пример скетча из библиотеки ardunoo и исправляем в ней строку с выбором канала на котором будем работать с силовым блоком, выбираем 8-й канал.

 noo.channel(8);     // Let's command 2-th channel

Запускаем скетч, открываем Serial Monitor и введя в него букву "b" привязываем силовой блок. Теперь можно поиграться, вводя "n" зажигаем свет, "f" - гасим, "x"- меняем состояние и т.п. Убедились что все работет? Идем дальше.

Теперь нам понадобится стандартная библиотека IRremote. которая предназначена для упрощения работы с приёмом и передачей ИК сигналов. С помощью этой библиотеки будем принимать команды с пульта, и выводить их в окно Serial Monitor среды Arduino.

Берем любой IR-пульт (я взял от автомобильного трансмиттера).

Нажимая кнопки, в окне монитора последовательного порта видим соответствующие им коды, расшифрованные arduino. Я не знаю коды всех ли пультов сможет расшифровать библиотека IRremote, но всегда можно что-то подобрать, что по командам не будет пересекаться с устройствами в доме.

Я выбрал три кнопки и решил что одна из них будет включать свет, вторая выключать, а третья - менять состояние.

Вписываем коды выбранных кнопок для вызова функций noo.on(), noo.off() и noo.onoff(). При желании можно дописать другие функции и коды.

Проверяем работу от пульта. Свет включается, выключается и переключается, все как и было задумано. Также сохранилось управление, отправкой буквы в серийный порт (мне это не нужно, но не мешает).

Теперь переходим к управлению с помощью голосового помощника Алиса. Запускаем Яндекс, переходим в раздел устройства.

и выбираем Умный пульт Яндекс (его я установил раньше и планирую использовать и с другими устройствами, имеющими IR-порт). Нажимаем кнопку "Добавить устройство". Выбираем "Настроить вручную".

Вводим название устройства (имеется ввиду наше устройство), я назвал его "На полке". Название устройства нужно выбирать несложное и легкопроизносимое, иначе Алиса будет ошибаться и неправильно распознавать это название, что сделает ввод команд затруднительным.

Дальше производим обучение пульта. Нажимаем "Добавить команду".

Задаем голосовую команду, выбирая из предложенных вариантов или пишем свою. Следуя подсказкам берем пульт.

и нажимаем кнопку, сигнал которой хотим записать в соответствии с выбранной командой.

Так последовательно записываем все команды для выбранных кнопок.

Теперь среди устройств появилось "На полке"

и пульт управления к нему из созданных команд.

Также есть вкладка "Голосовые команды" с подсказками.

Проверяем. Подаем команду из подсказки. Работает, задержки почти нет.

Я пока не планирую пока использовать управление системой NooLite через умный пульт Яндекса на постоянной основе, мне было интересно проверить такую возможность, поэтому я не изготавливал печатной платы и не приводил то что у меня получилось к виду законченного изделия. Пока все выглядит вот так.

Но при желании Arduino и модуль МТ1132 можно разместить в пластиковый корпус, прозрачный для инфракрасных лучей. IR-приемник очень чувствительный а Яндекс-пульт посылает мощный сигнал, поэтому располагать пульт и приемник соосно в прямой видимости не понадобится. При необходимости можно будет добавить еще один или несколько IR-приемников подключив их или паралельно или каждый к отдельному пину Arduino. Но пока и так все работает отлично.

Подведу итог: идея работает, все просто и наглядно. Освещением (или любой другой нагрузкой) можно управлять помощью:

  1. компьютера через Serial Monitor;

  2. пульта от любой бытовой техники;

  3. пульта умного дома Яндекс;

  4. голосового помощника Алиса на смартфоне, компьютере или колонке.

Исходники

Ссылка на библиотеку ardunoo

Библиотека IRemote

Программа от zhum c моей вставкой:

/*Let you connect MT1132 to your arduino like this:+---------+               +------------+| MT1132  +-(RX)-----(11)-+ Tx Arduino ||         +-(TX)-----(10)-+ Rx         ||         |               |            |*/#include <SoftwareSerial.h>#include <ardunoo.h>#include <IRremote.h>#define RXpin 10#define TXpin 11IRrecv irrecv(2); // указываем вывод, к которому подключен приемникdecode_results results;ArduNoo noo(RXpin,TXpin);void setup(){  Serial.begin(9600);  irrecv.enableIRIn(); // запускаем прием  noo.channel(8);     // Let's command 8-th channel    // ...}void loop(){  int r;  r=Serial.read();  if(r<='9' && r>='0'){ // change channel    noo.channel(r-'0');    return;  }  switch(r){  case 'n': //on    noo.on();    break;  case 'f': //off    noo.off();    break;  case 'x': // toggle    noo.onoff();    break;  case 'c': //print current channel    Serial.print(noo.channel());    break;  case 'b': //bind    noo.bind();    break;  case 'u': //unbind    noo.unbind();    break;  case '+':    noo.slow_on();    break;  case '-':    noo.slow_off();    break;  case '!':    noo.slow_onoff();    break;  case 'r': // record scene!    noo.record_scene();    break;  case 'R': // run scene!    noo.run_scene();    break;  case 's': // toggle 3-rd channel    noo.onoff();    break;  }    if ( irrecv.decode( &results )) { // если данные пришли    Serial.println( results.value ); // печатаем данные в Serial Monitor    if (results.value == 16753245)  //код кнопки, выбранной для выключения   {           noo.off();    //выключаем свет        }    if (results.value == 16769565)  //код кнопки, выбранной для включения   {      noo.on(); //включаем свет           }   if (results.value == 16736925)  //код кнопки, выбранной для изменения состояния      {           noo.onoff();   //меняем текущее состояние света         }    irrecv.resume(); // принимаем следующую команду  }}

Если кому-нибудь понравится - пользуйтесь.

Подробнее..

Категории

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

  • Имя: Макс
    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