Modbus PLC YAML help

I have been trying to get Modbus configured in HA and it has been a bear. I have tried to decipher the Modbus page for a few days now. All I am looking to start with is to be able to turn a coil on in my KOYO PLC controller at address 3074. I have tried using sample code and pretty much every thing I can find on this. Not much. I can manually turn on and off the coil 3074 with a Modbus simulator program so I know its working. Any help would be great. What I have so far that I know I need is. below. The PLC is slave 255.

modbus:

  • name: hub1
    type: tcp
    host: 192.168.1.243
    port: 502

I need help here haha.

I would like to know how to read the state of the coil and write to this coil.

Thanks.

Please format your YAML properly – see point 11 here.
According to the documentation, there should be this service: modbus.write_coil. You can try calling it from developer tools with unit: 255 (slave address), hub: hub1, address: 3074 (register address) and state: true (or false).

Sorry about that. New to this. I did what you said in the service. It does work. I can toggle off and on coils to my plc over Modbus. How do I format the YAML code to switch these coils on and off from the front end? I know how to add entitys to the front end. My YAML skills are not there yet. I want to be able to read the sates of others and not switch as well. I will eventually need to read integers but I’ll cross one bridge at a time. Thanks for the help. Any code examples would be appreciated.

You should be able to add a switch like this:

modbus:
  - name: hub1
    type: tcp
    host: 192.168.1.243
    port: 502
    switches:
      - name: whatever
        slave: 255
        address: 3074
        write_type: coil
        verify:

See Modbus - Home Assistant
For reading, see sensor and binary_sensor on the same page.

Thanks so much.
That seems to work. Is there a way to read the value of a coil as a binary sensor so I can create automations? I am also looking for a way to read a value for temperature from the PLC as well. I need to get a better grasp of the YAML. I see what is going on now but the documentation is tough sometimes to understand and program for a specific use. I looked at the binary sensor and tried a few things but its not correct. The spacing might be wrong or something.

I tried this below and it ended up not working. I can see the state but never changes.

    type: tcp    
    host: 192.168.1.243    
    port: 502

    switches:
      - name: Switch33
        slave: 255
        address: 3074
        write_type: coil
        verify:
        
    binary_sensors:
    - name: "Pool_Pump"
      address: 3074
      scan_interval: 20
      slave: 255 
      device_class: moving
      input_type: coil

The whole block under binary_sensors: should be indented with 2 more spaces, so that it is at the same indentation level as the switch above it.
You can use a command line program called yamllint to check your YAML. With the config you posted, it outputs this:

$ yamllint -
modbus:
  - name: hub1
    type: tcp    
    host: 192.168.1.243    
    port: 502

    switches:
      - name: Switch33
        slave: 255
        address: 3074
        write_type: coil
        verify:
        
    binary_sensors:
    - name: "Pool_Pump"
      address: 3074
      scan_interval: 20
      slave: 255 
      device_class: moving
      input_type: coil
stdin
  1:1       warning  missing document start "---"  (document-start)
  3:14      error    trailing spaces  (trailing-spaces)
  4:24      error    trailing spaces  (trailing-spaces)
  13:1      error    trailing spaces  (trailing-spaces)
  15:5      error    wrong indentation: expected 6 but found 4  (indentation)
  18:17     error    trailing spaces  (trailing-spaces)

You the man. That was it. Seems to work now. Can I use “sensor:” to retrieve floats and integer values from registers?

Yes, that should be possible. Here’s the relevant section of documentation.
Maybe something like this:

modbus:
  - name: hub1
    type: tcp
    host: 192.168.1.243
    port: 502

    switches:
      - name: Switch33
        slave: 255
        address: 3074
        write_type: coil
        verify:

    binary_sensors:
      - name: "Pool_Pump"
        address: 3074
        scan_interval: 20
        slave: 255
        device_class: moving
        input_type: coil

    sensors:
      - name: whatever
        slave: 255
        address: 1234
        data_type: int  # or float
        unit_of_measurement: ""

Thank you so much for your help. I will try this out.

Ok, New issue. Apparently my PLC is sending hex values in it’s register. I to have to convert them into a decimal with an online calc. I have value 2329 in my plc register and home assistant sees it as 9001. The calc. confirmed that. Hmm. Is there a way to do the math?

