Реверс-инжиниринг мерцающего светодиода

в 18:24, , рубрики: diy или сделай сам, reverse engineering, обратная разработка, светодиод, свеча, Электроника для начинающих

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

Конечно, самый интересный вопрос — как они работают? Учитывая, что стоят они буквально по несколько центов за штуку, там внутри не может быть какой-то дорогой электроники. В связи с этим возникает еще один вопрос: правда ли эти светодиоды хуже, чем многочисленные «свечи» на микроконтроллерах, схем которых полно в интернете?

Реверс инжиниринг мерцающего светодиода
Устройство относительно простое. В стандартном 5-миллиметровом корпусе размещены кристалл светодиода и микросхема, которая чуть больше первого по размеру. Схема контроллера соединена как с положительным, так и с отрицательным выводами. Третьей перемычкой к ней подключен анод светодиода, в то время как катодом он «сидит» на отрицательном выводе.

В блоге Evil Mad Scientist недавно был рассказ о похожих светодиодах. Там было показано, как они «поют», если преобразовать изменения яркости в звук. А также — как с их помощью управлять более мощным диодом. Подобные трюки основаны на том, что светодиод потребляет больший ток в те моменты, когда контроллер зажигает его ярче. Обычный светодиод, включенный последовательно с мерцающим, показывает очень похожие изменения яркости. Иными словами, падение напряжения на добавочном резисторе изменяется пропорционально яркости.

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

Реверс инжиниринг мерцающего светодиода
На диаграмме выше показаны изменения яркости диода в течение примерно минуты, записанные с частотой выборки 1 МГц. Заметны интервалы, когда светодиод непрерывно включен, и периоды, когда его яркость каким-то образом модулируется. Светодиод никогда не выключается надолго. Это разумно, ведь настоящая свеча тоже ярко светит большую часть времени, снижая яркость на короткие периоды мерцания.

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

Любопытно, что частота сигнала — примерно 440 Гц, как у стандартного камертона (нота Ля первой октавы — прим. перев.). Совпадение? Или разработчик просто взял генератор из какой-то музыкальной схемы? Так что есть доля правды в рассказах о «музыкальности» этих светодиодов. Каждый «кадр» постоянной яркости составляет ровно 32 такта и длится около 72 мс. Это соответствует 13-14 кадрам в секунду.

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

Реверс инжиниринг мерцающего светодиода
График яркости в зависимости от времени наводит на некоторые мысли: изменения яркости случайны, дискретны и имеют неравномерное распределение. Кажется, существуют 16 уровней яркости, низшие 4 из которых используются очень редко. Им соответствуют только 13 из 3600 отсчетов.

Реверс инжиниринг мерцающего светодиода
Постороение гистограммы открывает всю картину: фактически используется только 12 уровней яркости. Ровно половина кадров имеет максимальную яркость, остальные значения распределены примерно поровну.

Как это может быть реализовано на аппаратном уровне? Вполне вероятно, используется генератор равномерно распределенных случайных чисел, которые пропускают через простую функцию-формирователь. Для того распределения, которое мы наблюдаем, требуется как минимум 12x2=24 дискретных уровня. Половина из них отображаются в один. Это весьма любопытно, так как генератор, скорее всего, выдает двоичные числа. Наиболее логичной была бы разрядность числа 5 бит, а это 32 состояния. Отобразить 32-уровневую дискретную случайную величину в 24 уровня, не изменив распределения, не так просто, как кажется. Не забываем также, что это совсем не критичная схема, и у разработчика, вероятно, не было много времени на красивое решение. Поэтому он применил самое простое, своего рода хак.

Единственный простой способ, что приходит на ум — просто отбрасывать неподходящие значения и брать следующее случайное число. Нежелательные значения можно легко отделить по битовой маске. Так как схема синхронная, есть только конечное число попыток, пока не начнется следующий кадр. Если контроллер не уложился в заданное количество попыток, он застрянет на «неправильном» значении. Помните редкие выбросы на графике яркости?

Реализация на ANSI-C могла бы выглядеть так:

    char attempts=0;
    char out;
    while(attempts++<MAX_ATTEMPTS) 
    { 
        out=RAND()&0x1f; 
        if ((out&0x0c)!=0) break; // отбрасываем значения, у которых 2-й и 3-й биты нулевые 
    } 
    if (out>15) out=15; // верхняя половина диапазона соответствует максимальной яркости

Можно узнать, сколько делается попыток? По статистике, доля a=0,25 всех чисел должн быть отброшена и сгенерирована заново. Вероятность того, что за n попыток не будет выбрано «правильное» число, равна an.

   n=1      0,25
   n=2      0,0625
   n=3      0,015625
   n=4      0,003906

Доля аномально низких уровней яркости составляет 13/3600=0,0036, что хорошо совпадает с вариантом n=4. Таким образом, MAX_ATTEMPTS==4.

Обратите внимание, что более простым решением было бы просто использовать значение из предыдущего кадра, если встретилось недопустимое число. Этот вариант можно было бы исключить, исходя из автокорреляции (см. ниже). Наиболее же простое, вероятно, решение — изменить схему ШИМ — не было здесь использовано.

Последний кусочек головоломки — это сам генератор случайных чисел. Типичным способом генерации случайных последовательностей в цифровых схемах является применение сдвиговых регистров с линейной обратной связью. Такой регистр выдает псевдослучайную битовую последовательность, которая повторится не позже, чем через 2x-1 тактов, где x — разрядность регистра. Одной из особенностей таких последовательностей (и хороших псевдослучайных последовательностей в целом) является то, что их автокорреляционная функция равна единице только в точке 0 и в координатах, кратных длине последовательности. Во всех остальных интервалах она нулевая.

Реверс инжиниринг мерцающего светодиода
Я рассчитал автокорреляцию всей последовательности значений. Самоподобия не было найдено вплоть до 3500 кадров (на графике выше показано только 1200), что означает уникальность мерцания на протяжении по меньшей мере 4 минут. Неясно, наблюдалось ли повторение последовательности дальше или логический анализатор автора просто не позволял записывать дольше — прим. перев. Поскольку на каждый кадр нужно как минимум 5 бит случайных данных (а учитывая механизм отбрасывания нежелательных чисел — еще больше), псевдослучайная последовательность имеет длину по меньшей мере 17500 бит. Для этого потребуется регистр разрядности не менее 17, либо настоящий аппаратный генератор случайных чисел. В любом случае, интересно, как много внимания при разработке уделили тому, чтобы картина мерцания не повторялась.

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

Каков же лучший алгоритм мерцания? Можно ли улучшить этот?

Дополнение: Я наконец нашел время написать эмулятор. Написанная на ANSI-C программа, эмулирующая поведение этого светодиода, здесь. Код написан под AVR, но его легко портировать под любой другой контроллер. Репозиторий на Гитхабе содержит все данные и исходные коды, использованные в процессе реверс-инжиниринга светодиода.

Автор: Ocelot

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js