ARDUINO Возможно ли декодировать протокол RGB ленты WS2812 с помощью Arduino?

DAsh

✩✩✩✩✩✩✩
16 Июн 2020
6
0
Здравствуйте, возникла необходимость создать что-то вроде прокси между источником сигнала для WS2812 ленты и самой лентой.
После декодирования планирую производить небольшие изменения сигнала, такие как изменения яркости или вырезание конкретного куска из ленты, и ретранслировать дальше.

Однако, первый эксперимент дал не утешительный результат.
Собрал вот такую схему:
MVIMG_20200616_125617_2.jpg
Arduino Pro Mini выступает в роли источника сигнала. Сигнал подается на 6 пин.
Вот код (проверял на куске ленты, все работает):
C++:
#include "FastLED.h"

#define LED_COUNT 5
#define LED_PIN 6

CRGB strip[LED_COUNT];

void setup()
{
  FastLED.addLeds<WS2812B, LED_PIN, RGB>(strip, LED_COUNT);
}

void loop()
{
  for (int i = 0; i < LED_COUNT; i++)
  {
    strip[i] = CRGB::Red;
  }
  FastLED.show();
  delay(2000);
}
Собственно в коде просто происходит обновление ленты каждые 2 секунды. Длина ленты 5 светодиодов.

Arduino Uno выступает в роли приемника сигнала. Сигнал принимается на 3 пин через аппаратные прерывания.
Вот код:
C++:
#define PIN_IN 3

volatile int count;

void setup() {
  count = 0;
  attachInterrupt(digitalPinToInterrupt(PIN_IN), inChanged, CHANGE);
  Serial.begin(9600);
}

void loop() {
  delay(1000);
  int currentCount = count;
  Serial.print("Count:");
  Serial.println(currentCount);
  count = 0;
}

void inChanged() {
  count += 1;
}
Код просто подсчитывает количество изменений сигнала на 3 пине за 1 секунду и выводит лог через Serial порт.

Вот что выводится в логах:
13:45:12.043 -> Count:26
13:45:13.033 -> Count:0
13:45:14.016 -> Count:27
13:45:15.049 -> Count:0
13:45:16.035 -> Count:26
13:45:17.026 -> Count:0
13:45:18.058 -> Count:26
13:45:19.051 -> Count:0
13:45:20.039 -> Count:26
Для передачи сигнала для 5 светодиодов нужно ровно 120 бит, а значит 240 изменений сигнала. Из чего можно предположить, что ардуна не справляется с такой нагрузкой так как, в случае с данным примером, Arduino смогла зарегистрировать лишь 26 случаев.

Собственно вопрос.
Реально ли декодировать WS2812 сигнал исключительно средствами Arduino? Возможно это я делаю что-то не так.
Или же может быть есть какие либо иные подходы (возможно даже готовые модули) для подобных задач?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,242
1,297
Москва
Я не пробовал, но ардуинка может определять частоту достаточно шустрых сигналов. Скорее всего фастлед куда шустрее )
https://www.drive2.ru/b/1646666/ , есть раздел "протокол"
Время передачи одного бита 1.25 мкс, т.е. скорость передачи 800 кбит/с.
 
  • Лойс +1
Реакции: DAsh

DAsh

✩✩✩✩✩✩✩
16 Июн 2020
6
0
Наткнулся вот на этот пост на форуме Arduino

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

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

Старик Похабыч

★★★★★★★
14 Авг 2019
4,242
1,297
Москва
Ну вот тут я определял кол-во импульсов на 2-ом пине. с 8-го. Для теста надо соединть пин 2 и пин 8. Далее подается в setup-е подается сигнал и идет отлов колебаний и вывод результата после 1 сек. простоя.
ЗЫ. да, у меня там частота стоит 12кГц, а тут 800...видимо реально только аппаратно. н
 

Вложения

DAsh

✩✩✩✩✩✩✩
16 Июн 2020
6
0
Написал вот такой скетч:
C++:
#define PIN_IN 3
#define PIN_OUT 11

void setup() {
  pinMode (PIN_IN, INPUT);
  pinMode (PIN_OUT, OUTPUT);
  noInterrupts();
}