The PLC is sending binary data. It is up to the receiver how to display it (and even how to interpret it – it could be a float for example).

You are reading value this on the PLC itself, right? I guess it just displays everything in hex.
I don’t know what the number you are reading is supposed to mean, so I’ll just assume you just want it displayed in hex.
You should be able to convert the state of a sensor to hex with this template: {{ "%0x" % (states('sensor.sensor_name') | int) }}. I guess you’ll have to use it in a template sensor.

Basically I am reading the timer value on T0 register from the Koyo directlogic 06 PLC . The number in the timer in the Directsoft software on the ladder timer block is 2329. When home assistant reads it under sensor, it determines the number is 9001. I would like to get the 2329 number as displayed on my controller timer register location. I am not exactly sure what is going on yet. I mostly work with Allen Bradley controllers and software so I am still figuring this out. I assume that the value is getting converted from hex to decimal. I thought by reading a input register from the Modbus would directly read what is in the register. Still trying to wrap my head around it to fully explain what is going on.

Exactly. There are 16 bits of binary data in the register. It’s up to you to interpret it (Is it a signed integer? Unsigned integer? Float?) and display it (the number 10 in decimal can also be displayed as 0xA hex, 012 octal and so on).

To get 2329, you’ll need to create a template sensor that reads the decimal value 9001 from your modbus sensor and converts it to hex:

template:
  - sensor:
    - name: "hex value"
      unit_of_measurement: ""
      state: '{{ "%0x" % (states("sensor.sensor_decimal") | int) }}'

Replace sensor_decimal with the name of your sensor.

Is this right? I am getting value 0 on hex value. I feel so inept with this YAML coding.

modbus: 
  - name: hub1
    type: tcp    
    host: 192.168.1.243    
    port: 502

    switches:
      - name: Switch33
        slave: 255
        address: 3074
        write_type: coil
        verify:
        
    binary_sensors:
      - name: "Pool_Pump"
        address: 3074
        scan_interval: 10
        slave: 255 
        device_class: moving
        input_type: coil
        
    sensors:
      - name: Timer1
        slave: 255
        address: 256       
        data_type: int # or float
        unit_of_measurement: "Time"
        
template:
  - sensor:
      - name: "hex value"
        unit_of_measurement: ""
        state: '{{ "%0x" % (states("Timer1") | int) }}'    

Nope, that should be state: '{{ "%0x" % (states("sensor.timer1") | int) }}'

I just put this in and nothing under Modbus works now. Hmm, sure I’m not missing something more? Thanks.

modbus: 
  - name: hub1
    type: tcp    
    host: 192.168.1.243    
    port: 502

    switches:
      - name: Switch33
        slave: 255
        address: 3074
        write_type: coil
        verify:
        
    binary_sensors:
      - name: "Pool_Pump"
        address: 3074
        scan_interval: 10
        slave: 255 
        device_class: moving
        input_type: coil
        
    sensors:
      - name: Timer1
        slave: 255
        address: 256       
        data_type: int # or float
        unit_of_measurement: ""
        
template:
  - sensor:
      - name: "hex value"
        unit_of_measurement: ""
        state: '{{ "%0x" % (states("sensor.Timer1") | int) }}'    

Check your logs. Maybe you already had a template: section somewhere in your configuration.yaml (or !included files).

Some errors, not sure what they mean. Pretty vague.

Pymodbus: Modbus Error: [Input/Output] [Errno 32] Broken pipe

6:14:03 PM – (ERROR) Modbus

Setup of sensor platform modbus is taking over 10 seconds.

6:14:03 PM – (WARNING) Sensor - message first occurred at 6:14:03 PM and shows up 2 times

Setup of switch platform modbus is taking over 10 seconds.

6:14:03 PM – (WARNING) Switch

Setup of binary_sensor platform modbus is taking over 10 seconds.

6:14:03 PM – (WARNING) Binary sensor

Error doing job: Unclosed client session

6:13:49 PM – (ERROR) runner.py

No idea, sorry. Does not seem to be related to the template sensor you added. Try restarting Home Assistant.

Any idea why half the time on a restart of HA, entities for the Modbus are unavailable? I then restart and they will be working. Very odd.