Turn your Desktronic standing desk into a smart desk!

Actually I tried some stuff this weekend and now I can read out the correct height of the desk.
I read out the tx-uart-messages with the logic-analyzer and saw some dependencies in the value. The desk height is between 72.0cm and 119cm. From 72.0 to 99.9cm there is one decimal-digit. From 100 to 119 there only integers.

Mian-Learnings

Tx sends 6 bytes and heres what they mean:

Byte Meaning
1 constant value: 0x5A
2 tens digit of the height
3 units digit of the height
4 1st decimal digit of the height
5 constant value: 0x01
6 propably a kind of an id (actually the sum of all the other bytes divided by a specific number I don’t know) → I measured every value for every height (round about 280) and collected them in another table, which I won’t upload here, as it is too big und for this progression not needed.

Here is an example of the height 75.7:

I compared some values and found out:

Tens

Value Byte
7#.# 0x07
8#.# 0x7F
9#.# 0x6F
1## 0x06

Units

Value Byte
#0.# 0xBF
#1.# 0x86
#2.# 0xDB
#3.# 0xCF
#4.# 0xE6
#5.# 0xED
#6.# 0xFD
#7.# 0x87
#8.# 0xFF
#9.# 0xEF

1st decimal

Value Byte
##.0 0x3F
##.1 0x06
##.2 0x5B
##.3 0x4F
##.4 0x66
##.5 0x6D
##.6 0x7D
##.7 0x07
##.8 0x7F
##.9 0x6F

So I can read out every byte that is send via uart.
For this I wrote my own esphome-custom-component. Here you can find the repository. The currently active branch is feat/desktronic. (I had some inspiration from @ssieb here) Here I will just mention the important part of the component:

Main-Loop for getting the current-height

void Desktronic::loop()
{
    static int bytePositionInUARTMessage = 0;
    static double height = 0.0;
    bool beginning_skipping_garbage_bytes = true;

    while (esphome::uart::UARTDevice::available())
    {
        uint8_t byte;
        esphome::uart::UARTDevice::read_byte(&byte);

        // the uart-messages just get read. So they also can start in the middle of a message
        // in this case, these "garbage-bytes" have to be skipped
        if (beginning_skipping_garbage_bytes)
        {
            if (is_skipping_garbage_byte(byte))
            {
                continue;
            }
            else
            {
                beginning_skipping_garbage_bytes = false;
                bytePositionInUARTMessage = 0;
                height = 0.0;
            }
        }

        handle_byte(byte, bytePositionInUARTMessage, height);
    }
}

Managing how the bytes of the uart-message is parsed to a valid height.

void Desktronic::handle_byte(const uint8_t byte, int& bytePosition, double& height)
{
    switch (bytePosition)
    {
    case 0: // everytime 0x5A
        bytePosition = 1;
        break;
    case 1:
        // 70, 80, 90, 100
        height += get_tens_digit(byte);
        bytePosition = 2;
        break;
    case 2:
        // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
        height += get_units_digit(byte);
        bytePosition = 3;
        break;
    case 3:
        // 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9
        height += get_first_decimal_digit(byte);
        bytePosition = 4;
        break;
    case 4: // everytime 0x01
        bytePosition = 5;
        break;
    case 5: // the uart-message is complete
        current_pos_ = height;

        // update the height-sensor
        if (height_sensor_)
        {
            // accuracy is set in __init__.py
            height_sensor_->publish_state(height);
        }

        // reset the height and position
        bytePosition = 0;
        height = 0.0;

        break;
    default:
        break;
    }
}

I unfortunately had to do this with those static-variables because of the problematic of the garbage_bytes at the beginning. Because of this I cannot read out 6 bytes at once.

My Yaml-File looks like this:

...

################################################
# Ready for production (this should word as expected)
################################################

external_components:
  - source:
      type: git
      url: https://github.com/MhouneyLH/esphome_custom_components
      # ref: feat/desktronic
      # ref: feat/test
      ref: feat/old_test
      # ref: feat/without_map
    refresh: 10s
    components: [ desktronic ]

uart:
  - id: desk_uart
    rx_pin: 1
    baud_rate: 9600

desktronic:
  id: my_desktronic
  height:
    name: DeskHeight
  up:
    number: 14
  down:
    number: 12
  request:
    number: 4
  stopping_distance: 0
  timeout: 5s

Thats the result for now that makes me pretty happy for now :slight_smile: (its on less fps; on my pc it is realtime to the moving-desk):
height_sensor

Problems

I came across 2 problems:

  1. The flash-size is of my esp8266 is not enough to story the current program + the generated copy of it as I already use round about 65% of the space. So I have to clear out the whole esp in order to have the newest software on the device. I guess the easiert solution for that is to buy another esp with more flash-size.
  2. Sometimes I have problems to be connected to the esp. (When I am installing the new software on the device) The error message after waiting about 30secs:

    After that message it automatically connects. Maybe somebody had to deal with something like this in the past and know what to do about it.

Next Step

Now where I have this working state I am trying to move the desk via software.

1 Like