Close
0%
0%

Standing desk remote control

Controlling standing desk by voice through google assitant, home assistant and esphome on esp8266

Public Chat
Similar projects worth following
Just recently I started playing with Home Assistant on my fresh Raspberry and about the same time I started looking around for a new desk with adjustable heigh.

After getting one, first idea was obvious. Make this desk controllable through Google Assistant on my Google Home Mini

This got me lead testing my new low cost oscilloscope, figuring out the communication and how to integrate custom ESP8266 based hardware with HomeAssistant through ESPHome and then integrating Home Assistant with Google Assistant

Integrating dual motor $230 desk from Aliexpress to be able to controll it by voice and to be part of some automation scenarios, like lowering the desk when leaving home etc..

I chose ESP8266 as it's integrated WiFi and is cheaper than ESP32. 

Home automation is based on Home Assistant. It's easy to set up and lots of out-of-the-box integrations.

I don't have public IP available at home, but exposing HomeAssistant API was extremely easy thanks to serveo.net. This thing even has Hass add-on, that makes configuration a breeze.

Couple things that could be improved is that memories have to be represented as switches and that makes the control bit odd. Trying to change it to something like Fan speeds that are supported by ESPHome. Other thing is that Google Assistant - Home Assistant integration does not support sensors, so asking for values is not straight forward and you have to create script or IFTTT integration to make the communication more natural.

table.yaml

ESPHome Config

yaml - 1.03 kB - 04/12/2019 at 11:02

Download

table_height_sensor.h

Custom sensor

h - 845.00 bytes - 04/12/2019 at 11:02

