Desky Standing Desk (ESPHome) [Works with Desky, Uplift, Jiecang, Assmann & others]

Can you measure 5V on the relevant power wires with a multimeter?

Which desk do you have?

You could also try another Esp, especially if it was a cheap clone.

Also triple check all of your connections and solder where possible.

1 Like

I dont have a multimeter, the only boards i have are the cheap d1 mini clones - i see you mentioned moving to diguno i have 2 of those but not sure of the wiring

desk is an uplift v2 from 2021

Hey getting some errors updating to ESPHome 2023.12.0 about pins being used multiple times, so cannot update.

Some breaking change introduced since pre 2012.12?

It’s a new validation. You shouldn’t be doing that.

ah, ok i have no idea what its referring to, though. The GUI is reffereing to four different places where gpio is red underlined and its referring to pin 4 and pin 5, twice.

these 2:

output:
  - platform: gpio
    pin: ${desky_up_pin}
    id: up_green_wire
    inverted: true
  - platform: gpio
    pin: ${desky_down_pin}
    id: down_yellow_wire
    inverted: true

and

#Raise the desk 
  - platform: gpio
    id: raise_desk
    name: "Raise Desk"
    pin:
      number: D2
      # mode: INPUT_PULLUP
      inverted: true
    interlock: lower_desk
    on_turn_on:
    #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: raise_desk
#Lower the desk 
  - platform: gpio
    id: lower_desk
    name: "Lower Desk" 
    pin:
      number: D1
      # mode: INPUT_PULLUP
      inverted: true
    interlock: raise_desk
    on_turn_on:
My Entire yaml
esphome:
  name: bdi-standing-desk
  friendly_name: BDI Standing Desk
  on_boot:
    priority: -100.0
    then:
    #Request a desk height update after boot.
      - delay: 5s
      - switch.turn_on: wake_desk_and_get_height

substitutions:
  #Use your own ESP pin values
  desky_request_height_pin: GPIO14 #Request desk height | white wire  
  desky_purple_pin: GPIO13 #purple wire  
  desky_down_pin: GPIO05 #Move desk down | yellow wire  
  desky_up_pin: GPIO04  #Move desk up | green wire  

output:
  - platform: gpio
    pin: ${desky_up_pin}
    id: up_green_wire
    inverted: true
  - platform: gpio
    pin: ${desky_down_pin}
    id: down_yellow_wire
    inverted: true
  - platform: gpio
    pin: ${desky_purple_pin}
    id: purple_wire
    inverted: true

esp8266:
  board: d1_mini
  early_pin_init: False

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "[REDACT]"

ota:
  password: "[REDACT]"

## For Memory Sensor (debug platform in sensor)
debug:
  update_interval: 30s

sensor:
  # Sensors
  - platform: uptime
    name: "Desky Uptime"
  - platform: wifi_signal
    name: "Desky WiFi Signal"
    update_interval: 60s
  - platform: debug
    free:
      name: "Heap Free"
    fragmentation:
      name: "Heap Fragmentation"
    block:
      name: "Heap Max Block"
    loop_time:
      name: "Loop Time"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Bdi-Standing-Desk"
    password: "vdJyTtjMWGrb"

captive_portal:

####################################################################################################
##Notes/Info
####################################################################################################

## Home Assistant Thread: https://community.home-assistant.io/t/desky-standing-desk/383790/3
## ssieb who generously donated his time and knowledge to developing the custom component may offer some support on the Discord thread (please read both threads first).
## https://discord.com/channels/429907082951524364/952464939480645642

#Notes:
# 1. Use this component at own risk. It has not had extensive testing. May void warranty or cause desk faults etc.
# 2. This controller may bypass desk safety features like collision detection.
# 3. This component doesn't know about the values stored in your desk. Values in this config are (and must be) set independently.
# 4. ssieb's solution may be a lot simpler and cleaner for most people. I've cobbled together some more features in this config because I can't programn in C++.


#Troubleshooting Tips: 
#If you ever get a flashing ASr message, you might need to reset your desk.
#https://desky.com.au/blogs/news/reset-standing-desk-control-panel#:~:text=When%20ready%2C%20press%20and%20hold,Hooray!


#TODO 
#Ask ssieb to make change requests (move logic to component code)
  # Invert pins
  # Get Desk Height On Boot
  # Interlock Up/Down Pins (If not done already)
  # Interrupt/stop movement function (Stop desk motion)

