Гирлянда на адресных светодиодах WS2811 с платой HW-628 V1.1

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

Пытаюсь теперь довести до ума код, который я писал больше года назад. В коде могут быть лишние и неиспользуемые пока переменные, массивы.

Код:

Спойлер
#include <ESP8266WiFi.h>

#define lenArr(sizedArr) sizeof(sizedArr)/sizeof(*sizedArr)
#define FASTLED_ESP8266_RAW_PIN_ORDER
#include "FastLED.h"
constexpr uint8_t numLeds = 50;
constexpr uint8_t pinLeds = D8;
constexpr uint8_t COLOR_ORDER = RGB;
CRGB leds[numLeds];

constexpr uint8_t nameSTR = 16; 
constexpr uint8_t errorParsing = 0;
constexpr uint8_t modeLeds = 1;
constexpr uint8_t numLed = 2;
constexpr uint8_t brightLed = 3;
constexpr uint8_t redColor = 4;
constexpr uint8_t greenColor = 5;
constexpr uint8_t blueColor = 6;
constexpr uint8_t speedModeLeds = 7;

const char* ssid = "New_year_lights";
const char* password = "12345678";
IPAddress local_IP(10, 10, 10, 1);
IPAddress gateway(10, 10, 10, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiServer server(80);

constexpr char nameP[][nameSTR]{
  {"Error"}, 
  {"mode"},
  {"num"},
  {"bright"},
  {"red"},
  {"green"},
  {"blue"},
  {"speed"}
};
constexpr uint8_t lenNameP = lenArr(nameP);
uint8_t valueP[lenNameP] {};

#define ERROR 0
#define MODE 1
#define NUM 2
#define BRIGHT 3
#define RED_C 4
#define GREEN_C 5
#define BLUE_C 6
#define SPEED 7

const CRGB rainbow[]{0xff0000, 0xffa500, 0xffff00, 0x008000, 0x0000ff, 0x4b0082, 0xee82ee};
const CRGB color16[]{0xFFFFFF, 0xC0C0C0, 0xFF0000, 0xFF00FF, 0xFFFF00, 0x00FF00, 0x008000,
                    0x008080, 0x00FFFF, 0x0000FF, 0x000080, 0x800080, 0x808000, 0x800000,
                    0x808080, 0x000000 };
constexpr uint8_t brigth16[]{15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255};
//constexpr uint8_t brigth16[]{ 0, 10, 20, 100, 10, 200, 50, 127, 143, 159, 175, 191, 207, 223, 239, 255 };

void parsing(WiFiClient& client, uint8_t valueP[]) {
    static char c, nameStr[nameSTR]{};
    static uint8_t iNameP = 0, value = 0, iValue = 0;
    Serial.println("Start parsing");
    /*for (uint8_t i = 0; i < lenNameP; i++) {
        Serial.print(i); Serial.print(" ");
        Serial.print(nameP[i]); Serial.print(" = "); 
        Serial.print(valueP[i]); Serial.print(" ");
    }
    Serial.println(" ");*/
    while (client.available()) {
        c = client.read();
        if (c == '?') {
            while (c != ' ' && c != -1) {
                c = client.read();
                if (c == '\n' || c == '\r') break; 
                if (c >= 'a' && c <= 'z' && iNameP < (nameSTR - 1)) { 
                    nameStr[iNameP] = c;
                    iNameP++;
                }
                if (c == '=') {
                    nameStr[iNameP] = 0;
                    iNameP = 0;
                    for (uint8_t i = 0; i < lenNameP; i++)
                        if (strcmp(nameP[i], nameStr) == 0) { iValue = i; break; }
                }
                if (c >= '0' && c <= '9') {
                    value = value * 10 + (uint8_t(c) - 48); 
                }
                if ((c == '&' || c == ' ') && iValue) {
                    valueP[iValue] = value;
                    value = 0; iValue = 0;
                }
            }
        }
    }
    client.println(F("HTTP/1.1 200 OK"));
    client.println(F("Content-Type: text/plain"));
    client.println(F("Connection: close"));
    //client.println();
    //client.print('?');
    for (uint8_t i = 0; i < lenNameP; i++) {
        //client.print(nameP[i]);
        //client.print('=');
        //client.print(valueP[i]);
        //client.print('&');
        
        Serial.print(i); Serial.print(" ");
        Serial.print(nameP[i]); Serial.print("="); 
        Serial.print(valueP[i]); Serial.print("");
    }
    Serial.println("");
    Serial.println("Stop parsing");
    client.stop();
}

void setOneLed(uint8_t num, const uint8_t& bright, const CRGB& rgb) {
    //Serial.print("num = "); Serial.println(num);
    //Serial.print("bright = "); Serial.println(bright);
    if (num > 0 && num <= numLeds) {
        num--;
        leds[num] = CRGB(rgb);
        leds[num].maximizeBrightness();
        leds[num] %= brighten8_video(bright);
    }
}

void setup() {
    Serial.begin(9600);
    Serial.println("");
    Serial.println("Start");

    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(local_IP, gateway, subnet);
    WiFi.softAP(ssid, password);
    server.begin();
    FastLED.addLeds<WS2811, pinLeds>(leds, numLeds);
}

void loop() {
  WiFiClient client = server.available();
  while (client.connected())
       if (client.available() && !valueP[MODE]) parsing(client, valueP);
  if (!client.connected()) 
    client.stop();

   if (valueP[MODE]) {
    //Serial.print("mode = "); Serial.println(valueP[MODE]);
    switch (valueP[MODE]) {
      case 1: {
        for (uint8_t i = 0; i < numLeds; i++)
          setOneLed(i, valueP[0], CRGB(valueP[0], valueP[0], valueP[0]));
        break;
      }
      case 2: {
        setOneLed(valueP[NUM], valueP[BRIGHT], CRGB(valueP[RED_C], valueP[GREEN_C], valueP[BLUE_C]));
        break;
      }
    }
    FastLED.show();
    for (uint8_t i = 0; i < lenNameP; i++) valueP[i] = 0;
  }
   
   delay(100);
}

Вопрос на данный момент. Я отправляю команду с компьютера через браузер:
http://10.10.10.1/?mode=2&num=1&bright=50&red=200&green=0&blue=0&
Светодиод загорается, но почему-то функция parsing() отрабатывает дважды.
Монитор порта:

Start parsing
0 Error=0 1 mode=2 2 num=1 3 bright=50 4 red=200 5 green=0 6 blue=0 7 speed=0 
Stop parsing
Start parsing
0 Error=0 1 mode=2 2 num=1 3 bright=50 4 red=200 5 green=0 6 blue=0 7 speed=0 
Stop parsing

Почему так получается? Где я ошибся?

Перепиши это всё на библиотеку http сервера. Будет работать лучше и проще. Разбираться в этом самописном фарше - мазохизм.

1 лайк

Управление GET запросами пошло нормально, теперь буду FastLed изучать, чёт у меня яркость не сильно меняется, но думаю, разберусь.

Текст программы что получился:

Спойлер
#include <ESP8266WiFi.h>
#include "ESP8266WebServer.h"
#include "FastLED.h"

#define lenArr(sizedArr) sizeof(sizedArr)/sizeof(*sizedArr)
#define FASTLED_ESP8266_RAW_PIN_ORDER
constexpr uint8_t numLeds = 12;
constexpr uint8_t pinLeds = D8;
constexpr uint8_t COLOR_ORDER = RGB;
CRGB leds[numLeds];

const char* ssid = "New_year_lights";
const char* password = "12345678";
IPAddress local_IP(10, 10, 10, 1);
IPAddress gateway(10, 10, 10, 1);
IPAddress subnet(255, 255, 255, 0);
ESP8266WebServer server(80);

constexpr uint8_t nameSTR = 16; 
constexpr char nameP[][nameSTR]{
  {"mode"},
  {"num"},
  {"bright"},
  {"red"},
  {"green"},
  {"blue"},
};
constexpr uint8_t lenNameP = lenArr(nameP);
uint8_t valueP[lenNameP] {};

#define MODE 0
#define NUM 1
#define BRIGHT 2
#define RED_C 3
#define GREEN_C 4
#define BLUE_C 5

void setOneLed(uint8_t num, const uint8_t& bright, const CRGB& rgb) {
    //Serial.print("num = "); Serial.println(num);
    //Serial.print("bright = "); Serial.println(bright);
    if (num > 0 && num <= numLeds) {
        num--;
        leds[num] = CRGB(rgb);
        leds[num].maximizeBrightness();
        leds[num] %= brighten8_video(bright);
    }
}

void go() {
  //Serial.println("Start go");
  for (int i = 0; i < server.args(); i++)
    for (int j = 0; j < lenNameP; j++) 
      if (server.argName(i) == nameP[j]) {
        valueP[j] = server.arg(i).toInt();
        break;
      }
  server.send(200, "text/plain", "OK");
  /*for (uint8_t i = 0; i < lenNameP; i++) {
        Serial.print(i); Serial.print(" ");
        Serial.print(nameP[i]); Serial.print(" = "); 
        Serial.print(valueP[i]); Serial.print(" ");
  }
  Serial.println("");*/
}

void setup() {
    //Serial.begin(9600);
    //Serial.println("");
    //Serial.println("Start");

    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(local_IP, gateway, subnet);
    WiFi.softAP(ssid, password);

    server.begin();
    server.on("/go", go);

    FastLED.addLeds<WS2811, pinLeds>(leds, numLeds);
}

void loop() {
  server.handleClient(); 

  if (valueP[MODE]) {
    //Serial.print("mode = "); Serial.println(valueP[MODE]);
    switch (valueP[MODE]) {
      case 1: {
        for (uint8_t i = 0; i < numLeds; i++)
          setOneLed(i, 0, CRGB(0, 0, 0));
        break;
      }
      case 2: {
        setOneLed(valueP[NUM], valueP[BRIGHT], CRGB(valueP[RED_C], valueP[GREEN_C], valueP[BLUE_C]));
        break;
      }
    }
    FastLED.show();
    for (uint8_t i = 0; i < lenNameP; i++) valueP[i] = 0;
  }
}

Если задача в том, чтобы потренироваться, то поддерживаю начинание.
А для “быстро и красиво” есть WLED.

1 лайк

Целый день “убил” чтобы локализовать проблему.
Я что-то не понимаю или так и должно быть?

Тестовый код:

Спойлер
#include "FastLED.h"
#define FASTLED_ESP8266_RAW_PIN_ORDER
constexpr uint8_t numLeds = 12;
constexpr uint8_t pinLeds = D8;
CRGB leds[numLeds];

void setup() {
    FastLED.addLeds<WS2811, pinLeds, RGB>(leds, numLeds).setCorrection(TypicalLEDStrip);

    leds[0] = CRGB(200,0,0);
    leds[1] = CRGB(0,200,0);
    leds[2] = CRGB(0,0,200);

    FastLED.show();
    //FastLED.show();
    //FastLED.show();

}

void loop() {}

Если оставить только один FastLED.show(); то загорается только первый светодиод, если их будет три то загорятся все как надо.

IDE 2.2.1
Библиотека FastLED от DanielGarcia 3.6.0

Или я не подходящую библиотеку выбрал?

На AVR нормально отрабатывает?

Я такую гирлянду длиной 10м купил у китайцев за 380р, а тута вон оно чё…

Не пробовал на AVR, у меня схема уже спаяна и поксиполом залита. Может у кого есть возможность проверить?

Попробуй FastLED откатить на версию 3.5, ходят слухи, что у версии 3.6 с esp какие-то нестыковки

У есп, вообще нестыковочки с лентой по уровням. Кому-то везёт и все работает. А кому-то не очень.

Залей бинарником WLED, проверь им.

А может не стоило? Чем D2/D1 не угодили?

Нет, на 3,5 работает так же

Тоже не помогает

На AVR работает нормально

Ну, буду учитывать этот момент, вставил несколько лишних FastLED.show(); и основной код заработал как я и задумывал.

Кстати, двух штук тоже хватает ))