Download

  • 1 × ESP8266
  • 1 × 5V to 3.3V step down module
  • 1 × Raspberry Pi
  • 1 × Google Home Mini

  • Home Assistant integration

    Lubos Horacek04/14/2019 at 19:17 0 comments

    This part turned out to be super easy thanks to serveo.net and tutorial I found here.

    First thing was to make my home Raspberry Pi running Hass.io available from internet. Obvious idea was to go through some VPN etc.. But then I stumbled upon service called Ngrok and eventually to Serveo.net that is amaizingly easy to set up and there is Hass.io add-on. But even simple:

    ssh -R myalias:80:localhost:8123 serveo.net

     did the trick to expose my Hass to internet.

    Then I turned to the tutorial mentioned above and done .. easier than expected.

    Now it's just "Hey Google .. Activate Standing" :-)

  • Integrating with Home Assistant through ESPHome

    Lubos Horacek04/12/2019 at 10:50 0 comments

    Amazing https://esphome.io/ project makes it super easy to integrate most of Arduino modules with Home Assistant through ESP8266 or ESP32. tried in on one or two Sonoff devices, but how difficult is to integrate something custom, reading and sending some UART data.

    Turns out that it's extremely easy. Just implement custom sensor, that allows you to almost copy paste your Arduino IDE C code, register in yaml config and your height sensor reading data from UART is done.

    Sinding messsges is even more easy, as there is already UART switch, that give you option to send message on switch trigger.

    Custom sensor:

    class TableHeightSensor : public PollingComponent,  public UARTDevice, public sensor::Sensor{
     public:
      TableHeightSensor(UARTComponent *parent) : PollingComponent(1000), UARTDevice(parent) {}
    
      byte last[3];
      float value = 0;
      float lastPublished = -1;
    
      void setup() override {
        // This will be called by App.setup())
      }
    
      void loop() override {
        while (available()) {
          byte in = read();
          if(last[2] == 0xAA && last[1] == 0xA6){
            value = (((255*in) + last[0]) / 43.225) - 2; // substracting to make it display same number as controller
          }
         last[2] = last[1];
         last[1] = last[0];
         last[0] = in;
         yield();
       }
      }
    
      void update() override {
        if(value != lastPublished) {
          publish_state(value);
          lastPublished = value;
        }
      }
    };

    ESPHome config:

    uart:
      id: uart_bus
      tx_pin: GPIO5
      rx_pin: GPIO4
      baud_rate: 9600
    
    sensor:
      - platform: wifi_signal
        name: "WiFi Signal ${upper_devicename}"
        update_interval: 60s
      - platform: custom
        lambda: |-
          auto height_sensor = new TableHeightSensor(id(uart_bus));
          App.register_component(height_sensor);
          return {height_sensor};
        sensors:
          name: "${upper_devicename} height"
          unit_of_measurement: cm
          accuracy_decimals: 1
    
    switch:
      - platform: uart
        name: "Sitting"
        id: switch1
        icon: mdi:format-vertical-align-bottom
        data: [0x55, 0xAA, 0xD1, 0xD1, 0xD1]
        internal: False
      - platform: uart
        name: "Standing"
        id: switch4
        icon: mdi:format-vertical-align-top
        data: [0x55, 0xAA, 0xD7, 0xD7, 0xD7]
        internal: False
      # not bothering with exposing more buttons
    

    Now just go to Hass dashboard and integrate one more ESPHome device:

  • Figuring out the controller communication

    Lubos Horacek04/11/2019 at 21:45 0 comments

    First thing after receiving the table and tested it actually works, I opened the controller unit and tried to look it it's the same as some other tables already described around here or elsewhere on the internet. 

    Unfortunately the wiring was different from table to table, so I tried googling anything I could find on the controller and main unit. No luck again, so I took super cheap oscilloscope ( DSO138mini as I was still waiting for my logic analyser .. ) and tried different pins of the controller.

    By pressing controller buttons, I figured it goes:

    1. GND
    2. Vcc
    3. Rx
    4. Tx
    5. Button Down
    6. Button Up

    All pins being high when idle, Rx was having quite a lot of messages being sent by the main unit to the controller. Rx contained only messages when I pushed some button. I tried letting the table reach remote position and disconnecting the controller mid-way to see if it had some role in controlling the end position. Turned out not to be true and as soon as the button was pressed on the controller, main unit took care of travelling to given position and stopping.

    So next thing was figuring out what are the messages being sent. By checking the scope and the length of pulses, I figured it was 9600bps rate as on most of those controllers. So I've hooked ESP8266 Software serial to these repeating the stuff to Serial console. I tried to display binary output, but it was all over the place. Took me while to test outputting HEX and then compensating padding by 0 for values less than 16. Suddenly all messages were same length with only two bytes changing during the movement with 16bit position in little endian format stored in 3rd and 4th byte of the message:

    AA A6 [low byte] [high byte] 0C00

    Then I checked the controller's Tx and this is what it sent:

    Wake up:  55 AA F0 F0 F0
    Sleep: 55 FC

    Mem1: 55AAD1D1D1
    Mem2: 55AAD2D2D2
    Mem3: 55AAD3D3D3
    Mem4: 55AAD7D7D7

    Stop: 55AAE3E3E3

    With some more messages for storing new values to memory, but I was most interested WakeUp, Memory recall and Stop. Turned out WakeUp does not have to be called before triggering memory and sleep is handled by the main unit as well. And as memories we not specific heights, but fixed messages, it turned out to be pretty simple.

    After testing the comms with I added one diode to the Tx of of ESP8266, so it worked alongside the normal controller and not keeping it HIGH all the time.

    First I bothered with level-adjusting the signals, but turned out that ESP8266 pins can handle up to 5V levels, so I've ditched all the unnecessary stuff and then moved to ESP-12E module and small step-down to fit in to original controller enclosure.

    #include <SoftwareSerial.h>
    SoftwareSerial mySoftwareSerial(5, 16, false);
    byte last[3];
    
    void setup() {
      Serial.begin(9600);
      mySoftwareSerial.begin(9600);
      Serial.println("\nSoftware serial test started");
    }
    
    void loop() {
      if(Serial.available()){
        byte in = Serial.read();
        if(in == '1'){
          Serial.println("\nMemory 1");
    
          mySoftwareSerial.write(0x55);
          mySoftwareSerial.write(0xAA);
          mySoftwareSerial.write(0xD1);
          mySoftwareSerial.write(0xD1);
          mySoftwareSerial.write(0xD1);
        }
        // add more mem recalls to test    
      }
      
      if(mySoftwareSerial.available()){
        while(mySoftwareSerial.available()){
          byte in = mySoftwareSerial.read();
    
          if(in == 0x55){
            Serial.println(); 
          }
           if(in < 16){
            Serial.print('0'); 
          }
          Serial.print(in, HEX);
          
          if(last[2] == 0xAA && last[1] == 0xA6){
            Serial.print(" Heigh ");
            Serial.print((255*in) + last[0], DEC);
          }
          
          last[2] = last[1];
          last[1] = last[0];
          last[0] = in;
          yield();
        }
      }
    }

View all 3 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates