My company has bought several room thermostats with modbus capability. Those are from China. When I communicate with them on Modbus RTU, interesting things happen. Devices sometimes dont respond to me at all. Then in following polls, they sometimes respond. But in the end, after some time, be it one hour or two days, they totally stop responding and I am getting some errors from modbus master. I used serial port analyzer to see whats going on. I did all hardware checkpoints (termination resistor etc). And I tried many modbus masters. But even with only one thermostat connected, issue happens. Specifically to this issue, I developed my own modbus master with Python. The good part with that is, I use minimalmodbus library and I have the chance to close port after each poll. But still, even if my modbus master program keeps polling, thermostats totally stop responding. Somehow I have to solve that issue with programming. I cant always restart thermostats electrically to solve that communication issue.
Here is my code :
import os
import sys
import sqlite3
import time
import datetime
import minimalmodbus
minimalmodbus.CLOSE_PORT_AFTER_EACH_CALL=True
PORT_NAME = '/com5'
SLAVE1_ADDRESS = 1
SLAVE2_ADDRESS = 2
SLAVE3_ADDRESS = 3
BAUDRATE = 9600 # baud (pretty much bits/s). Use 2400 or 38400 bits/s.
TIMEOUT = 0.4 # seconds. At least 0.2 seconds required for 2400 bits/s.
MODE = minimalmodbus.MODE_RTU
sqlite_file = 'ModbusTable.db'
instrument1 = minimalmodbus.Instrument(PORT_NAME, SLAVE1_ADDRESS, MODE)
instrument1.serial.baudrate = BAUDRATE
instrument1.serial.timeout = TIMEOUT
instrument1.debug = False
instrument1.precalculate_read_size = True
instrument2 = minimalmodbus.Instrument(PORT_NAME, SLAVE2_ADDRESS, MODE)
instrument2.serial.baudrate = BAUDRATE
instrument2.serial.timeout = TIMEOUT
instrument2.debug = False
instrument2.precalculate_read_size = True
instrument3 = minimalmodbus.Instrument(PORT_NAME, SLAVE3_ADDRESS, MODE)
instrument3.serial.baudrate = BAUDRATE
instrument3.serial.timeout = TIMEOUT
instrument3.debug = False
instrument3.precalculate_read_size = True
print ('Okuyor')
while 1:
# Connecting to the database file
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
try:
values1 = instrument1.read_registers(40005, 2)
except IOError:
print ('Timestamp: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())+"Failed to read from instrument1")
# C) Updates the pre-existing entry
c.execute("""UPDATE ModbusData SET SetPoint = ? ,ActualTemp = ? WHERE ID= ? """,
(values1[0],values1[1],1))
time.sleep(0.5)
try:
values2 = instrument2.read_registers(40005, 2)
except IOError:
print ('Timestamp: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())+"Failed to read from instrument2")
# C) Updates the pre-existing entry
c.execute("""UPDATE ModbusData SET SetPoint = ? ,ActualTemp = ? WHERE ID= ? """,
(values2[0],values2[1],2))
time.sleep(0.5)
try:
values3 = instrument3.read_registers(40005, 2)
except IOError:
print ('Timestamp: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())+"Failed to read from instrument3")
# C) Updates the pre-existing entry
c.execute("""UPDATE ModbusData SET SetPoint = ? ,ActualTemp = ? WHERE ID= ? """,
(values3[0],values3[1],3))
time.sleep(0.5)
# Committing changes and closing the connection to the database file
conn.commit()
conn.close()
And here is how thermostats perform :
So I will appreciate so much if you will come up with your ideas.