-2

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 :

enter image description here

So I will appreciate so much if you will come up with your ideas.

Şansal Birbaş
  • 443
  • 1
  • 6
  • 14

1 Answers1

1

By the look of your screenshot, I think that you are not waiting long enough for the thermostat's reply. First request: the reply from "instrument1" is not received in the time frame you have configured. So your program sends a request to "instrument2", but receives the late reply for "instrument1". The rest of your log is all about that: one request receiving the reply from the previous request.