1 лайк

Да, я просто поставил две строки FastLED.show(); , где общее применение эффекта и всё заработало как часы. :slightly_smiling_face: А, и вернул 3.6.0 при этом.

Промежуточный рабочий результат моего творчества. )
По умолчанию включается автоматический режим с пятью спецэффектами, у каждого по пять скоростей.
Так же можно управлять гирляндой GET запросами, примеры в коде.

Спойлер
#include <ESP8266WiFi.h>
#include "ESP8266WebServer.h"
#include "FastLED.h"

#define lenArr(sizedArr) sizeof(sizedArr)/sizeof(*sizedArr)
#define FASTLED_ESP8266_RAW_PIN_ORDER
constexpr uint8_t numLeds = 50;
constexpr uint8_t pinLeds = D8;
CRGB leds[numLeds];
//CRGB lLeds[numLeds];
//uint8_t lBright[numLeds];
CHSV hsv;

const char* ssid = "New_year_lights";
const char* password = "12345678";
IPAddress local_IP(10, 10, 10, 1);
IPAddress gateway(10, 10, 10, 1);
IPAddress subnet(255, 255, 255, 0);
ESP8266WebServer server(80);

constexpr uint8_t nameSTR = 16; 
constexpr char nameP[][nameSTR]{
  {"mode"},
  {"num"},
  {"palette"},
  {"color"},
  {"red"},
  {"green"},
  {"blue"},
  {"bright"},
  {"speed"}
};
constexpr uint8_t lenNameP = lenArr(nameP);
uint8_t valueP[lenNameP] {};

