Open M3te0r opened 8 months ago
Update : Tested out the HS13B-1 pins conf since they seemed to correspond with the control panel wiring, took a LOLIN S3 Mini and a RJ45 connector, and it worked !
I had to adapt some parts of the config to match pins, min/max height and the 3rd preset
Here is my yaml
esphome:
name: flexispot
friendly_name: Flexispot
includes:
- desk_height_sensor.h
esp32:
board: lolin_s3_mini
variant: ESP32S3
framework:
version: latest
platform_version: 6.5.0
type: arduino
# Enable logging
logger:
#level: DEBUG
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: "[REDACTED]"
ota:
password: "[REDACTED]"
uart:
id: desk_uart
baud_rate: 9600
tx_pin: 43
rx_pin: 44
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 60s
- platform: uptime
name: Uptime
- platform: custom
lambda: |-
auto desk_height_sensor = new DeskHeightSensor(id(desk_uart));
App.register_component(desk_height_sensor);
return {desk_height_sensor};
sensors:
id: "desk_height"
name: Desk Height
unit_of_measurement: cm
accuracy_decimals: 1
icon: "mdi:counter"
switch:
- platform: gpio
name: "Virtual Screen"
pin:
number: 33
mode: OUTPUT
restore_mode: ALWAYS_ON
internal: true
- platform: uart
name: "Preset 1"
id: switch_preset1
icon: mdi:numeric-1-box
data: [0x9b, 0x06, 0x02, 0x04, 0x00, 0xac, 0xa3, 0x9d]
uart_id: desk_uart
- platform: uart
name: "Preset 2"
id: switch_preset2
icon: mdi:numeric-2-box
data: [0x9b, 0x06, 0x02, 0x08, 0x00, 0xac, 0xa6, 0x9d]
uart_id: desk_uart
- platform: uart
name: "Preset 3"
id: switch_preset3
icon: mdi:numeric-3-box
data: [0x9b, 0x06, 0x02, 0x10, 0x00, 0xac, 0xac, 0x9d]
uart_id: desk_uart
- platform: uart
name: "Stand" # Not available for all control panels
id: switch_stand
icon: mdi:human-handsup
data: [0x9b, 0x06, 0x02, 0x10, 0x00, 0xac, 0xac, 0x9d]
uart_id: desk_uart
- platform: uart
name: "Up"
id: switch_up
icon: mdi:arrow-up-bold
data: [0x9b, 0x06, 0x02, 0x01, 0x00, 0xfc, 0xa0, 0x9d]
uart_id: desk_uart
internal: true
- platform: uart
name: "Down"
id: switch_down
icon: mdi:arrow-down-bold
data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d]
uart_id: desk_uart
internal: true
- platform: uart
name: "M"
id: switch_m
icon: mdi:alpha-m-circle
data: [0x9b, 0x06, 0x02, 0x20, 0x00, 0xac, 0xb8, 0x9d]
uart_id: desk_uart
- platform: uart
name: "(wake up)" # Not available on all control panels
id: switch_wake_up
icon: mdi:gesture-tap-button
data: [0x9b, 0x06, 0x02, 0x00, 0x00, 0x6c, 0xa1, 0x9d]
uart_id: desk_uart
cover:
- platform: template
# icon: mdi:table-chair
# icon: mdi-human-male-height-variant
name: "Desk"
assumed_state: true
# Move desk up
open_action:
- while:
condition:
sensor.in_range:
id: desk_height
below: "126.9"
then:
- logger.log: "Executing up command"
- switch.turn_on: switch_up
- delay: 10ms
# Move desk down
close_action:
- while:
condition:
sensor.in_range:
id: desk_height
above: "62.21"
then:
- logger.log: "Executing down command"
- switch.turn_on: switch_down
- delay: 10ms
optimistic: true
Question is : I still want to use the keypad and there is only one RJ45 connector on the control block, the ESP32 can be powered on from the +5V, so could I just wire the ESP32 on the keypad PCB, right ?
What are the options if I want to keep the keypad ?
Update 2 Decided to buy 2 RJ45 female terminal connectors to handle the whole thing, looked at the esp32 keypad passthrough, a lot a yaml config files to handle position, cover stop, wake up command for move stop etc
ESP32 | Loctek Controller (E5) | Loctek Motion Cable Color (HS01B-1) |
---|---|---|
GND | GND | Blue |
GPIO44 | RX | Green |
GPIO43 | TX | Black |
GPIO36 | PIN 20 | Red |
ESP32 | Loctek keypad (HS01B-1) | Loctek Motion Cable Color (HS01B-1) |
---|---|---|
GND | Blue (Bridged to GND from controller) | |
RX | Green (Bridged to RX from controller) | |
GPIO35 | TX | Black |
GPIO18 | PIN 20 | Red |
It works great, i get to automate my desk and keep the keypad
I was getting some errors E07, E08 or Rst on the keypad, had to hold the down button till the desk reach the lowest height, but for now seems ok
Sometimes the esp switches or keypad buttons seem to not respond, looks like the esp32 restart itself, don't know why, even with reset_reason didn't get to understand why
esphome:
name: flexispot-2
friendly_name: Flexispot 2
includes:
- desk_height_sensor.h
- desk_keypad.h
on_boot:
priority: -100
then:
- wait_until:
api.connected
# force screen update to get height at api connect
- script.execute: script_start_command
- script.wait: script_start_command
esp32:
board: lolin_s3_mini
variant: ESP32S3
framework:
version: latest
platform_version: 6.5.0
type: arduino
debug:
update_interval: 30s
text_sensor:
- platform: debug
device:
name: "Device Info"
reset_reason:
name: "Reset Reason"
# Enable logging
logger:
level: DEBUG
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: "[REDACTED]"
button:
- platform: restart
name: "Restart ESP32"
binary_sensor:
- platform: gpio
name: "Screen"
id: "screen"
pin: 18
internal: false
on_press:
then:
- switch.turn_on: virtual_screen
on_release:
then:
- switch.turn_off: virtual_screen
script:
- id: screen_timer
mode: restart
then:
# on_start
- logger.log: "Executing screen timer command"
- switch.turn_on: virtual_screen
- delay: 12s # timer length (keypad screen timeout is 10s + 2s buffer)
- if:
condition:
binary_sensor.is_off : screen
then:
- switch.turn_off: virtual_screen
# on_end
- id: script_start_command
mode: restart
then:
- logger.log: "Executing Empty command"
- if:
condition:
switch.is_off : virtual_screen
then:
- script.execute: screen_timer
- delay: 630ms
else:
- script.execute: screen_timer
uart:
- id: desk_uart
baud_rate: 9600
tx_pin: 43
rx_pin: 44
- id: keypad_uart
baud_rate: 9600
tx_pin: 1
rx_pin: 35
sensor:
- platform: internal_temperature
name: "Internal Temperature"
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 60s
- platform: uptime
name: Uptime
- platform: custom
lambda: |-
auto desk_height_sensor = new DeskHeightSensor(id(desk_uart));
App.register_component(desk_height_sensor);
return {desk_height_sensor};
sensors:
id: "desk_height"
name: Desk Height
unit_of_measurement: cm
accuracy_decimals: 1
icon: "mdi:counter"
on_value:
then:
- script.execute: screen_timer
- platform: custom
lambda: |-
auto desk_keypad_sensor = new DeskKeypad(id(keypad_uart));
App.register_component(desk_keypad_sensor);
return {desk_keypad_sensor};
sensors:
id: "desk_command"
name: Desk command
icon: "mdi:counter"
on_value:
then:
lambda: |-
if(!id(keypad_switch).state)
{
if(id(desk_command).state == 1)
{
id(desk).make_call().set_command_open().perform();
} else if(id(desk_command).state == 2)
{
id(desk).make_call().set_command_close().perform();
} else if(id(desk_command).state == 3)
{
id(switch_preset1).turn_on();
} else if(id(desk_command).state == 4)
{
id(switch_preset2).turn_on();
} else if(id(desk_command).state == 5)
{
id(switch_preset3).turn_on();
} else if(id(desk_command).state == 6)
{
id(switch_m).turn_on();
} else if(id(desk_command).state == 7)
{
id(switch_alarm).turn_on();
} else if(id(desk_command).state == 8)
{
id(desk).make_call().set_command_stop().perform();
}
}
switch:
- platform: template
name: "Alarm"
id: switch_alarm
icon: mdi:alpha-m-circle
turn_on_action:
- logger.log: "Executing Alarm command"
# - script.execute: script_start_command
# - script.wait: script_start_command
# - uart.write:
# id: desk_uart
# data: [0x9b, 0x06, 0x02, 0x40, 0x00, 0xac, 0x90, 0x9d]
internal: false
- platform: template
name: "Keypad locked"
icon: mdi:key
id: "keypad_switch"
internal: false
restore_mode: RESTORE_DEFAULT_OFF
assumed_state: false
optimistic: true
- platform: gpio
name: "Virtual Screen"
id: "virtual_screen"
pin:
number: 36
mode: OUTPUT
restore_mode: ALWAYS_OFF
internal: false
- platform: template
name: "Preset 1"
id: switch_preset1
icon: mdi:numeric-1-box
turn_on_action:
- logger.log: "Executing Preset 1 command"
- script.execute: script_start_command
- script.wait: script_start_command
- uart.write:
id: desk_uart
data: [0x9b, 0x06, 0x02, 0x04, 0x00, 0xac, 0xa3, 0x9d]
internal: false
- platform: template
name: "Preset 2"
id: switch_preset2
icon: mdi:numeric-2-box
turn_on_action:
- logger.log: "Executing Preset 2 command"
- script.execute: script_start_command
- script.wait: script_start_command
- uart.write:
id: desk_uart
data: [0x9b, 0x06, 0x02, 0x08, 0x00, 0xac, 0xa6, 0x9d]
internal: false
- platform: template
name: "Preset 3"
id: switch_preset3
icon: mdi:numeric-3-box
turn_on_action:
- logger.log: "Executing Preset 3 command"
- script.execute: script_start_command
- script.wait: script_start_command
- uart.write:
id: desk_uart
data: [0x9b, 0x06, 0x02, 0x10, 0x00, 0xac, 0xac, 0x9d]
internal: false
- platform: uart
name: "Stand" # Not available for all control panels
id: switch_stand
icon: mdi:human-handsup
data: [0x9b, 0x06, 0x02, 0x10, 0x00, 0xac, 0xac, 0x9d]
uart_id: desk_uart
- platform: uart
name: "Up"
id: switch_up
icon: mdi:arrow-up-bold
data: [0x9b, 0x06, 0x02, 0x01, 0x00, 0xfc, 0xa0, 0x9d]
uart_id: desk_uart
internal: true
- platform: uart
name: "Down"
id: switch_down
icon: mdi:arrow-down-bold
data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d]
uart_id: desk_uart
internal: true
- platform: uart
name: "M"
id: switch_m
icon: mdi:alpha-m-circle
data: [0x9b, 0x06, 0x02, 0x20, 0x00, 0xac, 0xb8, 0x9d]
uart_id: desk_uart
- platform: uart
name: "(wake up)" # Not available on all control panels
id: switch_wake_up
icon: mdi:gesture-tap-button
data: [0x9b, 0x06, 0x02, 0x00, 0x00, 0x6c, 0xa1, 0x9d]
uart_id: desk_uart
#MANUAL RESET
#HOLD THE DOWN BUTTON UNTIL THE TABLE REACHES ITS LOWEST HEIGHT AND REBOUNDS
#MIGHT NEED TO BE RUN MULTIPLE TIMES DEPENDING ON THE HEIGHT
- platform: uart
name: "Factory Reset" # Hold Down 5secs
id: switch_factory_reset
icon: mdi:factory
data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d]
uart_id: desk_uart
send_every: 1ms
on_turn_on:
- delay: 5000ms
- switch.turn_off: switch_factory_reset
cover:
- platform: template
icon: mdi:table-chair
# icon: mdi-human-male-height-variant
name: "Desk"
id: "desk"
assumed_state: true
has_position: true
# set current position percent
lambda: return (float(id(desk_height).state) - float(62.1)) / (float(126.9) - float(62.1));
# target height mode
position_action:
- script.execute: script_start_command
- script.wait: script_start_command
# find if we are going up or down
- if:
condition:
lambda: return float(id(desk).position) < pos;
then:
- while:
condition:
# if going up, offset current position to 2 percent higher than reality and loop
lambda: return (float(id(desk).position) + 0.02) < pos;
then:
- cover.template.publish:
id: desk
current_operation: OPENING
#- logger.log: "Executing up command"
- switch.turn_on: switch_up
- delay: 400ms
else:
- while:
condition:
# if going down, offset current position to 2 percent lower than reality and loop
lambda: return (float(id(desk).position) - 0.02) > pos;
then:
- cover.template.publish:
id: desk
current_operation: CLOSING
- switch.turn_on: switch_down
- delay: 400ms
# clear the command queue with wake up command - https://github.com/iMicknl/LoctekMotion_IoT/issues/42#issuecomment-1416823108
- switch.turn_on: switch_wake_up
# publish idle status
- cover.template.publish:
id: desk
current_operation: IDLE
# Move desk up
open_action:
- script.execute: script_start_command
- script.wait: script_start_command
- while:
condition:
sensor.in_range:
id: desk_height
below: 126.9
then:
- logger.log: "Executing up command"
- cover.template.publish:
id: desk
current_operation: OPENING
- switch.turn_on: switch_up
- delay: 400ms
# clear the command queue with wake up command - https://github.com/iMicknl/LoctekMotion_IoT/issues/42#issuecomment-1416823108
- switch.turn_on: switch_wake_up
- cover.template.publish:
id: desk
state: OPEN
current_operation: IDLE
# Move desk down
close_action:
- script.execute: script_start_command
- script.wait: script_start_command
- while:
condition:
sensor.in_range:
id: desk_height
above: 62.1
then:
- logger.log: "Executing down command"
- cover.template.publish:
id: desk
current_operation: CLOSING
- switch.turn_on: switch_down
- delay: 400ms
# clear the command queue with wake up command - https://github.com/iMicknl/LoctekMotion_IoT/issues/42#issuecomment-1416823108
- switch.turn_on: switch_wake_up
- cover.template.publish:
id: desk
state: CLOSED
current_operation: IDLE
# Stop Button
stop_action:
- logger.log: "Executing stop command"
- switch.turn_on: switch_wake_up
- cover.template.publish:
id: desk
current_operation: IDLE
optimistic: false
I'm glad to see I'm not the only one triying to work with this specific interface.
I'm triying to make a "men in the middle" with an arduino mega, just to know how everything is moving (also, this is my first electronics experiment)
Hey @M3te0r,
I have the same controller, but my desks stops when sending one down or up command (0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d). When moving the desk it stops between movements, making the move unsteady. Do you also have the same issue?
Im using an ESP8266 ESP-12F NodeMcu
board.
Hi @Paulomart The up/down commands have the same behaviour as the physical up/down button, a single slighty hold push will wake up the terminal and send a single up/down command, a longer push hold will continuously send the commands until you release the button
To simulate that hold behaviour you have to loop through a cycle of wake up, up/down, that's the intent behind the cover
template, take a look at the open_action
you might have to fine tune the delay, don't go too short or it will spam the terminal and you'll need to reset the controller
@M3te0r thanks I got it to work that way.
An issue I was facing: the sensor for the height was firing to often. I debounced the sensor and that seemed to help with smoother movement.
Here is my final setup:
api:
encryption:
key: "xxxxxxx"
ota:
- platform: esphome
password: "xxxxxxxx"
substitutions:
min_height: "64" # cm
max_height: "124" # cm
screen_pin: D2
tx_pin: D5
rx_pin: D6
friendly_name: "Office 1 Desk 1"
name: "office-1-desk-1"
esphome:
name: ${name}
friendly_name: ${friendly_name}
includes:
- desk_height_sensor.h
on_boot:
priority: -10
then:
- switch.turn_on: switch_wake_up
external_components:
source: github://iMicknl/LoctekMotion_IoT@v2
components: [ loctekmotion_desk_height ]
logger:
esp8266:
board: nodemcuv2
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "recover me ${friendly_name}"
captive_portal:
uart:
id: desk_uart
baud_rate: 9600
tx_pin: ${tx_pin}
rx_pin: ${rx_pin}
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 60s
- platform: uptime
name: Uptime
- platform: loctekmotion_desk_height
id: "desk_height"
name: Desk Height
filters:
- clamp:
min_value: ${min_height}
max_value: ${max_height}
ignore_out_of_range: true
- debounce: 10ms
on_value_range:
- below: ${min_height}
then:
- switch.turn_off: switch_down
- above: ${max_height}
then:
- switch.turn_off: switch_up
on_value:
then:
- component.update: set_desk_height
button:
- platform: uart
name: "Step Up"
id: button_up
icon: mdi:arrow-up-bold
data: [0x9b, 0x06, 0x02, 0x01, 0x00, 0xfc, 0xa0, 0x9d]
uart_id: desk_uart
- platform: uart
name: "Step Down"
id: button_down
icon: mdi:arrow-down-bold
data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d]
uart_id: desk_uart
switch:
- platform: gpio
name: "Virtual Screen"
pin:
number: ${screen_pin}
mode: OUTPUT
restore_mode: ALWAYS_ON
internal: true
- platform: uart
name: "Up"
id: switch_up
icon: mdi:arrow-up-bold
data: [0x9b, 0x06, 0x02, 0x01, 0x00, 0xfc, 0xa0, 0x9d]
uart_id: desk_uart
send_every: 1ms
on_turn_on:
then:
- switch.turn_off: switch_down
internal: true
- platform: uart
name: "Down"
id: switch_down
icon: mdi:arrow-down-bold
data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d]
uart_id: desk_uart
send_every: 1ms
on_turn_on:
then:
- switch.turn_off: switch_up
internal: true
- platform: uart
name: "(wake up)" # Not available on all control panels
id: switch_wake_up
icon: mdi:gesture-tap-button
data: [0x9b, 0x06, 0x02, 0x00, 0x00, 0x6c, 0xa1, 0x9d]
uart_id: desk_uart
internal: true
cover:
- platform: template
id: desk_cover
icon: mdi:table-chair
name: "Desk"
assumed_state: true
optimistic: true
# Move desk up
open_action:
- if:
condition:
- switch.is_on: switch_down
then:
- switch.turn_off: switch_down
- delay: 500ms
- switch.turn_on: switch_up
# Move desk down
close_action:
- if:
condition:
- switch.is_on: switch_up
then:
- switch.turn_off: switch_up
- delay: 500ms
- switch.turn_on: switch_down
stop_action:
then:
- switch.turn_off: switch_down
- switch.turn_off: switch_up
number:
- platform: template
name: "Desk Height"
id: set_desk_height
min_value: ${min_height}
max_value: ${max_height}
icon: "mdi:counter"
unit_of_measurement: "cm"
device_class: "distance"
step: 0.1
lambda: !lambda |-
return id(desk_height).state;
set_action:
- if:
condition:
- lambda: !lambda |-
return x > id(desk_height).state;
then:
# direction up
- cover.open: desk_cover
- wait_until:
lambda: |-
return id(desk_height).state >= x - 1;
- cover.stop: desk_cover
- delay: 1s
# move a little down again to adjust for momentum
- uart.write:
id: desk_uart
data: [0x9b, 0x06, 0x02, 0x02, 0x00, 0x0c, 0xa0, 0x9d] # down
else:
# direction down
- cover.close: desk_cover
- wait_until:
lambda: |-
return id(desk_height).state <= x + 3;
- cover.stop: desk_cover
- delay: 1s
# move a little up again to adjust for momentum
- uart.write:
id: desk_uart
data: [0x9b, 0x06, 0x02, 0x01, 0x00, 0xfc, 0xa0, 0x9d] # up
Hi, Do you know if the HS11A-1C0 + CB38M2H(PB)-1 combo is compatible? It has one RJ45 cable going from the control block to the control panel Thanks!