I run a Raspberry Pi 4 with a USB-RS485 adaptor connected to a Panasonic IntesisBox, using the Python minimalmodbus module. First, I check the connection by this function:
import minimalmodbus
def openandcheckModbuscom():
print('---openandcheckModbuscom----------------')
# call the Modbus interface
ser = serial.Serial('/dev/ttyUSB0') # open serial port
if ser.is_open:
print('Serial port is open with the following settings:')
print(ser.is_open) # TRUE if port is open
print(ser.name) # print actual port name
print(ser.baudrate) # print port baudrate
else:
print('Serial port not open yet, sorry :-(')
ser.close()
When executed, it returns: TRUE, /dev/ttyUSB0 and 9600, so I think all is fine. Next, I want to get more data from the interface and also save data in my database, so I run:
def readHPstatus():
print('---readHPstatus----------------')
# call the Modbus interface
ser = serial.Serial('/dev/ttyUSB0') # open serial port
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
# Read various temperatures
outdoortemp = instrument.read_register(1, 0)
print(outdoortemp)
outgoingtemp = instrument.read_register(2, 0)
print(outgoingtemp)
ingoingtemp = instrument.read_register(3, 0)
print(ingoingtemp)
tanktemp = instrument.read_register(32, 0)
print(tanktemp)
setpointtemp = instrument.read_register(33, 0)
print(setpointtemp)
cur.execute("INSERT INTO HPstatus VALUES (?, ?, ?, ?, ?, ?,);", (Rightnow, outdoortemp, outgoingtemp, ingoingtemp, tanktemp, setpointtemp))
ser.close()
But that returns only the error message of no connection to the interface. How come, when I have just received both a confirmation of the port and the baud rate...? How do I get the second part going?
Full error message:
Traceback (most recent call last):
File "/home/cpoll/pycode/pollvp010.py", line 260, in <module>
readHPstatus()
File "/home/cpoll/pycode/pollvp010.py", line 179, in readHPstatus
outdoortemp = instrument.read_register(1, 0) # Registernumber, number of decimals
File "/home/cpoll/.local/lib/python3.9/site-packages/minimalmodbus.py", line 480, in read_register
returnvalue = self._generic_command(
File "/home/cpoll/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1245, in _generic_command
payload_from_slave = self._perform_command(functioncode, payload_to_slave)
File "/home/cpoll/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1322, in _perform_command
response_bytes = self._communicate(request_bytes, number_of_bytes_to_read)
File "/home/cpoll/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1490, in _communicate
raise NoResponseError("No communication with the instrument (no answer)")
minimalmodbus.NoResponseError: No communication with the instrument (no answer)
Revision on Oct, 11th
Revised code:
import sqlite3
import requests
import datetime
import json
import serial
import minimalmodbus
def readHPstatus():
print('---readHPstatus----------------')
# call the Modbus interface
ser = serial.Serial('/dev/ttyUSB0')
minimalmodbus.MODE_RTU
minimalmodbus.BYTEORDER_BIG
# print(minimalmodbus._getDiagnosticString())
IntesisBox = minimalmodbus.Instrument('/dev/ttyUSB0', 1, debug = True) # port name, slave address (in decimal)
IntesisBox.serial.baudrate = 9600
IntesisBox.serial.parity = minimalmodbus.serial.PARITY_NONE
IntesisBox.serial.bytesize = 8
IntesisBox.serial.stopbits = 2
IntesisBox.serial.timeout = 0.5
IntesisBox.clear_buffers_before_each_transaction = True
IntesisBox.close_port_after_each_call = True
if ser.is_open:
print('Serial port is open with the following settings:')
print('__Serial port at device:', ser.name)
print('__Serial port baudrate: ', ser.baudrate)
# Read various temperatures
OutdoorTemp = IntesisBox.read_register(1, 0)
print('Outdoor Temperature: ', OutdoorTemp)
OutGoingTemp = IntesisBox.read_register(2, 0)
print('Outgoing Temperature:', OutGoingTemp)
InGoingTemp = IntesisBox.read_register(3, 0)
print('Ingoing Temperature: ', InGoingTemp)
TankTemp = IntesisBox.read_register(32, 0)
print('Tank Temperature: ', TankTemp)
SetpointTemp = IntesisBox.read_register(33, 0)
print('Setpoint Temperature:', SetpointTemp)
cur.execute("INSERT OR IGNORE INTO HPstatus VALUES (?, ?, ?, ?, ?, ?)", (Rightnow, OutdoorTemp, OutGoingTemp, InGoingTemp, TankTemp, SetpointTemp))
else:
print('Serial port not open yet, sorry :-(')
ser.close()
print('---END-------------------\n')
Output from running the code:
---readHPstatus----------------
MinimalModbus debug mode. Create serial port /dev/ttyUSB0
Serial port is open with the following settings:
__Serial port at device: /dev/ttyUSB0
__Serial port baudrate: 9600
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 00 01 00 01 D5 CA (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 152782414.06 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Closing port /dev/ttyUSB0
MinimalModbus debug mode. Response from instrument: 01 03 02 00 00 B8 44 (7 bytes), roundtrip time: 0.0 ms. Timeout for reading: 500.0 ms.
Outdoor Temperature: 0
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 00 02 00 01 25 CA (8 bytes)
MinimalModbus debug mode. Opening port /dev/ttyUSB0
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 6.31 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Closing port /dev/ttyUSB0
MinimalModbus debug mode. Response from instrument: 01 03 02 00 00 B8 44 (7 bytes), roundtrip time: 0.0 ms. Timeout for reading: 500.0 ms.
Outgoing Temperature: 0
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 00 03 00 01 74 0A (8 bytes)
MinimalModbus debug mode. Opening port /dev/ttyUSB0
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 5.67 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Closing port /dev/ttyUSB0
MinimalModbus debug mode. Response from instrument: 01 03 02 00 00 B8 44 (7 bytes), roundtrip time: 0.0 ms. Timeout for reading: 500.0 ms.
Ingoing Temperature: 0
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 00 20 00 01 85 C0 (8 bytes)
MinimalModbus debug mode. Opening port /dev/ttyUSB0
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 6.64 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Closing port /dev/ttyUSB0
MinimalModbus debug mode. Response from instrument: 01 03 02 00 00 B8 44 (7 bytes), roundtrip time: 0.0 ms. Timeout for reading: 500.0 ms.
Tank Temperature: 0
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 00 21 00 01 D4 00 (8 bytes)
MinimalModbus debug mode. Opening port /dev/ttyUSB0
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 7.87 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Closing port /dev/ttyUSB0
MinimalModbus debug mode. Response from instrument: 01 03 02 00 00 B8 44 (7 bytes), roundtrip time: 0.0 ms. Timeout for reading: 500.0 ms.
Setpoint Temperature: 0
---END-------------------
First off remove these lines:
Minimalmodbus is already instantiating the serial port for you. Regarding your first code snippet you say:
Well... if by all is fine you mean you are able to set up your serial port you are right, but as I said above minimalmodbus is creating an instance of the serial port itself, and its baudrate is by default 19200, so you need to add these line after you create your instrument:
Then, according to the IntesisBox manual (page 7):
PAW-AW-MBS-H implements a Modbus RTU (Slave) interface, to be connected to an EIA-485 line. It performs 8N2 communication (8 data bits, no parity and 2 stop bit) with several available baud rates (2400 bps, 4800 bps, 9600 bps -default-, 19200 bps, 38400 bps, 57600 bps, 76800 bps and 115200 bps). It also supports 8N1 communication (8 data bits, no parity and 1 stop bit).
As I understand it, the device should work with both 8N1 and 8N2 with no problems but you might want to change minimalmodbus' configuration and give it a try:
If none of the above is helping you should probably pay attention to Brits' comments and check all those DIP switches and use something like QModMaster to debug your settings before writing any code.
Last but not least, make sure your wiring is correct. For Modbus you actually need three wires: A, B and GND. For more details you can refer to my answer here. Looking at the picture of your USB-to-RS485 I can see it's one of those with no provision for a GND wire. Heck, neither is there one on the IntesisBox... You'll probably have to check where the GND is on that hydro unit (whatever that might be) and connect it to one of the ground pins on the RPi header.
Reading the title of your question I'm guessing your understanding of how the serial port works is a bit off. Be aware that what you are doing on your first code snippet is all happening on the local serial port connected to your RPi. Your Intesis is not giving your its baudrate, because it is simply not giving you anything at all and hence this line on the log:
Although some devices are able to negotiate their baudrates automatically, yours is certainly not. Yet some other devices store their settings, including their baudrate in registers that are accessible through Modbus, but that's not the case with yours either. So I'm afraid the only way for your device to give you its baudrate is for you to look at the position of those DIP switches.