esphome / esphome-core

🚨 No longer used 🚨 - The C++ framework behind ESPHome
https://esphome.io/
GNU General Public License v3.0
545 stars 113 forks source link

Individual addressable leds in pixel strips #448

Closed mvturnho closed 5 years ago

mvturnho commented 5 years ago

Is your feature request related to a problem/use-case? Please describe.

I want to use a pixel strip to display sensor status like door open/close or temperature/pressure.

For example I have 8 door sensors an three temperature sensors.

With one pixel strip I would like to have the first 8 leds show the sensor status. Red is open. Green is closed.

The next 3 ĺeds for the temperature. Blue is cold, yellow, orange, red is hot. Describe the solution you'd like

Is it possible to address just a number (1-n) of leds in a strip with an mqtt message?

Additional context

Individual addressable lights for neopixel or fastled

OttoWinter commented 5 years ago

You can use a custom effect for that - see lambda effect. From there you can address all LEDs like you wish.

Closing as this issue is a duplicate.

mvturnho commented 5 years ago

Thanks I will try this approach.

And this project is really great to use. Thanks for that.

mvturnho commented 5 years ago

@OttoWinter It seems I am unable to get this working.

Here is the relevant part in my yaml config

esphomeyaml:
  name: m5stack
  platform: ESP32
  board: nodemcu-32s
  esphomelib_version: latest

wifi:
  ssid: 'xxxxxxxx'
  password: 'xxxxxxxx'

mqtt:
#  broker: '192.168.2.xx'
  broker: '192.168.xx.xx'
  username: ''
  password: ''

# Enable logging
logger:

ota:

light:
  - platform: fastled_clockless
    id: light_fastled
    chipset: WS2812B
    pin: GPIO21
    num_leds: 8
    rgb_order: GRB
    name: 'LED Strip'
    effects:
      - addressable_lambda:
          name: statustest
          update_interval: 500ms
          lambda: |-           
            ESP_LOGD("statustest", "switch on led 1");
            fadeToBlackBy(it.leds(), it.size(), 10);
            int pos = 1;
            it.leds()[pos] = CHSV(0, 255, 150);

            it.schedule_show();

when I compile this I get:

src\main.cpp: In lambda function:
src\main.cpp:32:26: error: 'class esphomelib::light::AddressableLight' has no member named 'leds'
fadeToBlackBy(it.leds(), it.size(), 10);
^
src\main.cpp:34:12: error: 'class esphomelib::light::AddressableLight' has no member named 'leds'
it.leds()[pos] = CHSV(0, 255, 150);
^
src\main.cpp:36:12: error: 'class esphomelib::light::AddressableLight' has no member named 'schedule_show'
it.schedule_show();
^

Could you help me out on this? Maybe there is some instruction on howto go about this, When I open the project in platformio my generated main.cpp also gives the errors.

OttoWinter commented 5 years ago

@mvturnho No, that's not the API. ESPHome has it's own addressable light abstraction.

ESP_LOGD("statustest", "switch on led 1");
for (int i = 0; i < it.size(); i++) 
  it[i] = it[i].get() - 10;
it[1] = ESPHSVColor(0, 255, 100);

See addressable_effects.cpp in source code for more examples

mvturnho commented 5 years ago

@OttoWinter Hi, it seems I keep running into problems with this.

I started with your example above, when compiling I get the folowing error:

src\main.cpp: In lambda function:
src\main.cpp:33:40: error: 'ESPHSVColor' was not declared in this scope
it[1] = ESPHSVColor(0, 255, 100);
^
src\main.cpp:33:40: note: suggested alternative:
In file included from .piolibdeps\esphomelib\src/esphomelib/light/addressable_light_effect.h:9:0,
from .piolibdeps\esphomelib\src/esphomelib/application.h:52,
from src\main.cpp:3:
.piolibdeps\esphomelib\src/esphomelib/light/addressable_light.h:63:8: note:   'esphomelib::light::ESPHSVColor'
struct ESPHSVColor {
^

Also, how can I use the state, color and brightness that I parse with the MQTT message?

{"effect":"statustest","state":"ON","brightness":255,"color":{"r":255,"g":255,"b":255}}

For convenience: this is my yaml file:

esphomeyaml:
  name: controlpanel
  platform: ESP32
  board: nodemcu-32s
  esphomelib_version:
    branch: master

wifi:
  ssid: 'XXXXXXXX'
  password: 'XXXXXXXXXXXXXXXX'
  domain : .visconti.nl

mqtt:
  broker: '192.168.3.100'
  port: 1883

# Enable logging
logger:
  level: DEBUG

ota:
  safe_mode: True
  password: VERYSECURE

# Example configuration entry
i2c:
  sda: 21
  scl: 22
  scan: True

light:
  - platform: fastled_clockless
    id: light_fastled
    chipset: WS2812B
    pin: GPIO4
    num_leds: 8
    rgb_order: GRB
    name: 'LED Strip'
    effects:
      - addressable_lambda:
          name: statustest
          update_interval: 500ms
          lambda: |-
            ESP_LOGD("statustest", "switch on led 1");
            for (int i = 0; i < it.size(); i++) 
              it[i] = it[i].get() - 10;
            it[1] = ESPHSVColor(0, 255, 100);

this is my main.cpp that is generated by esphometaml.

// Auto generated code by esphomeyaml
// ========== AUTO GENERATED INCLUDE BLOCK BEGIN ===========
#include "esphomelib/application.h"
using namespace esphomelib;
// ========== AUTO GENERATED INCLUDE BLOCK END ==========="

void setup() {
  // ===== DO NOT EDIT ANYTHING BELOW THIS LINE =====
  // ========== AUTO GENERATED CODE BEGIN ===========
  App.set_name("controlpanel");
  App.set_compilation_datetime(__DATE__ ", " __TIME__);
  LogComponent *logcomponent = App.init_log(115200);
  logcomponent->set_global_log_level(ESPHOMELIB_LOG_LEVEL_DEBUG);
  WiFiComponent *wificomponent = App.init_wifi();
  WiFiAP wifiap = WiFiAP();
  wifiap.set_ssid("XXXXXXXXX");
  wifiap.set_password("XXXXXXXXXXXXXXX");
  wificomponent->add_sta(wifiap);
  OTAComponent *otacomponent = App.init_ota();
  otacomponent->set_auth_password("VERYSECURE");
  otacomponent->start_safe_mode();
  mqtt::MQTTClientComponent *mqtt_mqttclientcomponent = App.init_mqtt("192.168.2.1", 1883, "", "");
  I2CComponent *i2ccomponent = App.init_i2c(21, 22, true);
  Application::MakeFastLEDLight application_makefastledlight = App.make_fast_led_light("LED Strip");
  application_makefastledlight.fast_led->add_leds<WS2812B, 4, GRB>(8);
  light::LightState *light_fastled = application_makefastledlight.state;
  light::MQTTJSONLightComponent *light_mqttjsonlightcomponent = application_makefastledlight.mqtt;
  light_fastled->add_effects({
      new light::AddressableLambdaLightEffect("statustest", [=](light::AddressableLight & it) -> void {
        ESP_LOGD("statustest", "switch on led 1");
        for (int i = 0; i < it.size(); i++) 
          it[i] = it[i].get() - 10;
        it[1] = ESPHSVColor(0, 255, 100);
    }, 500),
  });
  // =========== AUTO GENERATED CODE END ============
  // ========= YOU CAN EDIT AFTER THIS LINE =========
  App.setup();
}

void loop() {
  App.loop();
}
mvturnho commented 5 years ago

@OttoWinter

found that. it needed the namespace.

