sinricpro / esp8266-esp32-sdk

Library for https://sinric.pro - simple way to connect your device to Alexa, Google Home, SmartThings and cloud
https://sinric.pro
228 stars 121 forks source link

WS2812B not working as it should! #327

Closed shijil2023 closed 9 months ago

shijil2023 commented 11 months ago

I tried running a WS2812B LED strip, selected "Smart Light Bulb" in sinric pro dashboard. issue 1. only 1 LED turns on, I did changed the count in code. issue 2. The colors are not accurate, green appears instead of red. issue 3. the color temperature features not work at all, it shows error.

The board is ESP8266 and strip is WS2812B, which works fine with WLED and test codes,

kakopappa commented 11 months ago

Issue 2: Since you did not mention which app is used to control the LED, I assume it's Portal. So I tried sending from the Portal and the correct values for RGB appear in the Arduino Serial. Check whether you are getting the correct values like this from the server.

Red: #FF0000 Green: #00FF00 Blue: #0000FF

Serial.printf("Device %s color changed to %d, %d, %d (RGB)\r\n", deviceId.c_str(), device_state.color.r, device_state.color.g, device_state.color.b);

image

issue 3: Sketch does not support temperature features. You have to add the callbacks to your sketch and implement it.

bool onColorTemperature(const String &deviceId, int &colorTemperature) {
  device_state.colorTemperature = colorTemperature;
  Serial.printf("Device %s color temperature changed to %d\r\n", deviceId.c_str(), device_state.colorTemperature);
  return true;
}

bool onIncreaseColorTemperature(const String &deviceId, int &colorTemperature) {
  int index = colorTemperatureIndex[device_state.colorTemperature];              // get index of stored colorTemperature
  index++;                                                                // do the increase
  if (index < 0) index = 0;                                               // make sure that index stays within array boundaries
  if (index > max_color_temperatures-1) index = max_color_temperatures-1; // make sure that index stays within array boundaries
  device_state.colorTemperature = colorTemperatureArray[index];                  // get the color temperature value
  Serial.printf("Device %s increased color temperature to %d\r\n", deviceId.c_str(), device_state.colorTemperature);
  colorTemperature = device_state.colorTemperature;                              // return current color temperature value
  return true;
}

bool onDecreaseColorTemperature(const String &deviceId, int &colorTemperature) {
  int index = colorTemperatureIndex[device_state.colorTemperature];              // get index of stored colorTemperature
  index--;                                                                // do the decrease
  if (index < 0) index = 0;                                               // make sure that index stays within array boundaries
  if (index > max_color_temperatures-1) index = max_color_temperatures-1; // make sure that index stays within array boundaries
  device_state.colorTemperature = colorTemperatureArray[index];                  // get the color temperature value
  Serial.printf("Device %s decreased color temperature to %d\r\n", deviceId.c_str(), device_state.colorTemperature);
  colorTemperature = device_state.colorTemperature;                              // return current color temperature value
  return true;
}

..
SinricProLight &myLight = SinricPro[LIGHT_ID];
myLight.onColorTemperature(onColorTemperature);
myLight.onIncreaseColorTemperature(onIncreaseColorTemperature);
myLight.onDecreaseColorTemperature(onDecreaseColorTemperature);

complete example is here: https://github.com/sinricpro/esp8266-esp32-sdk/blob/master/examples/Light/Light/Light.ino

sivar2311 commented 11 months ago

Some time ago I wrote a complete light sketch for an analogue LED: https://gist.github.com/sivar2311/89d3cfe0bdb7c787bb40ce881a147acc

This contains all features for a light device

To control a WS2812B Stripe, you only need to adjust the setup() function to initialise the stripe and the setStripe() function to set the color of the Stripe.

shijil2023 commented 11 months ago

Issue 2: Since you did not mention which app is used to control the LED, I assume it's Portal. So I tried sending from the Portal and the correct values for RGB appear in the Arduino Serial. Check whether you are getting the correct values like this from the server.

