Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mod bus Question #3

Open
sleepyb opened this issue Oct 11, 2023 · 6 comments
Open

Mod bus Question #3

sleepyb opened this issue Oct 11, 2023 · 6 comments

Comments

@sleepyb
Copy link

sleepyb commented Oct 11, 2023

Hi, thank you for documenting your findings.

Quick question: can you write parameters to the unit via modbus?

Eg you can change setpoints etc via the official remote controller using a somewhat clunky parameter/value interface

Can these parameters be written to via modbus or can it only read the User information parameters?

Thanks.

@caliston
Copy link
Contributor

Yes, you can write the coils and holding registers, which are the read/write values. Here's some example code to read the setpoints - the write is commented out but did work when I tried it:

#!/usr/bin/env python3

from pyModbusTCP.client import ModbusClient

# the values return are 16-bit signed integers,
# so convert to python integers
def sint16(v):
    signbit = 1 << 15
    return (v & (signbit - 1)) - (v & signbit)

def read(mb, reg):
    result = mb.read_holding_registers(reg, 1)
    if isinstance(result, list):
        return sint16(result[0])
    else:
        return 0

def write(mb, reg, val):
    mb.write_single_register(reg, val)

# hostname of the ModbusTCP server
hostname = "192.168.4.117"

# connect to the server on port 502
mb = ModbusClient(host=hostname, port=502, unit_id=1, auto_open=True, debug=False)

# read settings from the holding register table
# these are in units of 0.1C, resolution 0.5C
z1_fixed_outgoingwater_set = read(mb, 2)*0.1
z1_tm1 = read(mb, 3)*0.1
z1_tm2 = read(mb, 4)*0.1
z1_te1 = read(mb, 5)*0.1
z1_te2 = read(mb, 6)*0.1

print("Zone 1: Fixed setpoint %f" % (z1_fixed_outgoingwater_set))
print("Zone 1: At min air temp te1=%f, outgoing water temp is tm1=%f" % (z1_te1, z1_tm1))
print("Zone 1: At max air temp te2=%f, outgoing water temp is tm2=%f" % (z1_te2, z1_tm2))

# set Zone 1 fixed outgoing water setpoint to 55C
##write(mb, 2, 55*10)

@sleepyb
Copy link
Author

sleepyb commented Oct 12, 2023

Brilliant! Thanks for your quick response.! 😁

So it would be possible for me to create my own inside controller/thermostat to tell the HP to provide a fixed temp output, but vary that "fixed" temp according to my own weather compensation scheme?

My (tentative) plan is to have a simple controller with "too hot" and "too cold" buttons. The user would prod those amif required and the controller would adjust the WC curve in response and also try to learn what flow temp is most appropriate for a given outside temp, time of day, day of week etc.

If I can control the parameters via modbus amd the HP doesn't do anything strange (like reboot after each change or something) this might be possible.

@caliston
Copy link
Contributor

I think that would be possible. The HP has several modes, incoming weather compensation, fixed flow temps and based on a sensor in the buffer tank. The interaction between the different modes can be somewhat non-obvious, especially if you have the HP running the show rather than via an external on/off thermostat, but I think simply turning off weather compensation and manipulating the set points will probably achieve what you want.

@Dectorian
Copy link

Hi. A big thank you for your input.

Using a serial usb interface, I can read registers.

I too am keen to read/write the setpoints from within Home Assistant.

The example code above applies to tcp.

Could you please provide an example code for serial?

@caliston
Copy link
Contributor

Here's a translation of the above example to use a serial Modbus device. I did pip3 install minimalmodbus to get the library:

#!/usr/bin/env python3

import minimalmodbus


def read(mb, address):
  return mb.read_register(address, functioncode=3, signed=True)

def write(mb, address, value):
  mb.write_register(address, value, functioncode=6, signed=True)

serialdev = "/dev/ttyUSB0"

instrument = minimalmodbus.Instrument(serialdev, slaveaddress=1, mode='rtu')  # port name, slave address (in decimal)
instrument.serial.baudrate = 19200         # Baud
instrument.serial.bytesize = 8
instrument.serial.parity   = 'N'
instrument.serial.stopbits = 2
instrument.serial.timeout  = 0.05          # seconds

instrument.mode = minimalmodbus.MODE_RTU   # rtu or ascii mode
instrument.clear_buffers_before_each_transaction = True

mb = instrument

# read settings from the holding register table
# these are in units of 0.1C, resolution 0.5C
z1_fixed_outgoingwater_set = read(mb, 2)*0.1
z1_tm1 = read(mb, 3)*0.1
z1_tm2 = read(mb, 4)*0.1
z1_te1 = read(mb, 5)*0.1
z1_te2 = read(mb, 6)*0.1

print("Zone 1: Fixed setpoint %f" % (z1_fixed_outgoingwater_set))
print("Zone 1: At min air temp te1=%f, outgoing water temp is tm1=%f" % (z1_te1, z1_tm1))
print("Zone 1: At max air temp te2=%f, outgoing water temp is tm2=%f" % (z1_te2, z1_tm2))
# set Zone 1 fixed outgoing water setpoint to 55C
#write(mb, 2, 55*10)

I've not used the register write function in HA, so not sure how best to do that. But the registers read above can equally be written to.

@ghayne
Copy link

ghayne commented Dec 12, 2023

Many thanks for this. I am using a USB Modbus dongle connected to a Raspberry Pi running node-red. Observing the various parameters has really helped to get weather compensation set up
Screenshot_2023-12-07_17-55-27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants