Canbus message decoding to multiple switches

Hi there.
I’m in the process of interfacing with a Mercedes-Benz PSM. The PSM is actually a PLC with at least two canbuses. One for the connection to the card (interior can B), and the other (ABH-CAN) for upfitters.
I’ve decided to interface my HMI (a waveshare touch screen) via ABH-CAN.
Getting the CANbus online is not an issue. I’ve also been able to decode most of the frames data.
The payload (data) of the can_frame is eight bytes long.

  • Byte 1: I/O-bits 1-4
  • Byte 2: I/O-bits 5-8
  • Byte 3: Databyte 1
  • Byte 4: Databyte 2
  • Bytes 5-6: Word1
  • Bytes 7-8: Word2
    The input-bits are coded with two bits;
  • 00 = off
  • 01 = on
  • 11 = Signal not available

The input-bits are LSB, so to send four input-bits on, off, off, off (as 1, 0, 0, 0) would be in 00 00 00 01, and thus 0x01.
In a similar manner, off, on, off, off would be 00 00 01 00 → 0x04.

The same analogy goes when the PSM transmits data on the ABH-CAN
Ideally I’d have some bits transferred via the can-bus, but also bytes (battery voltage, temperatures etc). But I have absolutely NO idea how to split the can-data in a reasonable manner to variables to use for switches/sensors

Sure, it starts with

canbus:
  - platform: esp32_can
    tx_pin: GPIO15
    rx_pin: GPIO16
    can_id: 6
    use_extended_id: true
    bit_rate: 125kbps
    on_frame:
      - can_id: 6
        can_id_mask: 1111111
        use_extended_id: True
        then:

And I draw a blank :slight_smile:

Any help is appreciated. I’d need the eight I/O bits to switches and the databytes for sensors

You’ll need to write some lambda code to pick apart the received data. Here’s an example from one of my devices:

sensor:
  - platform: template
    id: engine_rpm
    name: "Engine RPM"
    unit_of_measurement: "RPM"
    accuracy_decimals: 1
    filters:
      - sliding_window_moving_average:
          window_size: 4
          send_every: 4

canbus:
  - platform: esp32_can
    rx_pin: GPIO26
    tx_pin: GPIO27
    can_id: 1
    bit_rate: 500kbps
    on_frame:
      - can_id: 0xCF00400
        use_extended_id: true
        then:
        - lambda: |-
             id(engine_rpm).publish_state((x[4] + (x[5] * 256)) * .125f);

Here’s a solution to check the bits:

                id(sw_gr1_f11).publish_state((x[0] & 0x03) == 0x01);
                id(psm_out2).publish_state(((x[0] >> 2) & 0x03) == 0x01); 
                id(sw_gr1_ff2).publish_state(((x[0] >> 4) & 0x03) == 0x01);
                id(psm_out4).publish_state(((x[0] >> 6) & 0x03) == 0x01);

I asked Gemini, and the result was working. How nice