Red: #FF0000 Green: #00FF00 Blue: #0000FF

Serial.printf("Device %s color changed to %d, %d, %d (RGB)\r\n", deviceId.c_str(), device_state.color.r, device_state.color.g, device_state.color.b);

image

issue 3: Sketch does not support temperature features. You have to add the callbacks to your sketch and implement it.

bool onColorTemperature(const String &deviceId, int &colorTemperature) {
  device_state.colorTemperature = colorTemperature;
  Serial.printf("Device %s color temperature changed to %d\r\n", deviceId.c_str(), device_state.colorTemperature);
  return true;
}

bool onIncreaseColorTemperature(const String &deviceId, int &colorTemperature) {
  int index = colorTemperatureIndex[device_state.colorTemperature];              // get index of stored colorTemperature
  index++;                                                                // do the increase
  if (index < 0) index = 0;                                               // make sure that index stays within array boundaries
  if (index > max_color_temperatures-1) index = max_color_temperatures-1; // make sure that index stays within array boundaries
  device_state.colorTemperature = colorTemperatureArray[index];                  // get the color temperature value
  Serial.printf("Device %s increased color temperature to %d\r\n", deviceId.c_str(), device_state.colorTemperature);
  colorTemperature = device_state.colorTemperature;                              // return current color temperature value
  return true;
}

bool onDecreaseColorTemperature(const String &deviceId, int &colorTemperature) {
  int index = colorTemperatureIndex[device_state.colorTemperature];              // get index of stored colorTemperature
  index--;                                                                // do the decrease
  if (index < 0) index = 0;                                               // make sure that index stays within array boundaries
  if (index > max_color_temperatures-1) index = max_color_temperatures-1; // make sure that index stays within array boundaries
  device_state.colorTemperature = colorTemperatureArray[index];                  // get the color temperature value
  Serial.printf("Device %s decreased color temperature to %d\r\n", deviceId.c_str(), device_state.colorTemperature);
  colorTemperature = device_state.colorTemperature;                              // return current color temperature value
  return true;
}

..
SinricProLight &myLight = SinricPro[LIGHT_ID];
myLight.onColorTemperature(onColorTemperature);
myLight.onIncreaseColorTemperature(onIncreaseColorTemperature);
myLight.onDecreaseColorTemperature(onDecreaseColorTemperature);

complete example is here: https://github.com/sinricpro/esp8266-esp32-sdk/blob/master/examples/Light/Light/Light.ino

its all confusing for me.

  1. I have a WS2812B strip, so I used the 'Light_FastLED_WS2812" code, but you gave me a the 'Light' code.
  2. Which is the output PIN ?
kakopappa commented 11 months ago

@shijil2023 try the @sivar2311 sketch.

shijil2023 commented 11 months ago

@shijil2023 try the @sivar2311 sketch.

I tried the following code, slightly modified from @sivar2311 it turns on / off the LED, controlls brightness. nothing else works. it shows error "device did not handle..."

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <SinricPro.h>
#include <SinricProLight.h>
#include <FastLED.h>
#include <map>

#define WIFI_SSID  "xxxxxxxx"
#define WIFI_PASS  "xxxxxxxx4"
#define APP_KEY    "f25c9xxxxxxxxe226eac"
#define APP_SECRET "4b6c682xxxxxxxxxx-9a3f-784a607e1a59"
#define LIGHT_ID   "64c0exxxxxxxxxx22a91cde3"
#define BAUD_RATE  9600

#define LED_PIN     D5      // Pin connected to the Data Input of WS2812B strip
#define NUM_LEDS    60      // Number of LEDs in your strip

CRGB leds[NUM_LEDS];        // Define the array to store LED colors

struct Color {
    uint8_t r;
    uint8_t g;
    uint8_t b;
};

using ColorTemperatures = std::map<uint16_t, Color>;
ColorTemperatures colorTemperatures{
    {2000, {255, 138, 18}},
    {2200, {255, 147, 44}},
    // ... (other color temperature values and corresponding RGB colors)
    {9000, {214, 225, 255}}
};

