Topic: Управление WS2812
Есть такие замечательные светодиоды с контроллером WS2812. Пытаюсь управлять ими через Rеmote_XY и Bluetooth соединение.
Если отправлять некие статические коды, например, с RGB-круга, то это проходит на ура.
Но если я запускаю какие-то эффекты, когда цвето постоянно меняется, то связь умирает наглухо.
BT подключен через библиотеку softwarserial.
Для управления WS2812 я использую библиотеку iarduino_NeoPixel. Как и многие похожие, она использует массив внутри ардуино для установки цвета, а потом с помощью команды write закидывает этот массив в ленту светодиодов. Вот эта команда write написана на ассемблере и еще отключает все прерывания. Т.е. поджирает под себя все ресурсы.
Однако у меня всего 14 светодиодов. Вот что написано про ws2812.
Команды управления подаются пакетами по 3 байта, по одному для каждого из трёх цветов. Между пакетами идет пауза длительностью 50 мкс, пауза более 100 мкс означает конец передачи.
Длительность любого бита – 1,25 мкс. Бит «1«кодируется импульсом длительностью 0,8 мкс и паузой в 0,45 мкс. Бит «0«– 0,4 и 0,85 мкс. Возможны расхождения по времени до 150 нс. Такой пакет должен быть отправлен для каждого пикселя в светодиодной ленте.
Таким образом мне надо передать 14*3*8 = 336 бит. Каждый бит 1,25 мкс. 336*1.25 = 420 мкс. Т.е. не так уж и много. Но, как я уже писал, связь пропадает. Т.е. устройство не откликается на команды с телефона.
В общем я чего-то не понимаю. Помогите разобраться, плз.
Ниже привожу код программы. Главная проблема при RemoteXY.select_Mode = 2.
#define REMOTEXY_MODE__SOFTSERIAL
#include <SoftwareSerial.h>
#include <RemoteXY.h>
// настройки соединения
#define REMOTEXY_SERIAL_RX 9
#define REMOTEXY_SERIAL_TX 10
#define REMOTEXY_SERIAL_SPEED 9600
// конфигурация интерфейса
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
{ 255,5,0,17,0,51,0,8,161,1,
6,0,10,52,43,43,2,26,2,1,
2,2,22,11,191,26,93,31,79,78,
0,79,70,70,0,3,131,16,29,31,
11,164,26,67,1,2,15,59,10,107,
161,16,65,42,45,3,9,9 };
// структура определяет все переменные вашего интерфейса управления
struct {
// input variable
uint8_t rgb_1_r; // =0..255 значение Красного цвета
uint8_t rgb_1_g; // =0..255 значение Зеленого цвета
uint8_t rgb_1_b; // =0..255 значение Синего цвета
uint8_t switch_on; // =1 если переключатель включен и =0 если отключен
uint8_t select_Mode; // =0 если переключатель в положении A, =1 если в положении B, =2 если в положении C, ...
// output variable
char text_Mode[16]; // =строка UTF8 оканчивающаяся нулем
uint8_t led_On_g; // =0..255 яркость зеленого цвета индикатора
// other variable
uint8_t connect_flag; // =1 if wire connected, else =0
} RemoteXY;
#pragma pack(pop)
/////////////////////////////////////////////
// END RemoteXY include //
/////////////////////////////////////////////
#define PIN_SWITCH_ON 13
uint8_t rgb_r = 0; // =0..255 значение Красного цвета
uint8_t rgb_g = 0; // =0..255 значение Зеленого цвета
uint8_t rgb_b = 0; // =0..255 значение Синего цвета
uint8_t rgb_bright = 255; // =0..255 значение Синего цвета
#define PIN 7
#define LED_NUMBER 14
#include <iarduino_NeoPixel.h> // Подключаем библиотеку iarduino_NeoPixel для работы со светодиодами NeoPixel
iarduino_NeoPixel led(PIN, LED_NUMBER ); // Объявляем объект LED указывая (№ вывода Arduino к которому подключены светодиоды NeoPixel, количество используемых светодиодов)
unsigned long DiscoTime = 0;
void setup()
{
RemoteXY_Init ();
pinMode (PIN_SWITCH_ON, OUTPUT);
led.begin();
clrColor();
RemoteXY.select_Mode = 0;
Serial.begin(9600);
Serial.println("Candel begin...");
}
void loop()
{
RemoteXY_Handler ();
digitalWrite(PIN_SWITCH_ON, (RemoteXY.switch_on==0)?LOW:HIGH);
RemoteXY.led_On_g = 200*RemoteXY.switch_on;
if(!RemoteXY.switch_on){
//Состояние ВЫКЛ
strcpy (RemoteXY.text_Mode, "Candel off");
clrColor();
return;
}
//Состояние ВКЛ
switch (RemoteXY.select_Mode){
case 0:
strcpy (RemoteXY.text_Mode, "Light");
//clrColor();
rgb_r = 255;
rgb_g = 255;
rgb_b = 255;
setRGB(NeoPixelAll, 255, 255, 255);
break;
case 1:
strcpy (RemoteXY.text_Mode, "Color");
setColorFromDim();
break;
case 2:
strcpy (RemoteXY.text_Mode, "Discoteka");
ChangeColor();
break;
}
}
void setRGB(uint16_t NumPix, uint8_t rgbRed, uint8_t rgbGreen, uint8_t rgbBlue){
bool NeedWrite = false;
if(NumPix=NeoPixelAll){
for (uint16_t i=0; i<LED_NUMBER; i++){
if( (led.getPointer()[i+0] != rgbRed) || (led.getPointer()[i+1] != rgbGreen) || (led.getPointer()[i+2] != rgbBlue)) {
/*
Serial.print("setRGB(");
Serial.print(i,DEC);
Serial.print(") ");
Serial.print(led.getPointer()[i+0], DEC);
Serial.print(" ");
Serial.print(rgbRed, DEC);
Serial.print(",");
Serial.print(led.getPointer()[i+1], DEC);
Serial.print(" ");
Serial.print(rgbGreen, DEC);
Serial.print(",");
Serial.print(led.getPointer()[i+2], DEC);
Serial.print(" ");
Serial.println(rgbBlue, DEC);
*/
NeedWrite = true;
break;
}//if
} //for
}else{
if( (led.getPointer()[NumPix+0] != rgbRed) || (led.getPointer()[NumPix+1] != rgbGreen) || (led.getPointer()[NumPix+2] != rgbBlue)) {
/*
Serial.print("setRGB(");
Serial.print(NumPix,DEC);
Serial.print(") ");
Serial.print(led.getPointer()[NumPix+0], DEC);
Serial.print(" ");
Serial.print(rgbRed, DEC);
Serial.print(",");
Serial.print(led.getPointer()[NumPix+1], DEC);
Serial.print(" ");
Serial.print(rgbGreen, DEC);
Serial.print(",");
Serial.print(led.getPointer()[NumPix+2], DEC);
Serial.print(" ");
Serial.println(rgbBlue, DEC);
*/
NeedWrite = true;
}//if
}//else
if(NeedWrite){
//Serial.println("setRGB");
led.setColor(NumPix, byte(rgbRed), byte(rgbGreen), byte(rgbBlue)); // Устанавливаем цвет для светодиодов (номер,R,G,B)
led.write(); // Записываем
}
}
void setColorFromDim(){
if( (rgb_r != RemoteXY.rgb_1_r) || (rgb_g != RemoteXY.rgb_1_g) || (rgb_b != RemoteXY.rgb_1_b)) {
Serial.print("R: ");
Serial.print(RemoteXY.rgb_1_r, DEC);
Serial.print(" G: ");
Serial.print(RemoteXY.rgb_1_g, DEC);
Serial.print(" B: ");
Serial.println(RemoteXY.rgb_1_b, DEC);
rgb_r = RemoteXY.rgb_1_r;
rgb_g = RemoteXY.rgb_1_g;
rgb_b = RemoteXY.rgb_1_b;
setRGB(NeoPixelAll, byte(rgb_r), byte(rgb_g), byte(rgb_b)); // Устанавливаем цвет для всех светодиодов (все,R,G,B)
}
}
void clrColor(){
Serial.println("clrColor");
rgb_r = 0;
rgb_g = 0;
rgb_b = 0;
setRGB(NeoPixelAll, 0, 0, 0);
}
void ChangeColor(){
static uint8_t j; // Объявляем переменную для хранения значения сдвига спектра цветов для всех светодиодов (от 0 до 255)
uint8_t k; // Объявляем переменную для хранения положения сдвига спектра цвета для каждого светодиода на спектре j (зависит от количества светодиодов)
uint8_t r, g, b; // Объявляем переменную для хранения цветов RGB для каждого светодиода
const uint8_t z=50; // Определяем константу указывающую задержку в мс (чем выше значение, тем медленнее перелив цветов)
/*
j++; // Смещаем спектр цветов для всех светодиодов
for(uint16_t i=0; i<led.count(); i++){ // Проходим по всем светодиодам
k=((uint16_t)(i*256/led.count())+j); // Определяем положение очередного светодиода на смещённом спектре цветов
if(k<85) { b=0; r=k*3; g=255-r;}else // Перелив от зелёного к красному, через жёлтый
if(k<170){k-=85; g=0; b=k*3; r=255-b;}else // Перелив от красного к синему , через фиолетовый
{k-=170; r=0; g=k*3; b=255-g;} // Перелив от синего к зелёному, через голубой
led.setColor(i, r,g,b); // Устанавливаем выбранный цвет для очередного светодиода
} led.write(); // Записываем цвета всех светодиодов
delay(z); // Устанавливаем задержку
*/
unsigned long curTime = millis();
if(curTime - DiscoTime < z) return;
DiscoTime = curTime;
j++; // Смещаем спектр цветов для всех светодиодов
k=((uint16_t)(256/led.count())+j); // Определяем положение очередного светодиода на смещённом спектре цветов
if(k<85) { b=0; r=k*3; g=255-r;}else // Перелив от зелёного к красному, через жёлтый
if(k<170){k-=85; g=0; b=k*3; r=255-b;}else // Перелив от красного к синему , через фиолетовый
{k-=170; r=0; g=k*3; b=255-g;} // Перелив от синего к зелёному, через голубой
led.setColor(NeoPixelAll, r,g,b); // Устанавливаем выбранный цвет для очередного светодиода
led.write(); // Записываем цвета всех светодиодов
}