Глюки в 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();, и ставить его только в самом конце - это ни на что не влияет.
В конце - где?
Так:
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(); } } pixels.show(); delay(30); }Должно работать. Переменный резистор возьмите, замапьте его analogRead() в 1...NUMPIXELS и проверьте на StripUpdate().
Попробовал тестовый скетч:
#include <Adafruit_NeoPixel.h> #define LedPIN 13 // Pin D7 // On Trinket or Gemma, suggest changing this to 1 #define NUMPIXELS 16 // Popular NeoPixel ring size Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LedPIN, NEO_GRB + NEO_KHZ800); int Pow = 0; bool Ionithation = false; void setup() { pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) pixels.show(); StripUpdate(); } void loop() { for (Pow = 1; Pow<17; Pow ++) { StripUpdate(); delay(400); } Ionithation = !Ionithation; } void StripUpdate() { if (Ionithation) { for(int i=0; i<Pow; i++) { pixels.setPixelColor(i, pixels.Color(40, 20, 0)); //pixels.show(); } }else{ for(int i=0; i<Pow; i++) { // For each pixel... pixels.setPixelColor(i, pixels.Color(0, 0, 80)); //pixels.show(); } } if (Pow < 16){ for(int i=Pow; i<16; i++) { // For each pixel... pixels.setPixelColor(i, pixels.Color(0, 80, 0)); //pixels.show(); } } pixels.show(); delay(30); }И... все работает! Значит проблема не в том как написана функция StripUpdate(). Что-то другое нарушает работу NeoPixel. Есть идеи?
Особо идей нет. Но я бы для начала из первого скетча вынес весь Blynk...
А вообще, Ваша функция сворачивается в такое:
const uint32_t colorIonithation = 0xAABB00; const uint32_t colorNoIonithation = 0x000099; const uint32_t colorBackground = 0x009900; ... void StripUpdate() { ... digitalWrite(IonPin, Ionithation); for (uint8_t i = 0; i < 16; i++) { pixels.setPixelColor(i, (i < Pow) ? (Ionithation ? colorIonithation : colorNoIonithation) : colorBackground); } pixels.show(); delay(30); }sadman41, спасибо за пример!
Можете его объяснить? Я не силен в программировании, такая структура для меня неизвестна. Что означает символ "?", какая его функция?
Где об этом можно почитать?
Что означает символ "?", какая его функция?
https://prog-cpp.ru/c-if/ -> Тернарные операции
Спасибо!