struct DeviceState {
    bool  powerState       = false;
    Color color            = {214, 225, 255};
    int   colorTemperature = 9000;
    int   brightness       = 100;
} device_state;

SinricProLight& myLight = SinricPro[LIGHT_ID];

void setStripe() {
    if (device_state.powerState == false) { // Turn off?
        FastLED.clear(); // Clear all LEDs
    } else {
        CRGB colorRGB(device_state.color.r, device_state.color.g, device_state.color.b);
        for (int i = 0; i < NUM_LEDS; i++) {
            leds[i] = colorRGB;
        }
        FastLED.setBrightness(map(device_state.brightness, 0, 100, 0, 255));
    }
    FastLED.show(); // Send the updated colors to the LED strip
}

bool onPowerState(const String& deviceId, bool& state) {
    device_state.powerState = state;
    setStripe();
    return true;
}

bool onBrightness(const String& deviceId, int& brightness) {
    device_state.brightness = brightness;
    setStripe();
    return true;
}

bool onAdjustBrightness(const String& deviceId, int& brightnessDelta) {
    device_state.brightness += brightnessDelta;
    brightnessDelta = device_state.brightness;
    setStripe();
    return true;
}

bool onIncreaseColorTemperature(const String& devceId, int& colorTemperature) {
    auto current = colorTemperatures.find(device_state.colorTemperature);
    auto next = std::next(current);
    if (next == colorTemperatures.end()) next = current;
    device_state.color = next->second;
    device_state.colorTemperature = next->first;
    colorTemperature = device_state.colorTemperature;
    setStripe();
    return true;
}

bool onDecreaseColorTemperature(const String& devceId, int& colorTemperature) {
    auto current = colorTemperatures.find(device_state.colorTemperature);
    auto next = std::prev(current);
    if (next == colorTemperatures.end()) next = current;
    device_state.color = next->second;
    device_state.colorTemperature = next->first;
    colorTemperature = device_state.colorTemperature;
    setStripe();
    return true;
}

void setupWiFi() {
    Serial.printf("WiFi: connecting");
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    while (WiFi.status() != WL_CONNECTED) {
        Serial.printf(".");
        delay(250);
    }
    Serial.printf("connected\r\nIP is %s\r\n", WiFi.localIP().toString().c_str());
}

void setupSinricPro() {
    myLight.onPowerState(onPowerState);
    myLight.onBrightness(onBrightness);
    myLight.onAdjustBrightness(onAdjustBrightness);
    myLight.onIncreaseColorTemperature(onIncreaseColorTemperature);
    myLight.onDecreaseColorTemperature(onDecreaseColorTemperature);

    SinricPro.begin(APP_KEY, APP_SECRET);
}

void setup() {
    Serial.begin(BAUD_RATE);

    FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);

    setupWiFi();
    setupSinricPro();
}

void loop() {
    SinricPro.handle();
}
shijil2023 commented 11 months ago

...

sivar2311 commented 11 months ago

You have forgotten to implement and assign the onColor callback. This makes it impossible to set the strip to a specific color.

shijil2023 commented 11 months ago

You have forgotten to implement and assign the onColor callback. This makes it impossible to set the strip to a specific color. Yes. I am now able to set colors, but the white shade (warm white/cool white) options are not working). Also I am able to turn on/off and set colors via Google Assistant, but set color to white does nothing.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <SinricPro.h>
#include <SinricProLight.h>
#include <FastLED.h> // Include the FastLED library

#define WIFI_SSID  "YOUR-WIFI-SSID"
#define WIFI_PASS  "YOUR-WIFI-PASS"
#define APP_KEY    "YOUR-APPKEY"     // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "YOUR-APPSECRET"  // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define LIGHT_ID   "YOUR-DEVICEID"   // Should look like "5dc1564130xxxxxxxxxxxxxx"
#define BAUD_RATE  9600              // Change baudrate to your need for serial log