#other
  # Test collision detection
  # Limit external component fetch to just desky? 
  # Fix Desk Is moving on Boot.

external_components:
#Fetch ssieb's custom component# https://github.com/ssieb/custom_components/tree/master/components/desky
  - source:
      type: git
      url: https://github.com/ssieb/custom_components
    components: [ desky ]

uart:
  - id: desk_uart
    baud_rate: 9600
    rx_pin: 1 #Labelled TX on my D1mini clone (mislabelled?)
    ##You can uncomment the debug section below to see UART messages.
    # debug:
      # direction: RX
      # dummy_receiver: true
      # after:
        # bytes: 4
      # sequence:     
        # - lambda: UARTDebug::log_int(direction, bytes, ',');
 
desky:
  id: my_desky
  ####################################################################################
  ##Uncomment this block to use Ssieb's move_to componet function.
  # up:    
    # number: 4 #D2
    # inverted: true 
  # down:  
    # number: 5 #D1
    # inverted: true
  # stopping_distance: 15  # optional distance from target to turn off moving, default 15  
  ####################################################################################
  height:  # Sensor publishing the current height
    name: Desky Height
    id: desky_height
    accuracy_decimals: 1
    unit_of_measurement: cm
    #any other sensor options
    filters:
    - delta: 0.05 #Only send values to HA if they change
    - throttle: 200ms #Limit values sent to Ha to 5 per sec.
    - multiply: 0.1 #convert from mm to cm
    on_value:
      then:
          #If the value changes, then the desk is moving
        - binary_sensor.template.publish:
            id: desky_is_moving
            state: ON
        - delay: 300ms
          #Assume it's stopped moving if no height changes after a short time.
        - binary_sensor.template.publish:
            id: desky_is_moving
            state: Off
            
binary_sensor:
  - platform: template
    id: desky_is_moving
    name: "Desky Is Moving"
    filters:
      - delayed_off: 400ms
    #If the desk isn't moving for a bit we better turn off attempts at movement. It's like poor man's collision detection? 
    on_release:
      then:
        - button.press: desky_stop_desk

button: 
#Stop movement 
  - platform: template
    name: Stop Desk
    id: desky_stop_desk
    on_press:
      then:
        - switch.turn_off: raise_desk
        - switch.turn_off: lower_desk
# Combination Buttons
  - platform: template
    name: Desky Button 1
    id: button_1
    on_press:
      then:
        - output.turn_on: up_green_wire
        - output.turn_on: down_yellow_wire
        - delay: 300ms
        - output.turn_off: down_yellow_wire
        - output.turn_off: up_green_wire
  - platform: output
    output: purple_wire
    name: Desky Button 2
    id: button_2
    duration: 300ms
  - platform: template
    name: Desky Button 3
    id: button_3
    on_press:
      then:
        - output.turn_on: purple_wire
        - output.turn_on: down_yellow_wire
        - delay: 300ms
        - output.turn_off: down_yellow_wire
        - output.turn_off: purple_wire
  - platform: template
    name: Desky Button 4
    id: button_4
    on_press:
      then:
        - output.turn_on: purple_wire
        - output.turn_on: up_green_wire
        - delay: 300ms
        - output.turn_off: up_green_wire
        - output.turn_off: purple_wire

#Move to function
  - platform: template
    name: Go To Desky Height x
    id: go_to_desky_preset_height_x
    on_press:
      then:
      ##Option 1: Uncomment to use Ssieb's move_to componet functions
        # - lambda: id(my_desky).move_to(id(desky_target_height).state*10);  
 
      ##Option 2: Uncomment to use Mahko's lambda alternative 
      #Check if we need to move desk up or down from current position      
        if:
          condition:
          #Current height is more than target height, then move desk down
            lambda: |-
              return id(desky_target_height).state < id(desky_height).state;
          then:
            - switch.turn_on: lower_desk
            - wait_until:
              #Run until the difference between current and target state is < stopping distance 
                condition:
                  lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
            - switch.turn_off: lower_desk
          else:
          #Current height is less than target height, move desk up
            - switch.turn_on: raise_desk
            - wait_until:
                condition:
                  lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
                  #Run until the difference between current and target state is <0.3cm
            - switch.turn_off: raise_desk

number:
#Target Height ("Move desk to height x").
    #You should probably limit the range you can move the desk to to within the limits you've set via the control panel, perhaps offset a little within the range.
    #Sending commands higher/lower than this may cause error messages and require desk reset (or worse).
  - platform: template
    id: desky_target_height
    name: "Desky Target Height"
    optimistic: true
    unit_of_measurement: cm
    min_value: 65.0 
    max_value: 122.0
    step: 0.1
    
