Оглавление Идея Режимы Железо Важное замечание История разработки ПО Использование и неожиданные применения Нереализованные идеи Выводы Светящийся шар с выбором цвета вращением (поворотом шара). Всё остальное крутится вокруг этой идеи. Ещё шар реагирует на касание, хотя правильнее будет сказать: на накрытие, но об этом позже. Название: Лайти (Lighty). Одно видео лучше тысячи символов. Есть 4 режима:  выбор цвета, пульт управления, цветомузыка и плавная смена цветов. Переключение режимов тоже вращением, но в перевёрнутом состоянии. Для каждого режима свой цветной сектор. После перехода на другой сектор, начинается плавное затухание, в процессе которого можно передумать и выбрать другой режим. Крутим шар - меняется цвет свечения. Кладём ладонь — управляем яркостью: если просто прикоснуться ладонью, то яркость увеличивается, если накрыть — уменьшается. Максимальная яркость обозначается белой вспышкой. Представлен на первом видео статьи. Например телевизором, но в моём случае компом (на видео телевизор подключён к компьютеру). Можно регулировать громкость: крутим против часовой стрелки — уменьшается, по часовой — увеличивается. Можно делать play / pause: касаемся и немного задерживаем ладонь на шаре до белой вспышки. Реагирует на звуки, мигает под музыку. На видео другой корпус, с ним этот и следующий режимы красивее (смотреть со звуком). C  переходом одних в другие. Скорость перетекания цветов задаётся углом поворота. На маленькой (⌀ 43 мм) круглой платке: 3 RGB светодиода + драйвер для них (MAX6967) магнитометр и акселерометр LSM303DLHC для определения направления, угла наклона и т. д. оптический датчик приближения VCNL4000 используется для управления яркостью микрофон и усилитель MAX9814 для цветомузыки micro USB для связи с PC и зарядки LiPo аккумулятор (приклеивается к плате с обратной стороны) и контроллер заряда LM3658SD микроконтроллер STM32F103T8 ну и по мелочи: линейный стабилизатор с низким падением напряжения LP2981AIM5-3.3, диоды, маленький кварц, USBLC6-2SC6 для защиты USB  Плата приклеена двусторонним скотчем на основание из оргстекла, которое вставляется в матовый стеклянный шар (плафон от светильника). Устройство (плата и ПО) было разработано и сделано 11 лет назад. Одиннадцать, Карл! (мем тех лет). Все основные функции были реализованы, но не всё доведено до ума: после пары месяцев неспешной работы над прошивкой в свободное время энтузиазм иссяк, да и появились другие проекты. И вот, недавно, попалась статья про сезон DIY и я решил, если не расскажу про Лайти сейчас, то не расскажу уже никогда. Нашёл всё железо, разобрался в исходниках, наснимал фото / видео. Обращаю внимание, что вся компонентная база уже устарела и сейчас я бы многое сделал по другому (цифровой MEMS микрофон на I2S, адресные светодиоды). И так как всё это делалось для фана, я не задавался вопросами экономической целесообразности применения той или иной микросхемы, использовал то, с чем хотелось поиграться. Я всегда питал слабость ко всяким светящимся штукам. В детстве пробовал делать разную цветомузыку и ещё тогда понял, что главное в ней это экран (рассеиватель). Когда мне на глаза попался стеклянный матовый плафон от настенного светильника, я понял — оно! Первые же опыты показали, что такой плафон красиво рассеивает свет, а ещё он очень приятный тактильно, его приятно трогать. Есть и минус: всё таки это стекло, поэтому нужно обращаться крайне аккуратно. Прототип был сделан под этот плафон и так как хотелось чтобы снизу ничего  не выпирало, чтобы шар оставался шаром насколько это возможно, я решил сделать круглую плату которая поместится в отверстие плафона. Поставил только один сверх яркий 3W RGB светодиод без драйвера, просто на транзисторах с мощными резисторами (большая часть энергии уходила на их нагрев, а не на свечение). ATmega8 под ним, а магнитометр с обратной стороны платы. Микрофон и LM358 для цветомузыки. Не было ни аккумулятора, ни USB, а питалось всё от внешнего БП. Плата крепилась к основанию из оргстекла на винтах, а само основание держалось в плафоне на распорках. Прототип подтвердил жизнеспособность идеи, но стало очевидно что провод питания сильно мешает и нужен аккумулятор. Ещё, я понял что такой яркий светодиод ни к чему, и в итоге разработал новую плату, в которой сделал всё по другому. Так получился Lighty 1.0, улучшенный и расширенный. Использовал тот же плафон и основание, что и для прототипа. Появилось много нового, например VCNL4000. Это ИК датчик приближения, может измерять расстояние до 20 см и общую освещенность. В случае со стеклянным плафоном, расстояние до стекла уже на грани максимума измерений. К тому же, стекло шара ослабляет ИК излучение, поэтому измерять расстояние, например от руки до шара, получается плохо. Но я заметил, что значение приближенности меняется в зависимости от того накрыт ли шар рукой или нет. Меняется оно не сильно, но вполне достаточно для грубого измерения степени накрытия в процентах. Это я и применил для регулировки яркости: касаемся (немного накрываем) — яркость увеличивается, кладём всю ладонь (накрываем сильнее) — яркость уменьшается. Так как мне хотелось цветомузыку получше (я конечно понимал что это бестолковая фигня, которая надоедает через 2 минуты, но бывает что хочется странного), то я поставил MAX9814 в качестве усилителя. Благодаря AGC (АРУ), усиление автоматически подстраивается под уровень звука. Аккумулятор привнёс автономность и удобство. Старался разместить его так чтобы не сильно увеличивать габариты. Это позволяет встраивать платку в разные места и корпуса. Самая глупая — забыл добавить резисторный делитель для контроля напряжения аккумулятора (это в автономном то устройстве!). Отказался от контроля LM3658SD через линию LM3658_ENABLE и использовал её для измерения напряжения аккумулятора (добавил 2 выводных резистора навесным монтажом). Ещё забыл сделать линию управления MAX9814: на плате пин !SHDN подключён к питанию. Оказалось, что MAX9814 потребляет довольно много тока, что негативно сказывается на времени работы от аккумулятора, особенно это заметно в спящем режиме МК (читать даташит на усилитель надо было внимательнее). Пришлось порезать дорожки, припаяться к via (переходному отверстию) и кинуть проводок на заботливо разведённый неиспользуемый выход микроконтроллера. Теперь, когда не нужен звук с микрофона, можно выключать усилитель. После исправления ошибок добавил новую функцию: управление по ИК каналу. На тот момент у меня уже довольно давно применялся USB-HID IR приёмник (тоже самодельный) и какой-то ненужный пульт. Приёмник эмулирует клавиатуру и при получении сигнала с кодом кнопки PAUSE отправляет по USB виртуальное нажатие клавиши пробел. Ещё есть управление громкостью. Этот пульт я и заменил: Лайти может слать коды трёх кнопок пульта (PAUSE, VOLUME+, VOLUME-).  Добавил ещё 2 выводных резистора, транзистор, ИК светодиод и нашел ещё один свободный и легкодоступный пин STM32F103 с поддержкой выхода аппаратного таймера с PWM. В режиме ИК пульта важна энергоэффективность. Шар стоит на столе целыми днями и должен быть всегда готовым к управлению, без необходимости предварительного включения. Поэтому в этом режиме МК большую часть времени спит, включается от акселерометра когда шар крутят, передаёт ИК команды и засыпает снова. В таком режиме аккумулятора хватает на неделю. В целом, управление работает довольно надёжно: даже через матовое стекло ИК светодиод добивает несколько метров до приёмника, так как в импульсе через него фигачит неслабый ток. Стеклянный плафон слишком хорошо рассеивает и смешивает цвета от светодиодов: кажется что он там один, а не три. Поэтому в режимах цветомузыки и плавной смены цвета всё это превращается в цветную кашу.  Нашел другой корпус, пластиковый, с матовым рассеивателем. В нём свет от отдельных светодиодов не так сильно сливается и получаются классные световые пятна, что как раз и нужно для цветомузыки и плавного перетекания цвета. Под этот корпус был применён второй Лайти (собирал две платы одновременно). Кстати в нем датчик приближения работает как положено: можно измерять расстояние от руки до пластика. Проект на github Всё написано на C, без ОС (зря, было бы удобнее). В качестве IDE использовал широко популярный (в узких кругах) на тот момент CoIDE. Одной из основных задач была работа с LSM303DLHC. Он не даёт готовое направление (heading), его нужно высчитывать из значений напряжённости магнитного поля по осям XYZ. Данные по I2C читаются с помощью драйвера LSM303DLHC от ST. На просторах сети был найден алгоритм получения направления, который помимо магнитных данных, использует ещё и показания акселерометра: выполняет пересечение и нормализацию векторов ускорения и магнитного поля, рассчитывает направление в градусах.  Алгоритм предполагает наличие данных минимумов и максимумов значений напряженности магнитного полей по осям (m_min, m_max). Для этого есть калибровка с сохранением результатов во флеш память. Если при старте, сохранённых данных не найдено, то запускается процедура калибровки: нужно вращать устройство по всем осям пока не прекратятся вспышки (если найдено новое минимальное или максимальное значение светодиоды вспыхивают). Калибровку обязательно делать с той же конфигурацией металлических материалов (например крепёжные винты) которая будет присутствовать в дальнейшем. Если же калибровка не удалась или нужно её повторить, то всегда можно запустить её снова, включив Лайти в перевёрнутом состоянии. Для плавности изменения цвета, полученные значения направлений нужно усреднять. Но просто так усреднять углы не получиться, ведь у нас  замкнутая шкала (0..359) и в районе перехода через ноль будут проблемы. Нашел следующее решение: каждый угол (направление) перевести в координаты x, y, потом отдельно усреднить x и y компоненты векторов и восстановить угол обратно.  Помимо  направления, из LSM303DLHC считываются данные акселерометра, чтобы получить отклонение от вертикальной оси и понять примерную  ориентацию в пространстве: например перевёрнут ли шар или нет. Наконец, линии прерывания (INT1 / INT2) LSM303DLHC задействованы для пробуждения в случае движения (вибрации) — это для режима пульта управления. Акселерометр настраивается по I2C таким образом, что в случае превышения порогового значения он дёргает линию INT1 и выводит МК из сна по EXTI прерыванию. Полученное значение направления (вращение по вертикальной оси) выступает в качестве Hue компоненты HSV цветового пространства, которое используется повсеместно в прошивке. Накрытие ладонью определяет яркость — Value. Насыщенность цвета (Saturation) регулируется отклонением от вертикали: в основном режиме берём шар в руку и наклоняем его. Это не очень нужно, так как по умолчанию она и так максимальна, а её уменьшение делает цвет менее насыщенным, ближе к белому, что не так красиво. Так как для светодиодов нужны значения в RGB пространстве, нужно преобразование.  Светодиодами управляет 10 канальный MAX6967, на каждый из трёх светодиодов нужно 3 канала, один остался свободным. Разрешение каждого канала 8 бит (255 значений яркости). Для передачи данных используется SPI. Используя данные приближенности (proximity) от VCNL4000, с помощью простейшего масштабирования рассчитывается степень накрытия шара. Для этого, нужно знать значение  приближенности соответствующее 0% (когда рука не накрывает шар) и значение при накрытии рукой (это будет 100%).  Для получения этих значений нужна калибровка. Она выполняется сразу после калибровки LSM303DLHC: сначала определяем 0% (ProximityOffset), потом ждём накрытия ладонью и сохраняем максимальное значение (в коде вместо максимального значения сохраняется уже рассчитанный коэффициент для пересчета - ProximityMaxCoverCoeff). VCNL4000 позволяет получить текущий уровень освещенности, но на данный момент это не используется: можно сделать автоматическую регулировку яркости. Сначала усиленный сигнал микрофона оцифровывается АЦП микроконтроллера, результаты читаются без использования DMA (а надо бы). Затем выполняется FFT (БПФ) на 64 точки. Использовал STM32F10x_DSP_Lib от ST - пригодилась функции cr4_fft_64_stm32(), для которой нужно соблюдать специальный формат комплексных чисел (вещественная и мнимая части в одной переменной, мнимая часть равна нулю).  Полученный спектр на 32 частоты (нам нужна только первая половина массива готовых амплитуд) усредняется и распределяется по трём светодиодам (9 каналов) в соответствии с шаблоном, полученным опытным путём, с помощью программы для ПК. Шаблон это 9 переменных uint32_t (по числу используемых каналов MAX6967), каждый бит в переменной указывает надо ли этому каналу реагировать на ту или иную частоту. Да да, для отладки, была написана программа на C# и реализован обмен данными по USB: STM32 реализует интерфейс HID устройства с одним endpoint (буфер на 64 байта). В программе можно посмотреть показания всех датчиков, задать любой цвет для любого светодиода и посмотреть визуализацию аудио спектра. Лайти - это всего лишь игрушка сделанная по фану и как это часто бывает с игрушками, она надоедает. Тем не менее, несколько месяцев он красиво стоял на столе, светил и использовался для регулировки громкости при просмотре всякого. Потом, прошло много лет, оба сделанных Лайти затерялись в дальних углах. Но несколько лет назад было найдено новое применение обоим: первый стал ёлкой а второй котиком → детским ночником. Микро ёлка из икеи, навесил на неё гирлянды с микро лампочками, Лайти с более ёмким аккумулятором разместился в горшке. Светодиоды были выпаяны, а вместо них подключил гирлянды. Добавил новые функции: циклическое переключение режимов по двойному тапу, например двойном ударе по столу на котором стоит горшок: не переворачивать же ёлку с шариками чтобы переключить режим. Вместо ИК пульта, новый режим в котором можно выбрать только одну гирлянду. И последняя модификация, специально для дочки: включение при касании волшебной палочкой звезды на макушке (магнит вклеенный в палочку, геркон в звезде, чуть кода и получается магия). Самый обычный детский ночник из магазина с ярким разноцветным светодиодом. Теперь там Лайти с очень простым функционалом в прошивке: включение по кнопке (опять спящий режим МК) и самое главное: таймер автоматического отключения через полчаса с постепенным угасанием приятного теплого света. В основной прошивке активны 4 режима, хотя при выборе их больше: 2 слота так и остались пустыми. Мне казалось что 6 режимов я точно сделаю, но руки так и не дошли. Ниже несколько идей из списка 10 летней давности. Магический шар (спроси у вселенной)  - трясешь и получаешь ответ красным / зеленым цветом. Режим работы от компьютера по USB: индикация уведомлений, событий и т.д. Режим "Свеча" — имитация огня и задувание посредством микрофона. Хоть я и не сделал следующую версию платы с исправлениями и доработками, я получил удовольствие от придумывания разных идей и разработки как железа, так и ПО. Испытываешь прекрасное чувство удовлетворённости когда получается воплотить идеи в что‑то материальное и работоспособное. Получил много опыта, который реально применял позже: при разработке других, «серьёзных» и «полезных» устройств с цифровым компасом и аудио усилителем. Надеюсь что мой опыт, идеи и решения покажутся читателям любопытными, а может даже полезными. И ещё: рассказывайте о своих проектах! Ведь я ещё тогда, 11 лет назад, хотел рассказать о проекте на хабре, но не делал этого, так как стремился сначала довести всё до идеала. Сейчас понимаю, что если бы я уже тогда написал статью, то возможно, именно это и помогло бы сделать следующую версию. Так что всё должно быть в своё время и в стремлении к идеалу надо знать меру. P.S.: Кому было интересно, подписывайтесь на мой телеграм канал. Шутка, нет у меня канала.