void loop() {
  PORTB = PIND;
}
Белый цвет передается. Остальные цвета нет, даже черный. Причем цвет постоянно меняется.
По всей видимости ноль получается не достаточно короткий.

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

kalobyte

★★★✩✩✩✩
1 Янв 2020
724
148
код неправильный
считывать надо не количество импульсов, там 1 и 0 кодируются разной длительностью сигнала шим
для этого надо использовать таймер

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

DAsh

✩✩✩✩✩✩✩
16 Июн 2020
6
0
код неправильный
считывать надо не количество импульсов, там 1 и 0 кодируются разной длительностью сигнала шим
для этого надо использовать таймер
Данный код лишь тест производительности. По сути он просто передает сигнал с пинов 0-5 на пины 8-13.
На счет 0 и 1 я знаю, собственно об этом я и написал. Сигнал для 0 получается слишком длинным при ретранслировании и чип воспринимает его как 1.

непонятна задача, зачем такой изврат делать
Собственно, чего именно не понятно? Задачу, вроде, я в начале ясно расписал.
Зачем: Есть материнская плата с одним выходом для адресной RGB ленты. Есть корпус с RGB подсветкой передней панели и прозрачной боковой крышкой.
Подсветка имеет 2 недостатка:
1) Она не поддерживает синхронизацию с материнской платой. У нее свой собственный контроллер который управляется кнопкой на корпусе.
2) Светит она так ярко что немного выбешивает.

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

Что я хочу получить в итоге: Не бесящую Plug & Play подсветку корпуса, без необходимости устанавливать дополнительные драйвера на компьютер, которая синхронизируется с материнской платой через RGB выход и подстраивается по кнопке на корпусе.

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

kalobyte

★★★✩✩✩✩
1 Янв 2020
724
148
дык не используй подсветку в плате
сделай свой контроллер

я видел платы с выходом для адресных диодов и еще там на самой плате диоды подсвечивают радиаторы
они вроде адресные тоже или просто ргб?

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

DAsh

✩✩✩✩✩✩✩
16 Июн 2020
6
0
дык не используй подсветку в плате
сделай свой контроллер
Спасибо за совет, но он не удовлетворяет требованиям технического задания ;)
А именно: ... которая синхронизируется с материнской платой через RGB выход ...

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

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

В общем, давайте не будем отклоняться от темы. Основной вопрос топика заключается в декодировании протокола WS2812B.
И как мне видится, это скорее всего возможно. Если не на ATMega328P так на каком нибудь другом чипе по шустрей.
Так что для меня это теперь уже принципиальный вопрос, и мне сейчас важнее добиться декодирования протокола, нежели сделать подсветку для компа.

Как появится свободное время, займусь написанием скетча. О результатах обязательно отпишусь. Спасибо всем кто писал по делу.
 

kalobyte

★★★✩✩✩✩
1 Янв 2020
724
148
на фоурме ардуины пишут
We had a thread in here about a month or two ago that was basically asking the same thing. The consensus was you could not do it with a Uno you needed a faster Arduino and no one had done it yet.

так что не понтянет она
да и я так и не понял, если ты настраиваеш в софте от платы встроеные диоды, то там можно ввести бесконечное число диодов и дальше и все это будет как одна лента типа?
тут проще наверное переписать софт для управления этими диодами
 

DAsh

✩✩✩✩✩✩✩
16 Июн 2020
6
0
В общем, после нескольких экспериментов могу с уверенностью сказать, что ни Arduino pro mini(ATMega328P) ни Wemos D1 mini(ESP8266) не могут справиться с этой задачей без хардварных доработок.

Для чтения пинов в ATMega328P использовал PINB

Для чтения пинов в ESP8266 использовал вот это
C++:
#define PIN_IN_MASK 0x0020 // GPIO5 bit mask
#define GPIO_IN ((volatile uint32_t*) 0x60000318)
#define READ_PIN_IN (*GPIO_IN & PIN_IN_MASK)

Пока искал другие решения набрел на мысль использовать сдвиговый регистр для чтения одного байта за раз.
В случае с Arduino за два раза, вот как-то так:
C++:
byte data = (PIND & b11000000) | PINB
Выходы регистра должны быть подключены к пинам 6-13.

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