Глюки в WS2812B
- Войдите на сайт для отправки комментариев
Всем привет! Создаю один проект. В качестве индикации буду использовать адресные светодиоды WS2812B, 16 штук, которые создают визуальную шкалу. Код:
#include <Adafruit_NeoPixel.h> #define BLYNK_PRINT Serial #include <ESP8266WiFi.h> #include <BlynkSimpleEsp8266.h> char auth[] = "1f65de93e395467c9a2bab7f12886742"; char ssid[] = "DIR-615"; char pass[] = "forfrends"; #define LedPIN 13 // Pin D7 // On Trinket or Gemma, suggest changing this to 1 #define NUMPIXELS 16 // Popular NeoPixel ring size #define FanPin 13 // D7 int FanSpeed = 500; bool Ionithation = false; #define IonPin 2 // D8 #define Button 0 // D3 #define pin_A 14 // D5 #define pin_B 12 // D6 unsigned char encoder_A; unsigned char encoder_B; unsigned char encoder_A_prev=0; unsigned char encoder_B_prev=0; String input_string = ""; int Pow = 7; //Adafruit_NeoPixel pixels(NUMPIXELS, LedPIN, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LedPIN, NEO_GRB + NEO_KHZ800); void setup() { Serial.begin(9600); Blynk.begin(auth, ssid, pass); // You can also specify server: //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80); //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080); pinMode(pin_A, INPUT); pinMode(pin_B, INPUT); pinMode(Button, INPUT); digitalWrite(Button, HIGH); pinMode(IonPin, OUTPUT); digitalWrite(IonPin, LOW); pinMode(FanPin, OUTPUT); analogWrite(FanPin, FanSpeed); pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) pixels.show(); StripUpdate(); } BLYNK_READ(V0) { Blynk.virtualWrite(V0, Pow); } BLYNK_WRITE(V1) { Pow = param.asInt(); if (Pow > NUMPIXELS) Pow = NUMPIXELS; else if (Pow < 1) Pow = 1; StripUpdate(); } BLYNK_WRITE(V2) { Ionithation = param.asInt(); digitalWrite(IonPin, Ionithation); StripUpdate(); } void loop() { Blynk.run(); // You can inject your own code or combine it with other sketches. // Check other examples on how to communicate with Blynk. Remember // to avoid delay() function! encoder(); button(); } void button(){ if (!digitalRead(Button)){ Ionithation = !Ionithation; StripUpdate(); Blynk.virtualWrite(V2, Ionithation); delay(300); } } void encoder(){ encoder_A = digitalRead(pin_A); // считываем состояние выхода А энкодера encoder_B = digitalRead(pin_B); // считываем состояние выхода B энкодера if((!encoder_A) && (encoder_A_prev)){ // если состояние изменилось с положительного к нулю if(encoder_B) { if (Pow<NUMPIXELS){ Pow++; }else{ Pow = NUMPIXELS; } StripUpdate(); } else { if (Pow > 1){ Pow--; }else{ Pow=1; } StripUpdate(); } } else if((!encoder_B) && (encoder_B_prev)){ // если состояние изменилось с положительного к нулю if(!encoder_A) { if (Pow<NUMPIXELS){ Pow++; }else{ Pow = NUMPIXELS; } StripUpdate(); } else { if (Pow > 1){ Pow--; }else{ Pow=1; } StripUpdate(); } } encoder_A_prev = encoder_A; // сохраняем значение А для следующего цикла encoder_B_prev = encoder_B; } void StripUpdate() { FanSpeed = map(Pow, 1, NUMPIXELS, 50, 1023); analogWrite(FanPin, FanSpeed); if (Ionithation) { digitalWrite(IonPin, HIGH); for(int i=0; i<Pow; i++) { pixels.setPixelColor(i, pixels.Color(40, 20, 0)); pixels.show(); } }else{ digitalWrite(IonPin, LOW); for(int i=0; i<Pow; i++) { // For each pixel... pixels.setPixelColor(i, pixels.Color(0, 0, 80)); pixels.show(); } } if (Pow < NUMPIXELS){ for(int i=Pow; i<NUMPIXELS; i++) { // For each pixel... pixels.setPixelColor(i, pixels.Color(0, 80, 0)); pixels.show(); } } delay(30); }
Последняя функция StripUpdate() отвечает за формирование цвета на ленте. Переменная Pow содержит текущий уровень шкалы по количеству светодиодов (1-16). NUMPIXELS - максимальный уровень (количество светодиодов, в данном случае - 16).
Суть функции закрашивать Pow количество светодиодов синим (или желтым), а дальше до конца зеленым цветами. Выглядеть это должно быть так: Допустим Pow = 6, значит первые 6 светодиодов светят синим, а остальные (7-16) зеленым....
Но наблюдаются глюки. То цвет не тот, то вместо 16 светит 18 (и более) светодиодов, то вся лента нормально светит, правильно, а один светодиод горит не тем цветом, голубым, или розовам, или вообще красным, в общем совсе не того цвета.
При этом обычные примеры из NeoPixel работают без проблем и без глюков.
Что можете посоветовать? Что я сделал не так, где ошибся?
команда pixels.show(); высвечивает на ленте готовую картинку. Ее надо подавть после того, как вы вывели цвет на все диоды. А вы ее в цикле после каждого диода лепите.
Или после каждого pixels.show(); надо ставить задержку, такую чтобы вся пиксели успели пересчитаться и в и вывестись на ленту
Или после каждого pixels.show(); надо ставить задержку, такую чтобы вся пиксели успели пересчитаться и в и вывестись на ленту
После show() задержка требуется только для того, чтобы зритель смог насладиться композицией текущего фрейма ;)
А так - диагноз верный, поддерживаю.
Вставка пауз делает переключение ленты плавным, с последовательным обновлением светодиодов. Мне такие спец эферты не нужны. Кстати, так в примерах сделано.
Пробовал убирать pixels.show();, и ставить его только в самом конце - это ни на что не влияет.
В конце - где?
Так:
Должно работать. Переменный резистор возьмите, замапьте его analogRead() в 1...NUMPIXELS и проверьте на StripUpdate().
Попробовал тестовый скетч:
И... все работает! Значит проблема не в том как написана функция StripUpdate(). Что-то другое нарушает работу NeoPixel. Есть идеи?
Особо идей нет. Но я бы для начала из первого скетча вынес весь Blynk...
А вообще, Ваша функция сворачивается в такое:
sadman41, спасибо за пример!
Можете его объяснить? Я не силен в программировании, такая структура для меня неизвестна. Что означает символ "?", какая его функция?
Где об этом можно почитать?
Что означает символ "?", какая его функция?
https://prog-cpp.ru/c-if/ -> Тернарные операции
Спасибо!