feature-requests icon indicating copy to clipboard operation
feature-requests copied to clipboard

GOSUND LB3

Open pepsonEL opened this issue 4 years ago • 15 comments

Describe the problem you have/What new integration you would like

Hi. Tommorow i recive my new light table led GOSUND LB3. Maybe is any person who implement to this lamp EDPHome and can tell me and send me config for this lamp ? Or maybe who can help me please.

https://rcpro.pl/product-pol-19418-Inteligentna-lampka-nocna-Gosund-LB3.html Please describe your use case for this integration and alternatives you've tried:

Additional context

pepsonEL avatar Jan 22 '21 21:01 pepsonEL

Any news ?

pepsonEL avatar Sep 23 '21 10:09 pepsonEL

Hi I just received this device today and did some tests and I have good news for you (and probably others).

Status so far:

  1. It's ESP8266EX
  2. It's not convertible by tuya-convert
  3. PCB has serial pinouts on hidden side (need to remove pcb from device for first flashing)
  4. Flashed with esphome using serial sucessfully (sample config below)
  5. GPIO: GPIO13 = WLED PWM GPIO12 = G_LED PWM GPIO5 = B_LED PWM GPIO15 = R_LED PWM

TODO: There is i2c touch sensor for side touch "buttons", it's On-Chip IC. Haven't found any info about it yet.

substitutions:
  devname: mynitebird

output:
  - id: "${devname}_output_wled"
    platform: esp8266_pwm
    pin: GPIO13
    frequency: 1000 Hz

  - id: "${devname}_output_gled"
    platform: esp8266_pwm
    pin: GPIO12
    frequency: 1000 Hz

  - id: "${devname}_output_bled"
    platform: esp8266_pwm
    pin: GPIO5
    frequency: 1000 Hz

  - id: "${devname}_output_rled"
    platform: esp8266_pwm
    pin: GPIO15
    frequency: 1000 Hz

light:
  - platform: monochromatic
    name: "${devname}_wled"
    id: "${devname}_wled"
    output: "${devname}_output_wled"

  - platform: monochromatic
    name: "${devname}_gled"
    id: "${devname}_gled"
    output: "${devname}_output_gled"

  - platform: monochromatic
    name: "${devname}_bled"
    id: "${devname}_bled"
    output: "${devname}_output_bled"

  - platform: monochromatic
    name: "${devname}_rled"
    id: "${devname}_rled"
    output: "${devname}_output_rled"

jkolczasty avatar Dec 29 '21 16:12 jkolczasty

@jkolczasty

Thanks for what you posted above, I appreciate your work. I wanted to share back what added progress I've been able to make (though I'm a Tasmota user). The I2C bus is on the following GPIOs:

GPIO2 - I2C SDA GPIO14 - I2C SCL

I was able to query what is (I think) both bus 1 and bus 2 and found devices at address 0x39 and 0x45. This does not explicitly apply to a specific driver that I've found yet, I guess I need to pop the bottom off the light again and try to read the super tiny chip again (arg!).

If I figure out the chip or manage to talk to it, I'll post some more.