#Offset correction - Adjust until you get the best accuracy. 
#The desk keeps moving for a little while after the up/down pins are released and we try to account for this.
#1.5cm was about right on mine
  - platform: template
    name: "Desky Stopping Distance cm"
    id: stopping_distance_cm
    unit_of_measurement: cm
    optimistic: true
    min_value: 0
    max_value: 2
    step: 0.1
    restore_value: true
    initial_value: 1.5
    
###############################################
#Define some preset heights.
###############################################
#You can freely define as many adjustable presets as you like.
#These are all seperate/independant of what you've set via the control panel (we can't retrieve them currently).
 
#Standing Height #1 - Set a standing height. 
  - platform: template
    id: desky_standing_height_1
    name: "Standing Height 1"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 110
    max_value: 120
    step: 0.1
    restore_value: true
    initial_value: 115

#Standing Height #1 - Set a standing height. 
  - platform: template
    id: desky_standing_height_2
    name: "Standing Height 2"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 115
    max_value: 125
    step: 0.1
    restore_value: true
    initial_value: 120
  
#Sitting Height #1 - Set a sitting height. This is independant of what you've set via the control panel.
  - platform: template
    id: desky_sitting_height_1
    name: "Sitting Height 1"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 65
    max_value: 69
    step: 0.1
    restore_value: true
    initial_value: 67.0

#Sitting Height #2 - Set a sitting height. This is independant of what you've set via the control panel.
  - platform: template
    id: desky_sitting_height_2
    name: "Sitting Height 2"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 72.6
    max_value: 82.6
    step: 0.1
    restore_value: true
    initial_value: 77.6
      
switch:
#wake up ther desk and request it sends its height 
  - platform: gpio
    id: wake_desk_and_get_height
    name: "Request Desk Height"
    pin:
      number: D5
      inverted: true
    on_turn_on:
    - delay: 100ms
    - switch.turn_off: wake_desk_and_get_height
  - platform: restart
    name: "Desky Restart"

#Raise the desk 
  - platform: gpio
    id: raise_desk
    name: "Raise Desk"
    pin:
      number: D2
      # mode: INPUT_PULLUP
      inverted: true
    interlock: lower_desk
    on_turn_on:
    #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: raise_desk
#Lower the desk 
  - platform: gpio
    id: lower_desk
    name: "Lower Desk" 
    pin:
      number: D1
      # mode: INPUT_PULLUP
      inverted: true
    interlock: raise_desk
    on_turn_on:
   #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: lower_desk

D1 and D2 are the same as GPIO5 and GPIO4. You have the pins defined as outputs and also as switches. Use one or the other.

1 Like

ahh. not sure I can do that easily :slight_smile:

maybe code might have to rewritten.

what if I just added allow_other_uses: true to the 2 offending pins?

EDIT: the above won’t fix the output of the pins. OK, not easy fix for me.

1 Like

I think my example config used pins twice.

Quite possibly it was bad practice I implemented.

Probably a hacky solution to have the custom component, some up/down switches, and the presets all working in parallel from memory.

Likely needs review. Best solution may be to address at the custom component level (feature request to merge up/down switches and memory presets into custom component)

I can take a look at this at some point but it’s unlikely to be for a few weeks.

Edit: You could (but possibly not should) bypass it with allow_other_uses:

Edit 2: I see you’ve tried that. Possibly it needs to be added to 3 places, including the custom component pin definition?

thanks! it was suggested that I remove the output section and change the output to switches, which I did in this version but it still gives those validation errors on pins 4 and 5 error on lines 343, 356, 369 and 373, but pin D2 == GPIO4 may also be reused.:

Here’s my moodified.yaml

Updated yaml
esphome:
  name: bdi-standing-desk
  friendly_name: BDI Standing Desk
  on_boot:
    priority: -100.0
    then:
    #Request a desk height update after boot.
      - delay: 5s
      - switch.turn_on: wake_desk_and_get_height

substitutions:
  #Use your own ESP pin values
  desky_request_height_pin: GPIO14 #Request desk height | white wire  
  desky_purple_pin: GPIO13 #purple wire  
  desky_down_pin: GPIO05 #Move desk down | yellow wire  
  desky_up_pin: GPIO04  #Move desk up | green wire  