#define LED_PIN    D5    //pin connected to LED strip
#define NUM_LEDS   60    //number of LEDs in strip

CRGB leds[NUM_LEDS];    // Define the array to store LED colors

struct DeviceState {    // Stores current device state with following initial values:
    bool  powerState       = false;           // initial state is off
    CRGB  color            = CRGB::White;     // color is set to white (default color)
    int   brightness       = 100;             // brightness is set to 100
} device_state;

SinricProLight& myLight = SinricPro[LIGHT_ID]; // SinricProLight device

void setStripe() {
    // Calculate brightness
    CRGB adjustedColor = device_state.color;
    adjustedColor.nscale8_video(device_state.brightness);

    if (device_state.powerState == false) {
        FastLED.clear(); // Turn off all LEDs
    } else {
        fill_solid(leds, NUM_LEDS, adjustedColor); // Set all LEDs to the adjusted color
    }

    FastLED.show(); // Send the updated colors to the LED strip
}

bool onPowerState(const String& deviceId, bool& state) {
    device_state.powerState = state; // store the new power state
    setStripe(); // update the LEDs
    return true;
}

bool onBrightness(const String& deviceId, int& brightness) {
    device_state.brightness = brightness; // store new brightness level
    setStripe(); // update the LEDs
    return true;
}

bool onColor(const String& deviceId, byte& r, byte& g, byte& b) {
    device_state.color = CRGB(r, g, b); // store new color
    setStripe(); // update the LEDs
    return true;
}

void setupWiFi() {
    Serial.printf("WiFi: connecting");
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    while (WiFi.status() != WL_CONNECTED) {
        Serial.printf(".");
        delay(250);
    }
    Serial.printf("connected\r\nIP is %s\r\n", WiFi.localIP().toString().c_str());
}

void setupSinricPro() {
    myLight.onPowerState(onPowerState); // assign onPowerState callback
    myLight.onBrightness(onBrightness); // assign onBrightness callback
    myLight.onColor(onColor); // assign onColor callback

    SinricPro.begin(APP_KEY, APP_SECRET); // start SinricPro
}

void setup() {
    Serial.begin(BAUD_RATE); // setup serial

    FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); // Initialize FastLED for WS2812B, GRB color order

    setupWiFi(); // connect wifi
    setupSinricPro(); // setup SinricPro
}

void loop() {
    SinricPro.handle(); // handle SinricPro communication
}
sivar2311 commented 11 months ago

I don't know which functionality and what phrases are supported by Google Home assistent. There might be differences.

Please try to set the color temperature via SinricPro Dashboard (https://portal.sinric.pro/dashboard) and report back here if it is working or not.

sivar2311 commented 11 months ago

Using the Google Home app, everything works as expected.

https://github.com/sinricpro/esp8266-esp32-sdk/assets/2558564/2af6b360-4839-4d3c-9c07-6a2b3627255a

stale[bot] commented 11 months ago

This issue has gone quiet. Spooky quiet. We currently close issues after 14 days of inactivity. It’s been at least 7 days since the last update here. If we missed this issue or if you want to keep it open, please reply here. As a friendly reminder, the best way to fix this or any other problem is to provide a detailed error description including a serial log. Thanks for being a part of the SinricPro community!

stale[bot] commented 9 months ago

Hey again! It’s been 14 days since anything happened on this issue, so our friendly robot (that’s me!) is going to close it. Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to comment on this issue or create a new one if you need anything else. As a friendly reminder, the best way to fix this or any other problem is to provide a detailed error description including a serial log. Thanks again for being a part of the SinricPro community!

adamkstock commented 9 months ago

Hi sorry to post on a closed issue , but i had the exact same problems (1 and 2) and i resolved them as such - 1 changed this line of code - FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS); to FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);

2 every time this line exists - FastLED.show(); make it perform the action twice like so - FastLED.show(); FastLED.show();

i think this is all down to the varying quality of led strips (in both data throughput and how they are wired/documented).... but it resolved the issues for me . hope it helps