If it is of use to you, in trying to tune the color gamma, I found it was very weak on the red, a little weak on green, and that the white LED was very bright (when transitioning between color and white light. I can share that if it helps you, though not sure if how to translate between Tasmota and EspHome.

All the best.

ams2121 avatar Jan 10 '22 20:01 ams2121

It's KF8TS2716 chip. It's very same what is used in xiaomi lamps and someone already did some research on that:

https://github.com/mmakaay/esphome-xiaomi_bslamp2/blob/d97c3361b09dacbab0dc9452bdd3c3e1e1235967/doc/technical_details.md

Currently have no time to write some test code for esphome, but it's still on top of my to-do.txt file ;-)

jkolczasty avatar Jan 10 '22 20:01 jkolczasty

I just found that same/slightly link! (https://github.com/mmakaay/esphome-xiaomi_bslamp2/blob/dev/doc/technical_details.md) You are totally on top of this. I've never written an i2c driver, though thinking of writing one also. I'll put a link to code here as I play with it (hopefully it's only somewhat awful!)

ams2121 avatar Jan 10 '22 21:01 ams2121

Are there any news on this? Has anyone gotten the touch function to work?

flixlix avatar Mar 18 '22 12:03 flixlix

Had not time to look at it so far. Maybe next week will find some time ;-)

jkolczasty avatar Mar 21 '22 11:03 jkolczasty

It's unclear what the alternative offered is here so I'm not sure why this was closed. Reports are that the KF8TS2716 is a generic MCU and if so the code used in the Xiaomi lamp may be different and thus the i2c commands different.

bfranske avatar Sep 09 '22 23:09 bfranske

I'm using mine, remote only via MQTT (with Tasmota). Getting the touch to work would be nice, however its definitely beyond my skill level. @jkolczasty is the real pro! anyhow best to all.

ams2121 avatar Sep 10 '22 01:09 ams2121

Aby new about touch ?

pepsonEL avatar Nov 08 '22 18:11 pepsonEL

Any news ?

pepsonEL avatar Feb 03 '23 09:02 pepsonEL

So, I did reverse engineer those lamps, and got both the touch and the tap-to-turn-on features to work! The "tap-to-turn-on" is handled by a cheap MEMS accelerometer, whose support I submitted in esphome/esphome#6187. The great news is that the behavior can be heavily customized (single tap, double tap, length, intensity), and you get your lamp's acceleration as a bonus (extremely useful ofc 🤣).

The touch part (at least on my model), is (poorly) handled by a cbm7320 IC chip that talks over I2C to the ESP8266. This cbm chip is not very well put together : if the lamp is above 60% brightness the chip's touch sensing mechanism gets confused and the chip start spitting out nonsense on I2C… Also that chip is in fact a general purpose MCU with a specific firmware made to transmit touch sensing events over I2C, so I don't know if a driver makes sense for esphome.

Anyway, here's my custom config (just ignore the cbm7320 part for now). But with #6187 the da270 part works well 😄

esphome:
  friendly_name: "Bedside Lamp"

esp8266:
  board: esp01_1m

output:
  - platform: esp8266_pwm
    id: blue_led
    pin: GPIO5
  - platform: esp8266_pwm
    id: green_led
    pin: GPIO12
  - platform: esp8266_pwm
    id: warm_white_led
    pin: GPIO13
  - platform: esp8266_pwm
    id: red_led
    pin: GPIO15

light:
  - platform: rgbw
    id: main_light
    name: "Light"
    red: red_led
    green: green_led
    blue: blue_led
    white: warm_white_led

i2c:
  sda: GPIO2
  scl: GPIO14
  scan: false
  frequency: 32 kHz # Matches the default firmware

external_components:
  - source: components

cbm7320:

binary_sensor:
  - platform: gpio
    icon: 'mdi:gesture-tap-box'
    pin:
      number: GPIO4
      mode:
        input: true
        pullup: false
    name: "Tap Detector"
    on_press:
      - light.toggle: main_light
  - platform: cbm7320
    name: Power Button
    channel: 14
    on_press:
      - light.toggle: main_light
  - platform: cbm7320
    name: Left Slider A
    channel: 7
  - platform: cbm7320
    name: Left Slider B
    channel: 8
  - platform: cbm7320
    name: Left Slider C
    channel: 9
  - platform: cbm7320
    name: Left Slider D
    channel: 10
  - platform: cbm7320
    name: Left Slider E
    channel: 11
  - platform: cbm7320
    name: Left Slider F
    channel: 12
  - platform: cbm7320
    name: Left Slider G
    channel: 13
  - platform: cbm7320
    name: Right Slider A
    channel: 0
  - platform: cbm7320
    name: Right Slider B
    channel: 1
  - platform: cbm7320
    name: Right Slider C
    channel: 2
  - platform: cbm7320
    name: Right Slider D
    channel: 3
  - platform: cbm7320
    name: Right Slider E
    channel: 4
  - platform: cbm7320
    name: Right Slider F
    channel: 5
  - platform: cbm7320
    name: Right Slider G
    channel: 6

sensor:
  - platform: da217
    address: 0x27
    resolution: 14bits
    full_scale: 4g
    tap_quiet_duration: 30ms
    tap_shock_duration: 70ms
    double_tap_duration: 500ms
    interrupt_source: unfiltered
    enable_double_tap_interrupt: true
    map_double_tap_interrupt_to_int1: true
    tap_acceleration_threshold: 0.0625
    output_data_rate: 125Hz
    accel_x:
      name: "Acceleration X"
    accel_y:
      name: "Acceleration Y"
    accel_z:
      name: "Acceleration z"

Ecco avatar Feb 08 '24 01:02 Ecco

@Ecco Thank you so much!

FYI there's a key mismatch in your 6187 between OUTPUT_DATA_RATES in sensor.py and OutputDataRate in da217.h; one uses underscores before HZ but not the other.

rootnegativ1 avatar Feb 11 '24 01:02 rootnegativ1

Sorry to hijack this issue for a slightly off-topic question, but: Could anyone provide a link to a guide on how to flash this light via the serial port? I have connected Vcc, GND, RX and TX to a serial ftdi adapter, but esptool is unable to read/write anything - so any help would be appreciated!

happenpappen avatar Jun 16 '24 10:06 happenpappen

I finally got around to playing with one of mine, and think I have it working "good enough".

As mentioned by others, there are signal issues when LEDs are going at high brightness which effect the touch inputs. I've done the best I can to mitigate them, but there are still quirks, where inputs will be ignored or jump unexpectedly, and there isn't a lot that can be done about it, so what you get here is about as good as it gets unless someone wants to spend a much greater amount of time trying to mitigate the oddities.

Here is the config I came up with. I will not be creating an external component for this, as I don't think it's polished well enough, and I don't desire to spend much more time on it.

esphome:
  on_boot:
    - priority: 600
      then:
        - lambda: !lambda |-
            // Set up accelerometer to detect taps and signal int
            id(i2c_tap_setup).write_byte(0x00, 0xA5);
            id(i2c_tap_setup).write_byte(0x0F, 0x41);
            id(i2c_tap_setup).write_byte(0x10, 0x07);
            id(i2c_tap_setup).write_byte(0x11, 0x00);
            id(i2c_tap_setup).write_byte(0x16, 0x50);
            id(i2c_tap_setup).write_byte(0x19, 0x10);
            id(i2c_tap_setup).write_byte(0x2A, 0x85);
            id(i2c_tap_setup).write_byte(0x2B, 0x02);

i2c:
  sda: GPIO2
  scl: GPIO14
  scan: false
  frequency: 32 kHz # Matches the default firmware

i2c_device:
  - id: i2c_touch_input
    address: 0x2D
  - id: i2c_tap_setup
    address: 0x27

output:
  - platform: esp8266_pwm
    id: output_red
    pin: GPIO15
    max_power: 0.9
    frequency: 500 Hz
  - platform: esp8266_pwm
    id: output_green
    pin: GPIO12
    max_power: 0.85
    frequency: 500 Hz
  - platform: esp8266_pwm
    id: output_blue
    pin: GPIO5
    max_power: 0.85
    frequency: 500 Hz
  - platform: esp8266_pwm
    id: output_warm_white
    pin: GPIO13
    max_power: 0.9
    frequency: 500 Hz

light:
  - platform: rgbw
    id: light_primary
    name: None
    red: output_red
    green: output_green
    blue: output_blue
    white: output_warm_white
    color_interlock: true

binary_sensor:
  - platform: gpio
    id: sensor_tap
    pin:
      number: GPIO4
      mode:
        input: true
        pullup: false
    on_press:
      - light.toggle: light_primary

number:
  - platform: template
    id: touch_input_last_value
    optimistic: true
    min_value: 0
    max_value: 4294967295
    step: 1
    on_value:
      then:
        - lambda: !lambda |-
            uint32_t dec = (int)x;
            if (dec > 0 && (dec & 0xFF00FF) == dec) {
              if ((dec & 0xFF) <= 0x60) {
                //ESP_LOGD("TOUCH RIGHT", "0x%02X", dec & 0xFF);
                id(touch_right_slider)->execute(dec & 0xFF);
              } else {
                //ESP_LOGD("TOUCH LEFT", "0x%02X", dec & 0xFF);
                id(touch_left_slider)->execute(dec & 0xFF);
              }
            } else if (dec > 0 && (dec & 0x00FFFF) == dec) {
              if ((dec & 0xFF) == 0x40) {
                id(touch_button)->execute();
              } else {
                //ESP_LOGD("TOUCH LEFT", "0x%02X", dec & 0xFF);
                id(touch_left_slider)->execute(dec & 0xFF);
              }
            } else if (dec > 0 && dec == 0x800181) {
              //ESP_LOGD("TOUCH LEFT", "0x%02X", dec & 0xFF);
              id(touch_left_slider)->execute(dec & 0xFF);
            }

interval:
  - interval: 200ms
    then:
      - lambda: !lambda |-
          uint8_t read_data[4];

          // Read data
          if (id(i2c_touch_input).read(read_data, sizeof(read_data)) == 0) {
            uint32_t dec = read_data[0] << 16 | read_data[1] << 8 | read_data[2];
            if (id(touch_input_last_value).state != dec) {
              auto call = id(touch_input_last_value).make_call();
              call.set_value(dec);
              call.perform();
            }
            //ESP_LOGI("i2c", "Received: 0x%02X 0x%02X 0x%02X 0x%02X (%i)", read_data[0], read_data[1], read_data[2], read_data[3], dec);
          }

script:
  - id: touch_button
    then:
      - light.toggle: light_primary
  - id: touch_left_slider
    parameters:
      value: int
    then:
      - lambda: !lambda |-
          auto call = id(light_primary).make_call();
          call.set_transition_length(250); // 0.25s
          switch (value) {
            case 0x20: // #1
              call.set_brightness(0.1);
              break;
            case 0x30: // #2
              call.set_brightness(0.15);
              break;
            case 0x10: // #3
              call.set_brightness(0.19);
              break;
            case 0x18: // #4
              call.set_brightness(0.27);
              break;
            case 0x08: // #5
              call.set_brightness(0.35);
              break;
            case 0x0C: // #6
              call.set_brightness(0.43);
              break;
            case 0x04: // #7
              call.set_brightness(0.51);
              break;
            case 0x06: // #8
              call.set_brightness(0.59);
              break;
            case 0x02: // #9
              call.set_brightness(0.67);
              break;
            case 0x03: // #10
              call.set_brightness(0.75);
              break;
            case 0x01: // #11
              call.set_brightness(0.83);
              break;
            case 0x81: // #12
              call.set_brightness(0.91);
              break;
            case 0x80: // #13
              call.set_brightness(1.0);
              break;
            default:
              //ESP_LOGE("LEFT SLIDER", "Invalid Value: 0x%02X", value);
              return;
          }
          call.perform();
          //ESP_LOGD("LEFT SLIDER", "Value: 0x%02X", value);
  - id: touch_right_slider
    parameters:
      value: int
    then:
      - lambda: !lambda |-
          auto call = id(light_primary).make_call();
          call.set_transition_length(0); // 0s
          call.set_color_mode(ColorMode::RGB);
          call.set_white(0);

          // evens are "between" states where it thinks both odds are selected
          // but upon release, it will almost always shift to an odd, so latch
          // evens to the nearest odd to lessen release jumping
          switch (value) {
            case 0x01: // #1
              call.set_color_mode(ColorMode::WHITE);
              call.set_rgb(0, 0, 0);
              call.set_white(1);
              break;
            case 0x03: // #2
            case 0x02: // #3
              call.set_rgb(1.0, 0.8, 0); // yellow
              break;
            case 0x06: // #4
            case 0x04: // #5
              call.set_rgb(1.0, 0, 0.65); // purple
              break;
            case 0x0C: // #6
            case 0x08: // #7
              call.set_rgb(1.0, 0.45, 0); // orange
              break;
            case 0x18: // #8
            case 0x10: // #9
              call.set_rgb(0, 0, 1.0); // blue
              break;
            case 0x30: // #10
            case 0x20: // #11
              call.set_rgb(0, 1.0, 0); // green
              break;
            case 0x60: // #12
            case 0x40: // #13
              call.set_rgb(1.0, 0, 0); // red
              break;
            default:
              //ESP_LOGE("RIGHT SLIDER", "Invalid Value: 0x%02X", value);
              return;
          }
          call.perform();
          //ESP_LOGD("RIGHT SLIDER", "Value: 0x%02X", value);

A couple notes:

  • this config is for control only, make sure to properly fill out your device name, wifi, ota, etc as needed
  • The touch sensor detects 7 unique positions, but has "in-between" states where it thinks two values are both active. For brightness it doesn't make much of a difference, so I just let it do whatever is active at the time, but it will slightly jump upon release. For the color selector side, it is too jarring, so I locked to one direction. There can still be jumping on release, but it should be somewhat tolerable.
  • At high brightness, touch inputs can get stuck beyond our control. I've mitigated as best I can by adjusting output frequency and max_power, you may need to tweak them further.
    • I would not recommend using the color cyan (green+blue) or full RGB white (red+green+blue) as those colors cause the most noise for touch input
    • You can set whatever colors on the color slider you wish (minding the warning above), I just chose some at random.
  • The touch interval is set to 200ms. It can go every loop (0ms), however, it seems to register more double-touches, 200ms was my happy medium, adjust to taste
  • debugging lines are all commented out, uncomment if you want to try to get a better idea of where things might be failing.

Feel free to post if there are any obvious improvements found.

Cossid avatar Oct 19 '25 17:10 Cossid