esp8266:
  board: d1_mini
  early_pin_init: False

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "REDACTED"

ota:
  password: "REDACTED"

## For Memory Sensor (debug platform in sensor)
debug:
  update_interval: 30s

sensor:
  # Sensors
  - platform: uptime
    name: "Desky Uptime"
  - platform: wifi_signal
    name: "Desky WiFi Signal"
    update_interval: 60s
  - platform: debug
    free:
      name: "Heap Free"
    fragmentation:
      name: "Heap Fragmentation"
    block:
      name: "Heap Max Block"
    loop_time:
      name: "Loop Time"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Bdi-Standing-Desk"
    password: "REDACTED"

captive_portal:

####################################################################################################
##Notes/Info
####################################################################################################

## Home Assistant Thread: https://community.home-assistant.io/t/desky-standing-desk/383790/3
## ssieb who generously donated his time and knowledge to developing the custom component may offer some support on the Discord thread (please read both threads first).
## https://discord.com/channels/429907082951524364/952464939480645642

#Notes:
# 1. Use this component at own risk. It has not had extensive testing. May void warranty or cause desk faults etc.
# 2. This controller may bypass desk safety features like collision detection.
# 3. This component doesn't know about the values stored in your desk. Values in this config are (and must be) set independently.
# 4. ssieb's solution may be a lot simpler and cleaner for most people. I've cobbled together some more features in this config because I can't programn in C++.


#Troubleshooting Tips: 
#If you ever get a flashing ASr message, you might need to reset your desk.
#https://desky.com.au/blogs/news/reset-standing-desk-control-panel#:~:text=When%20ready%2C%20press%20and%20hold,Hooray!


#TODO 
#Ask ssieb to make change requests (move logic to component code)
  # Invert pins
  # Get Desk Height On Boot
  # Interlock Up/Down Pins (If not done already)
  # Interrupt/stop movement function (Stop desk motion)

#other
  # Test collision detection
  # Limit external component fetch to just desky? 
  # Fix Desk Is moving on Boot.

external_components:
#Fetch ssieb's custom component# https://github.com/ssieb/custom_components/tree/master/components/desky
  - source:
      type: git
      url: https://github.com/ssieb/custom_components
    components: [ desky ]

uart:
  - id: desk_uart
    baud_rate: 9600
    rx_pin: 1 #Labelled TX on my D1mini clone (mislabelled?)
    ##You can uncomment the debug section below to see UART messages.
    # debug:
      # direction: RX
      # dummy_receiver: true
      # after:
        # bytes: 4
      # sequence:     
        # - lambda: UARTDebug::log_int(direction, bytes, ',');
 
desky:
  id: my_desky
  ####################################################################################
  ##Uncomment this block to use Ssieb's move_to componet function.
  # up:    
    # number: 4 #D2
    # inverted: true 
  # down:  
    # number: 5 #D1
    # inverted: true
  # stopping_distance: 15  # optional distance from target to turn off moving, default 15  
  ####################################################################################
  height:  # Sensor publishing the current height
    name: Desky Height
    id: desky_height
    accuracy_decimals: 1
    unit_of_measurement: cm
    #any other sensor options
    filters:
    - delta: 0.05 #Only send values to HA if they change
    - throttle: 200ms #Limit values sent to Ha to 5 per sec.
    - multiply: 0.1 #convert from mm to cm
    on_value:
      then:
          #If the value changes, then the desk is moving
        - binary_sensor.template.publish:
            id: desky_is_moving
            state: ON
        - delay: 300ms
          #Assume it's stopped moving if no height changes after a short time.
        - binary_sensor.template.publish:
            id: desky_is_moving
            state: Off
            
binary_sensor:
  - platform: template
    id: desky_is_moving
    name: "Desky Is Moving"
    filters:
      - delayed_off: 400ms
    #If the desk isn't moving for a bit we better turn off attempts at movement. It's like poor man's collision detection? 
    on_release:
      then:
        - button.press: desky_stop_desk

button: 
#Stop movement 
  - platform: template
    name: Stop Desk
    id: desky_stop_desk
    on_press:
      then:
        - switch.turn_off: raise_desk
        - switch.turn_off: lower_desk