            ESP_LOGD("statustest", "switch on led 1");
            for (int i = 0; i < it.size(); i++) 
              it[i] = it[i].get() - 10;
            it[1] = light::ESPHSVColor(0, 255, 100);

only question I have then is: how can I use the state, color and brightness that I parse with the MQTT message?

Thanks

OttoWinter commented 5 years ago

how can I use the state, color and brightness that I parse with the MQTT message?

Store them in a global variable (globals:) in a mqtt.on_message trigger and then use those in the effect

mvturnho commented 5 years ago

@OttoWinter

Hi just for feedback and reference to other users. I left the light - efects solution and went for the mqtt on_json_message. In this way I can set the individual leds from the json message. I added led_indexto address the individual leds. with led_stateI can set them ONor OFF.

{
    "led_index": "16",
    "led_state": "ON",
    "led_bright": 100,
    "led_color": {
        "r": 255,
        "g": 255,
        "b": 0
    }
}
esphomeyaml:
  name: controlpanel
  platform: ESP8266
  board: nodemcuv2
  esphomelib_version:
    branch: dev

wifi:
  ssid: 'XXXXXXXXXXX'
  password: 'XXXXXXXXXXXXXXXXX'
  domain : .visconti.nl

mqtt:
  broker: '192.168.1.1'
  port: 1883

  on_json_message:
    topic: controlpanel/status/led
    then:
        - lambda: |-
            int index = 0;
            float brightness = 50.0;
            int r = 100;
            int g = 100;
            int b = 100;
            if (x.containsKey("led_index"))  {
                index = x["led_index"];
                light::FastLEDLightOutputComponent *fast_led = application_makefastledlight.fast_led;
                if (x.containsKey("led_bright"))
                    brightness = x["led_bright"];
                if ((index >= 0) && (index < fast_led->size()))  {
                    if (x.containsKey("led_state"))  {
                        if (x["led_state"] == "ON") {
                            if (x.containsKey("led_color")) {
                                r = x["led_color"]["r"];
                                g = x["led_color"]["g"];
                                b = x["led_color"]["b"];
                            }
                            ESP_LOGD("on_json_message", "LED index %d bright %f state ON", index, brightness);
                            light_fastled->turn_on();
                            fast_led->get_controller()->leds()[index].setRGB(r, g, b);
                            fast_led->get_controller()->leds()[index].maximizeBrightness(brightness);
                            fast_led->schedule_show();
                        }  else if (x["led_state"] == "OFF") {
                            ESP_LOGD("on_json_message", "LED index %d state OFF", index);
                            fast_led->get_controller()->leds()[index].setRGB(0, 0, 0);
                            fast_led->schedule_show();
                        } else
                            ESP_LOGD("on_json_message", "INVALID value led_state");
                    }  else
                        ESP_LOGD("on_json_message", "INVALID missing led_state");
                } else
                    ESP_LOGD("on_json_message", "INVALID led_index out of bounds 0 < led_index < %d",fast_led->size());
            }
            else
                ESP_LOGD("on_json_message", "INVALID missing led_index");

# Enable logging
logger:
  level: DEBUG

ota:
  safe_mode: True
  password: VERYSECURE

light:
  - platform: fastled_clockless
    id: light_fastled
    chipset: WS2812B
    pin: D4
    num_leds: 16
    rgb_order: GRB
    name: 'LED Strip'