How to transfer data from uart

You might be better off just testing in hex like Karosm mentioned.

There’s more examples for recieving and publishing here.

There’s some examples of setting up hex globals here which might be useful for testing.

It all depends what you want to accomplish. If you send hex values and want to use these values to automation or you send some text to be visualized in HA…

It sounds intresting and thanks, the main idea is to import hex strings. Someone by specific byte in string will be converted to decimal values, and someone will be conveterd to a binary on/off sensor. Like (0x01, 0x00, 0x00, 0x00) = switch state on, or (0x02, 0x00, 0x00, 0x00 = switch state off) for a example.

Tested your example but get following error. Sorry. I realy trying to read and understood what you send me in both examples, but I still not understood right.

Failed config

uart: [source /config/esphome/esphome-web-74a6c6.yaml:50]
  - id: uart_bus
    tx_pin: 
      number: 1
      mode: 
        output: True
        input: False
        open_drain: False
        pullup: False
        pulldown: False
        analog: False
      inverted: False
    rx_pin: 
      number: 3
      mode: 
        input: True
        output: False
        open_drain: False
        pullup: False
        pulldown: False
        analog: False
      inverted: False
    baud_rate: 115200
    debug: 
      direction: BOTH
      dummy_receiver: True
      after: 
        delimiter: 
          - 0x7E
        bytes: 150
        timeout: 100ms
      sequence: 
        - then: 
            - 
              Couldn't find ID 'desk_height'. Please check you have defined an ID with that name in your configuration.
              lambda: !lambda |-
                UARTDebug::log_int(direction, bytes, ',');                 // Log the message as int. 
                UARTDebug::log_hex(direction, bytes, ',');                 // Log the message in hex.

yaml:

substitutions:
  name: esid
  friendly_name: esid_dosa

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  min_version: 2024.6.0
  name_add_mac_suffix: false
  project:
    name: esphome.web
    version: dev
  includes:
    #- uart_read_line_sensor.h

esp8266:
  board: esp01_1m

# Enable logging
logger:
   baud_rate: 0

# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

# Allow provisioning Wi-Fi via serial
#improv_serial:

wifi:
  # Set up a wifi access point
  ap: {}

# In combination with the `ap` this allows the user
# to provision wifi credentials to the device via WiFi AP.
captive_portal:

dashboard_import:
  package_import_url: github://esphome/example-configs/esphome-web/esp8266.yaml@main
  import_full_config: true

# To have a "next url" for improv serial
web_server:



uart:
  id: uart_bus
  tx_pin: GPIO1
  rx_pin: GPIO3
  baud_rate: 115200
  debug:
    direction: BOTH
    dummy_receiver: true
    after:
      # bytes: 9 
      # timeout: 10ms
      delimiter: [0x7E] #Specific end byte
    sequence:     
      - lambda: |-
          UARTDebug::log_int(direction, bytes, ',');                 // Log the message as int. 
          UARTDebug::log_hex(direction, bytes, ',');                 // Log the message in hex.
          ESP_LOGD("custom", "Bytes size: %d", bytes.size());        // Log how many bytes in the message.
          if (direction == UART_DIRECTION_RX)                        // Check message direction (Change to TX if required)
            {
                if (bytes.size() == 9)                               // Check number of bytes
                  {
                      if ( bytes[0] == 0xF2 &&                       // Check the first three bytes and the last byte
                           bytes[1] == 0xF2 && 
                           bytes[2] == 0x01 &&
                           bytes[8] == 0x7E
                          )       
                        {
                          int height = (bytes[4] * 256) + bytes[5];  // Do some operations with some bytes.
                          id(desk_height).publish_state(height);     // Publish results to a sensor.
                        }
                  }
            }

    
switch:
  - platform: template
    name: "Dieselvärmare"
    optimistic: true
    turn_on_action:
      - uart.write: "heater_on\r\n"
    turn_off_action:
      - uart.write: "heater_off\r\n"
button:
  - platform: uart
    name: "Dieselvärmare På"
    data: "heater_on\r\n"
  - platform: uart
    name: "Dieselvärmare Av"
    data: "heater_off\r\n"
    