# Combination Buttons
  - platform: template
    name: Desky Button 1
    id: button_1
    on_press:
      then:
        - switch.turn_on: up_green_wire
        - switch.turn_on: down_yellow_wire
        - delay: 300ms
        - switch.turn_off: down_yellow_wire
        - switch.turn_off: up_green_wire
  - platform: template
    name: Desky Button 2
    id: button_2
    on_press:
      then:
        - switch.turn_on: purple_wire
        - delay: 300ms
        - switch.turn_off: purple_wire
  - platform: template
    name: Desky Button 3
    id: button_3
    on_press:
      then:
        - switch.turn_on: purple_wire
        - switch.turn_on: down_yellow_wire
        - delay: 300ms
        - switch.turn_off: down_yellow_wire
        - switch.turn_off: purple_wire
  - platform: template
    name: Desky Button 4
    id: button_4
    on_press:
      then:
        - switch.turn_on: purple_wire
        - switch.turn_on: up_green_wire
        - delay: 300ms
        - switch.turn_off: up_green_wire
        - switch.turn_off: purple_wire

#Move to function
  - platform: template
    name: Go To Desky Height x
    id: go_to_desky_preset_height_x
    on_press:
      then:
      ##Option 1: Uncomment to use Ssieb's move_to componet functions
        # - lambda: id(my_desky).move_to(id(desky_target_height).state*10);  
 
      ##Option 2: Uncomment to use Mahko's lambda alternative 
      #Check if we need to move desk up or down from current position      
        if:
          condition:
          #Current height is more than target height, then move desk down
            lambda: |-
              return id(desky_target_height).state < id(desky_height).state;
          then:
            - switch.turn_on: lower_desk
            - wait_until:
              #Run until the difference between current and target state is < stopping distance 
                condition:
                  lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
            - switch.turn_off: lower_desk
          else:
          #Current height is less than target height, move desk up
            - switch.turn_on: raise_desk
            - wait_until:
                condition:
                  lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
                  #Run until the difference between current and target state is <0.3cm
            - switch.turn_off: raise_desk

number:
#Target Height ("Move desk to height x").
    #You should probably limit the range you can move the desk to to within the limits you've set via the control panel, perhaps offset a little within the range.
    #Sending commands higher/lower than this may cause error messages and require desk reset (or worse).
  - platform: template
    id: desky_target_height
    name: "Desky Target Height"
    optimistic: true
    unit_of_measurement: cm
    min_value: 65.0 
    max_value: 122.0
    step: 0.1
    
#Offset correction - Adjust until you get the best accuracy. 
#The desk keeps moving for a little while after the up/down pins are released and we try to account for this.
#1.5cm was about right on mine
  - platform: template
    name: "Desky Stopping Distance cm"
    id: stopping_distance_cm
    unit_of_measurement: cm
    optimistic: true
    min_value: 0
    max_value: 2
    step: 0.1
    restore_value: true
    initial_value: 1.5
    
###############################################
#Define some preset heights.
###############################################
#You can freely define as many adjustable presets as you like.
#These are all seperate/independant of what you've set via the control panel (we can't retrieve them currently).
 
#Standing Height #1 - Set a standing height. 
  - platform: template
    id: desky_standing_height_1
    name: "Standing Height 1"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 110
    max_value: 120
    step: 0.1
    restore_value: true
    initial_value: 115

#Standing Height #1 - Set a standing height. 
  - platform: template
    id: desky_standing_height_2
    name: "Standing Height 2"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 115
    max_value: 125
    step: 0.1
    restore_value: true
    initial_value: 120
  
#Sitting Height #1 - Set a sitting height. This is independant of what you've set via the control panel.
  - platform: template
    id: desky_sitting_height_1
    name: "Sitting Height 1"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 65
    max_value: 69
    step: 0.1
    restore_value: true
    initial_value: 67.0

#Sitting Height #2 - Set a sitting height. This is independant of what you've set via the control panel.
  - platform: template
    id: desky_sitting_height_2
    name: "Sitting Height 2"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 72.6
    max_value: 82.6
    step: 0.1
    restore_value: true
    initial_value: 77.6
      
switch:
#wake up ther desk and request it sends its height 
  - platform: gpio
    id: wake_desk_and_get_height
    name: "Request Desk Height"
    pin:
      number: D5
      inverted: true
    on_turn_on:
    - delay: 100ms
    - switch.turn_off: wake_desk_and_get_height
  - platform: restart
    name: "Desky Restart"

#Raise the desk 
  - platform: gpio
    id: raise_desk
    name: "Raise Desk"
    pin:
      number: D2
      # mode: INPUT_PULLUP
      inverted: true
    interlock: lower_desk
    on_turn_on:
    #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: raise_desk