#define MODE 0
#define NUM 1
#define PALETTE 2
#define COLOR 3
#define RED_C 4
#define GREEN_C 5
#define BLUE_C 6
#define BRIGHT 7
#define SPEED 8

#define MODBRIGHT 200

const CRGB myRainbow [] {CRGB::Red, CRGB::OrangeRed, CRGB::Yellow, CRGB::Green,
                        0x42AAFF, CRGB::MediumBlue, CRGB::Purple};
constexpr uint8_t lenMyRainbow = lenArr(myRainbow);

const TProgmemPalette16 myPalette_p 
    {CRGB::White, CRGB::Red, CRGB::Magenta, CRGB::Maroon, CRGB::OrangeRed, 
    CRGB::SaddleBrown, CRGB::Yellow, 
    CRGB::Green, CRGB::Olive, CRGB::Lime,
    0x42AAFF, CRGB::Aqua, CRGB::MediumBlue,  CRGB::Navy,
    CRGB::Purple, CRGB::Indigo
    };

void setOneAllLed_(const uint8_t& num, const uint8_t& bright, const CRGB& rgb) {
  hsv = CHSV(rgb2hsv_approximate(rgb));
  if (!num)  
    for (uint8_t i = 0; i <= numLeds; i++) 
      leds[i] = CHSV(hsv.h, hsv.s, bright);
  else 
    leds[num - 1] = CHSV(hsv.h, hsv.s, bright);

  FastLED.show();
  FastLED.show();
}