The main idea is to import hex strings and convert specific bytes to decimal valus, also if possible convert bytes from specific hex strings to on/off state values. My first idea was if I could receive the data as a sensor to HA, it will be possible later to convert the specific bytes with a template from configuration.yaml

Then the code on post#33 is what you need, just pick bytes[…] for corresponding template sensor. Line of code and you can use it for binary template sensor (on/off) .

But can that code import hex data? it feels like it import as ascii and then convert it to decimal. Is it possible to import as hex then? Also wonder. The data hex strings that will be imported, is the format important. I mean if it matters if it come as “00 00 00 00” or “00:00:00:00” or “0x00, 0x00; 0x00, 0x00” ? Sorry if I sounds dumb, just trying to learn.

It presents in dec whatever it receives. But if you send ascii, every character is one byte, so 15 would be two bytes, 49 and 53.

Maybe I understood. If I change “bytes [0]” to 4 it your example, will it mean it read value from byte 4 when or it read value with 4 bytes?


sequence:
      - lambda: |-
          UARTDebug::log_string(direction, bytes);
          id(testsensor).publish_state( bytes[0] );

For example, make 5 template sensors and send values from Nano. Update the sensors
id(testsensor1).publish_state( bytes[0] );

id(testsensor5).publish_state( bytes[4] );

I see, thanks. Do you know if it is posible to create a template who add two sensor to one? For a example my nano send 0x12, HA see it and convert as T1=48 / T2=120 / T3=49 / T4=50 in decimal. I want to read only T3/T4 and add it together to get “49, 50” who can be converted to “12” in ascii. Maybe not the best way of course but it is the best I can find out. Thanks for your patience for a dumb person :grinning:

I’m not following now… If nano sends 0x12, esphome receives 0x12 and sensor shows in decimal which is 18.

I follow your example and add:

    sequence:
      - lambda: UARTDebug::log_string(direction, bytes);
          id(testsensor).publish_state( bytes[0] );
          id(testsensor2).publish_state( bytes[1] );
          id(testsensor3).publish_state( bytes[2] );
          id(testsensor4).publish_state( bytes[3] );
          id(testsensor5).publish_state( bytes[4] );

sensor:
  - platform: template
    name: "T1"
    id: "testsensor"
    accuracy_decimals: 5
  - platform: template
    name: "T2"
    id: "testsensor2"
  - platform: template
    name: "T3"
    id: "testsensor3"
  - platform: template
    name: "T4"
    id: "testsensor4"
  - platform: template
    name: "T5"
    id: "testsensor5"

in log it shows as:

[21:38:12][D][uart_debug:158]: <<< "0x12"
[21:38:12][D][sensor:093]: 'T1': Sending state 48.00000  with 5 decimals of accuracy
[21:38:12][D][sensor:093]: 'T2': Sending state 120.00000  with 1 decimals of accuracy
[21:38:12][D][sensor:093]: 'T3': Sending state 49.00000  with 1 decimals of accuracy
[21:38:12][D][sensor:093]: 'T4': Sending state 50.00000  with 1 decimals of accuracy
[21:38:12][D][sensor:093]: 'T5': Sending state 128.00000  with 1 decimals of accuracy

T3 and T4 shows “49” and “50”. I want to add this two to one value"49, 50". When this two shows togheter as “49, 50” it will maybe be possible for a template to convert “49, 50” back to hex “12” or decimal “18”.

Ahh, you are still sending ascii, not hex. so ascii 0=48, ascii x=120 etc…
That doesn’t make sense.
If you send Serial.write(123); from Nano what you get on Esphome byte [0] ?

DOH! I think I found the problem, or one of them. My nano had every time sended serial.write(“123”), when it send serial.write(123) things begin happen. Byte [0] now shows as 123 when I send (123) or 18 if I send (0x12), before it shows as 49 becuse it read every letter as a byte. Now even Mahko_Mahko:s example is working and it do it mory easy to separate when several hex strings sends att same time.

Finally! Now you cand send / receive numeric data without playing with ascii.

Yes, many thanks for your help and time!! Now my project can continue and at same time I learn me a lot.

1 Like