#Lower the desk 
  - platform: gpio
    id: lower_desk
    name: "Lower Desk" 
    pin:
      number: D1
      # mode: INPUT_PULLUP
      inverted: true
    interlock: raise_desk
    on_turn_on:
   #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: lower_desk

  - platform: gpio
    pin: ${desky_up_pin}
    id: up_green_wire
    inverted: true
  - platform: gpio
    pin: ${desky_down_pin}
    id: down_yellow_wire
    inverted: true
  - platform: gpio
    pin: ${desky_purple_pin}
    id: purple_wire
    inverted: true

D1 is GPIO5 and D2 is GPIO4.

So id: up_green_wire is basically a duplicate of id: raise_desk and down_yellow_wire of id: lower_desk. The switches duplicate functionality and cause the conflict.

This was bad design on my part when implementing the memory preset feature.

So some refactoring is required through the config to just define the up/down switch once and repoint things to use it throughout.

Just on mobile on hols so can’t help much with specifics ATM.

thanks @Mahko_Mahko ! I was able to get some more help from others, especially @firstof9 and members in the ESPHome Discord to fix it. This yaml seems to retain all functionality and obey all the pin re-use rules.

I kept getting into a loop of fixing one thing, and getting another issue so I couldn’t really excute the fix myself.

Have a look below, if you wish. Cheers

New updated yaml
esphome:
  name: bdi-standing-desk
  friendly_name: BDI Standing Desk
  on_boot:
    priority: -100.0
    then:
    #Request a desk height update after boot.
      - delay: 5s
      - switch.turn_on: wake_desk_and_get_height

substitutions:
  #Use your own ESP pin values
  # Use pin lables like god intended
  #desky_request_height_pin: D5 #Request desk height | white wire  
  desky_purple_pin: D7 #purple wire  
  #desky_down_pin: D1 #Move desk down | yellow wire  
  #desky_up_pin: D2  #Move desk up | green wire  

esp8266:
  board: d1_mini
  early_pin_init: False

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "[REDACTED]"

ota:
  password: "[REDACTED]"

## For Memory Sensor (debug platform in sensor)
debug:
  update_interval: 30s

sensor:
  # Sensors
  - platform: uptime
    name: "Desky Uptime"
  - platform: wifi_signal
    name: "Desky WiFi Signal"
    update_interval: 60s
  - platform: debug
    free:
      name: "Heap Free"
    fragmentation:
      name: "Heap Fragmentation"
    block:
      name: "Heap Max Block"
    loop_time:
      name: "Loop Time"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Bdi-Standing-Desk"
    password: "[REDACTED]"

captive_portal:

####################################################################################################
##Notes/Info
####################################################################################################

## Home Assistant Thread: https://community.home-assistant.io/t/desky-standing-desk/383790/3
## ssieb who generously donated his time and knowledge to developing the custom component may offer some support on the Discord thread (please read both threads first).
## https://discord.com/channels/429907082951524364/952464939480645642

#Notes:
# 1. Use this component at own risk. It has not had extensive testing. May void warranty or cause desk faults etc.
# 2. This controller may bypass desk safety features like collision detection.
# 3. This component doesn't know about the values stored in your desk. Values in this config are (and must be) set independently.
# 4. ssieb's solution may be a lot simpler and cleaner for most people. I've cobbled together some more features in this config because I can't programn in C++.


#Troubleshooting Tips: 
#If you ever get a flashing ASr message, you might need to reset your desk.
#https://desky.com.au/blogs/news/reset-standing-desk-control-panel#:~:text=When%20ready%2C%20press%20and%20hold,Hooray!


#TODO 
#Ask ssieb to make change requests (move logic to component code)
  # Invert pins
  # Get Desk Height On Boot
  # Interlock Up/Down Pins (If not done already)
  # Interrupt/stop movement function (Stop desk motion)

#other
  # Test collision detection
  # Limit external component fetch to just desky? 
  # Fix Desk Is moving on Boot.

external_components:
#Fetch ssieb's custom component# https://github.com/ssieb/custom_components/tree/master/components/desky
  - source:
      type: git
      url: https://github.com/ssieb/custom_components
    components: [ desky ]

uart:
  - id: desk_uart
    baud_rate: 9600
    rx_pin: 1 #Labelled TX on my D1mini clone (mislabelled?)
    ##You can uncomment the debug section below to see UART messages.
    # debug:
      # direction: RX
      # dummy_receiver: true
      # after:
        # bytes: 4
      # sequence:     
        # - lambda: UARTDebug::log_int(direction, bytes, ',');
 