void setOneAllLed(const uint8_t& num, const CRGBPalette16& cPalette, const uint8_t& index, 
const uint8_t& bright, const TBlendType& blending) {
  if (!num)
    for (uint8_t i = 0; i < numLeds; i++) 
      leds[i] = ColorFromPalette(cPalette, index-1, bright, blending);
  else 
    leds[num-1] = ColorFromPalette(cPalette, index-1, bright, blending);

  FastLED.show();
  FastLED.show();
}

void go() {
  for (int i = 0; i < server.args(); i++)
    for (int j = 0; j < lenNameP; j++) 
      if (server.argName(i) == nameP[j]) {
        valueP[j] = server.arg(i).toInt();
        break;
      }
  server.send(200, "text/plain", "OK");
}

void setup() {
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(local_IP, gateway, subnet);
    WiFi.softAP(ssid, password);

    server.begin();
    server.on("/go", go);

    FastLED.addLeds<WS2811, pinLeds, RGB>(leds, numLeds).setCorrection(TypicalLEDStrip);
    valueP[MODE] = 4; //4
    
    uint32_t seed = 0;
    for (uint8_t i = 0; i < 16; i++) {
       seed *= 4;
       seed += analogRead(A0) & 3;
    }
    randomSeed(seed);
}

void loop() {
  static uint32_t interval = 0;
  static uint32_t previousMillis = 0;
  static uint8_t mode = 0;
  static uint8_t indexMode = 0;
  static int8_t setupIndexMode = 0;
  static uint8_t brightMode = 0;
  static uint8_t startI = 0, colorI = 0;
  static uint8_t autoMode = 0;
  static uint32_t autoModeInterval = 0;
  static uint32_t previousMillisAuto = 0;
  static uint8_t positionLed = 0;
  static int8_t positionStep = 0;
  static uint8_t colorLed = 0;
  static int8_t colorStep = 0;
  
 
  server.handleClient(); 

  if (valueP[MODE]) {
    if (valueP[MODE] == 4) autoMode = 1; else autoMode = 0;
    switch (valueP[MODE]) {
      case 1: {
        //http://10.10.10.1/go?mode=1 - гашение всех
        //закрасить один с заданной яркостью в цвет RGB
        //http://10.10.10.1/go?mode=1&num=3&palette=1&red=0&green=200&blue=0&bright=100 
        //http://10.10.10.1/go?mode=1&palette=1&red=0&green=200&blue=0&bright=100 - все одним цветом RGB
        //закрасить один с заданной яркостью в цвет из моей палитры
        //http://10.10.10.1/go?mode=1&num=3&palette=2&color=150&bright=100 
        //http://10.10.10.1/go?mode=1&palette=2&color=100&bright=100 - все одним цветом из моей палитры

        switch (valueP[PALETTE]) {
            case 0: { 
              setOneAllLed_(0, 0, 0);
            break;
            }
            case 1: { 
              setOneAllLed_(valueP[NUM], valueP[BRIGHT], CRGB(valueP[RED_C], valueP[GREEN_C], valueP[BLUE_C]));        
            break;
            }
            case 2: { 
              setOneAllLed(valueP[NUM], myPalette_p, valueP[COLOR], valueP[BRIGHT], LINEARBLEND);
            break;
            }

        }
        mode = 0;
        break;
      }
      
      case 2: { //активные простые режимы indexMode == color, interval == speed
        mode = 2;
        indexMode = valueP[COLOR];
        brightMode = valueP[BRIGHT];
        interval = valueP[SPEED];
        if (!brightMode) brightMode = MODBRIGHT; 
        if (!interval) interval = 30;
        setupIndexMode = 1;

        //Рандом цветами радуги по умолчанию 
        //http://10.10.10.1/go?mode=2

        //Рандом моей палитры 
        //http://10.10.10.1/go?mode=2&color=1&bright=150&speed=50

        //Рандом моей палитры с затуханием 
        //http://10.10.10.1/go?mode=2&color=2&bright=150&speed=50

        //Вспышка по всей ленте
        //http://10.10.10.1/go?mode=2&color=3&bright=150&speed=50

        //Разноцветная змейка
        //http://10.10.10.1/go?mode=2&color=4&bright=150&speed=50

        //Переливание цветами радуги вся лента
        //http://10.10.10.1/go?mode=2&color=5&bright=150&speed=50


      }
      
      case 3: { //Системные команды

        break;
      }

      case 4: { //Автоматический режим
        //http://10.10.10.1/go?mode=4
        mode = 2;
        brightMode = valueP[BRIGHT];
        interval = valueP[SPEED];
        if (brightMode == 0) brightMode = MODBRIGHT;
        break;
      }


    }
    for (uint8_t i = 0; i < lenNameP; i++) valueP[i] = 0;
  }

  if (mode) {
    uint32_t currentMillis = millis();
    if (autoMode) {
      if(currentMillis - previousMillisAuto >= autoModeInterval) {
        previousMillisAuto = currentMillis;
        randomSeed(micros());
        autoModeInterval = random(2,11) * 30000UL;
        interval = random(1, 6) * 30UL;
        indexMode = random(1,6);
        setupIndexMode = 1;
      }  
    }
    if(currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (setupIndexMode) {
        if (indexMode == 2) brightMode /= 2; else brightMode = MODBRIGHT;
        
        if (indexMode == 4) {
          //interval *= 4;
            positionLed = random(1,numLeds+1);
            do 
              positionStep = random(-1,2); 
            while (!positionStep);
        }

        if (indexMode == 5) {
          colorLed = random(11, 245);
          do 
              colorStep = random(-3,4); 
          while (!colorStep); 
        }

        setupIndexMode = 0;
      }

      switch (mode) {
        case 2: {
          switch (indexMode) {
            case 0: {
              setOneAllLed(random(1,numLeds+1), myPalette_p, random(1, 8) * 16, brightMode, LINEARBLEND);
              break;
            }
            case 1: {
              setOneAllLed(random(1,numLeds+1), myPalette_p, random(1, 15) * 16, brightMode, LINEARBLEND);
              break;
            }
            case 2: { 
             setOneAllLed(random(1,numLeds+1), myPalette_p, random(1, 255), brightMode, LINEARBLEND);
             fadeToBlackBy(leds, numLeds,8);
             break;
            }
            case 3: {
              EVERY_N_MILLISECONDS(interval * 25UL) {
                for (uint8_t i = 0; i < numLeds; i++)
                  setOneAllLed(i, myPalette_p, random(1, 255), brightMode, LINEARBLEND);
              } 
              fadeToBlackBy(leds, numLeds, brightMode / 5);
              FastLED.show();
              break;
            }
            case 4: {
              if (positionLed <= 1 || positionLed >= numLeds) 
                positionStep *= -1;
              positionLed += positionStep;
              setOneAllLed_(positionLed, brightMode, myRainbow[random(0, lenMyRainbow)]);
              fadeToBlackBy(leds, numLeds, 50);
              FastLED.show();
              break;
            }
            case 5: {
              if (colorLed <= 10 || colorLed >= 245) colorStep *= -1;
              colorLed += colorStep;
              setOneAllLed(0, RainbowColors_p, colorLed, brightMode, LINEARBLEND);
              break;
            }

            
          }
          break;
        }
      }
    }
  }
}

Не посоветуете библиотеку наподобие ESP8266WebServer.h только для Arduino Mega? У меня с шилдом POE W5500 в связке работает мега.