desky:
  id: my_desky
  ####################################################################################
  ##Uncomment this block to use Ssieb's move_to componet function.
  # up:    
    # number: 4 #D2
    # inverted: true 
  # down:  
    # number: 5 #D1
    # inverted: true
  # stopping_distance: 15  # optional distance from target to turn off moving, default 15  
  ####################################################################################
  height:  # Sensor publishing the current height
    name: Desky Height
    id: desky_height
    accuracy_decimals: 1
    unit_of_measurement: cm
    #any other sensor options
    filters:
    - delta: 0.05 #Only send values to HA if they change
    - throttle: 200ms #Limit values sent to Ha to 5 per sec.
    - multiply: 0.1 #convert from mm to cm
    on_value:
      then:
          #If the value changes, then the desk is moving
        - binary_sensor.template.publish:
            id: desky_is_moving
            state: ON
        - delay: 300ms
          #Assume it's stopped moving if no height changes after a short time.
        - binary_sensor.template.publish:
            id: desky_is_moving
            state: Off
            
binary_sensor:
  - platform: template
    id: desky_is_moving
    name: "Desky Is Moving"
    filters:
      - delayed_off: 400ms
    #If the desk isn't moving for a bit we better turn off attempts at movement. It's like poor man's collision detection? 
    on_release:
      then:
        - button.press: desky_stop_desk

button: 
#Stop movement 
  - platform: template
    name: Stop Desk
    id: desky_stop_desk
    on_press:
      then:
        - switch.turn_off: raise_desk
        - switch.turn_off: lower_desk
# Combination Buttons
  - platform: template
    name: Desky Button 1
    id: button_1
    on_press:
      then:
        - switch.turn_on: raise_desk
        - switch.turn_on: lower_desk
        - delay: 300ms
        - switch.turn_off: lower_desk
        - switch.turn_off: raise_desk
  - platform: template
    name: Desky Button 2
    id: button_2
    on_press:
      then:
        - switch.turn_on: purple_wire
        - delay: 300ms
        - switch.turn_off: purple_wire
  - platform: template
    name: Desky Button 3
    id: button_3
    on_press:
      then:
        - switch.turn_on: purple_wire
        - switch.turn_on: lower_desk
        - delay: 300ms
        - switch.turn_off: lower_desk
        - switch.turn_off: purple_wire
  - platform: template
    name: Desky Button 4
    id: button_4
    on_press:
      then:
        - switch.turn_on: purple_wire
        - switch.turn_on: raise_desk
        - delay: 300ms
        - switch.turn_off: raise_desk
        - switch.turn_off: purple_wire

#Move to function
  - platform: template
    name: Go To Desky Height x
    id: go_to_desky_preset_height_x
    on_press:
      then:
      ##Option 1: Uncomment to use Ssieb's move_to componet functions
        # - lambda: id(my_desky).move_to(id(desky_target_height).state*10);  
 
      ##Option 2: Uncomment to use Mahko's lambda alternative 
      #Check if we need to move desk up or down from current position      
        if:
          condition:
          #Current height is more than target height, then move desk down
            lambda: |-
              return id(desky_target_height).state < id(desky_height).state;
          then:
            - switch.turn_on: lower_desk
            - wait_until:
              #Run until the difference between current and target state is < stopping distance 
                condition:
                  lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
            - switch.turn_off: lower_desk
          else:
          #Current height is less than target height, move desk up
            - switch.turn_on: raise_desk
            - wait_until:
                condition:
                  lambda: return abs((id(desky_height).state - (id(desky_target_height).state)))<(id(stopping_distance_cm).state);
                  #Run until the difference between current and target state is <0.3cm
            - switch.turn_off: raise_desk

number:
#Target Height ("Move desk to height x").
    #You should probably limit the range you can move the desk to to within the limits you've set via the control panel, perhaps offset a little within the range.
    #Sending commands higher/lower than this may cause error messages and require desk reset (or worse).
  - platform: template
    id: desky_target_height
    name: "Desky Target Height"
    optimistic: true
    unit_of_measurement: cm
    min_value: 65.0 
    max_value: 122.0
    step: 0.1
    
#Offset correction - Adjust until you get the best accuracy. 
#The desk keeps moving for a little while after the up/down pins are released and we try to account for this.
#1.5cm was about right on mine
  - platform: template
    name: "Desky Stopping Distance cm"
    id: stopping_distance_cm
    unit_of_measurement: cm
    optimistic: true
    min_value: 0
    max_value: 2
    step: 0.1
    restore_value: true
    initial_value: 1.5
    
###############################################
#Define some preset heights.
###############################################
#You can freely define as many adjustable presets as you like.
#These are all seperate/independant of what you've set via the control panel (we can't retrieve them currently).
 
#Standing Height #1 - Set a standing height. 
  - platform: template
    id: desky_standing_height_1
    name: "Standing Height 1"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 110
    max_value: 120
    step: 0.1
    restore_value: true
    initial_value: 115

#Standing Height #1 - Set a standing height. 
  - platform: template
    id: desky_standing_height_2
    name: "Standing Height 2"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 115
    max_value: 125
    step: 0.1
    restore_value: true
    initial_value: 120
  
#Sitting Height #1 - Set a sitting height. This is independant of what you've set via the control panel.
  - platform: template
    id: desky_sitting_height_1
    name: "Sitting Height 1"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 65
    max_value: 69
    step: 0.1
    restore_value: true
    initial_value: 67.0

#Sitting Height #2 - Set a sitting height. This is independant of what you've set via the control panel.
  - platform: template
    id: desky_sitting_height_2
    name: "Sitting Height 2"
    optimistic: true
    unit_of_measurement: cm
    #Limit the range
    min_value: 72.6
    max_value: 82.6
    step: 0.1
    restore_value: true
    initial_value: 77.6
      
switch:
#wake up ther desk and request it sends its height 
  - platform: gpio
    id: wake_desk_and_get_height
    name: "Request Desk Height"
    pin:
      number: D5
      inverted: true
    on_turn_on:
    - delay: 100ms
    - switch.turn_off: wake_desk_and_get_height
  - platform: restart
    name: "Desky Restart"

#Raise the desk 
  - platform: gpio
    id: raise_desk
    name: "Raise Desk"
    pin:
      number: D2
      # mode: INPUT_PULLUP
      inverted: true
    on_turn_on:
    #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: raise_desk
#Lower the desk 
  - platform: gpio
    id: lower_desk
    name: "Lower Desk" 
    pin:
      number: D1
      # mode: INPUT_PULLUP
      inverted: true
    on_turn_on:
   #Auto off after 15s just in case
    - delay: 15s
    - switch.turn_off: lower_desk

  - platform: gpio
    pin: ${desky_purple_pin}
    id: purple_wire
    inverted: true
1 Like

Hopefully it can help others. :slight_smile:

2 Likes

Does this still work with new desky controller?

What is the model number?

Its desky dual controller

I agree that is the belief, but I personally disagree with it. Our company needed to know which of these would be up to some serious use, so I loaded two of each brand of desk with 200 lbs. and ran them up and down day and night for weeks. Both Linak desks died in less than 5000 cycles and the Jiecang desks were still going after 40,000 cycles when I stopped the test.

The Linak desks have smoother and quieter motion, but seem to have problems with durability (at least the ones I had).

1 Like

Interesting. What duty cycle did you use for testing?

In the interest of time, we ran one of each brand at 20% duty cycle, even though they are rated for 10%, hoping for quick success. When the Linak desk failed so quickly, we started a second one at 5% duty to rule out things like overheating. That one ran longer, but not much. (I misspoke previously; it got to around 6000 cycles that time.)

The failure was a brake that acts while descending, presumably to prevent the motor from acting as a generator and overloading the electronics. It started making a horrible squealing sound.

1 Like

So i built one of these a little over a year ago, and I noticed that my monitor has to be adjusted to be at eyeline height when i change the desk from sit to stand and viceversa. It seemed dumb to have the desk automated, and having to adjsut the monitor by hand…so… i made this:

i have limit switches for both positions, and i have a HA scene that moves both desk and monitor at the same time. I used this video as a guide to figure out the electronics/mechanics:

Was it overkill and ridiculous? yeah, it was… but it was a fun build.

Oh wow. Next level.

However the theory goes that you shouldn’t need to do that. Your sit and stand positions should both result in right angle arms which means the relative height of the monitor should be the same.

So could possibly be an issue with either your presets or your desk range.

I did a crazy hand cranked desk project during lockdown which ultimately failed because of insufficient range lol.

I did one of those Drzzz projects too… They are great!