Reputation: 21
I'm trying to communicate with a Uponor Smatrix Base X-245 using a use a Raspberry Pi 3B+ over the serial port (UART), without much luck.
Here is a sample output from the UART (/dev/ttyS0) using pyserial:
import serial
ser = serial.Serial("/dev/ttyS0", baudrate=19200)
while True:
received_data = ser.read()
sleep(0.025)
data_left = ser.inWaiting()
received_data += ser.read(data_left)
print (received_data.hex())
Data without any thermostats (8) connected:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
dd e7 c9 6b 01 0a 2e fe
dd e7 af 83 01 56 89 ff
dd e7 f5 33 01 bf 36 fe
dd e7 f7 6d 01 ce f6 fe
dd e7 f7 2b 01 aa 36 fe
dd e7 f7 75 01 da f6 fe
dd e7 f7 49 01 fe 76 ff
dd e7 f5 45 01 99 f6 fe
Data with all thermostats (8) connected:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
dd e7 c9 6b 01 0a 2e fe 77 5e 6e e3 ed db 83 ff ff 81 e7 fb 87 ff 6f 89 fb 3d 7b 99 ff 75 53 fe
dd e7 c9 6b a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 3d 87 ff 6f 95 ff ff 8d 2f ff
dd e7 af 83 01 56 89 ff 77 de 6d e4 ed cb 83 ff ff 81 e7 fb 87 ff 6f 89 fb 85 7b 99 ff 0b 07 ff
dd e7 af 83 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff 6f 95 ff ff 25 3b fe
dd e7 f5 33 01 bf 36 fe 77 5e df d3 ed eb 83 ff ff 81 e7 fb 87 ff 6f 89 fb 85 7b 99 ff 71 0f ff
dd e7 f5 33 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff 6f 95 ff ff d3 fb ff
dd e7 f7 6d 01 ce f6 fe f7 fe fc fe
dd e7 f7 6d a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 79 87 ff 6f 95 ff ff 15 d3 fe
dd e7 f7 2b 01 aa 36 fe
dd e7 f7 2b a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 67 87 ff 6f 95 ff ff 43 91 ff
dd e7 f7 75 01 da f6 fe 77 de 5f c7 ed 97 83 ff ff 81 e7 fb 87 ff 6f 89 fb 07 7b 99 ff cf 8f fe
dd e7 f7 75 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 07 87 ff 6f 95 ff ff 77 9b ff
dd e7 f7 49 01 fe 76 ff 77 de 5f e2 ed 7b 83 ff ff 81 e7 fb 87 ff 6f 89 fb 79 7b 99 ff 95 ff ff
dd e7 f7 49 a5 01 01 85 ff 7f e7 ff b7 91 fd cb 8f f9 93 89 fb 79 87 ff 6f 95 ff ff c1 3 ff
dd e7 f5 45 01 99 f6 fe 77 5e 5f d4 ed bb 83 ff ff 81 e7 fb 87 ff 6f 89 fb 3d 7b 99 ff bb d1 ff
dd e7 f5 45 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 3d 87 ff 6f 95 ff ff bf 0d ff
Included here the same data, but color coded to recognize patterns.
Also the raw bytes that were captured:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0
dd e7 c9 k 01 \n . fe w ^ n e3 ed f7 83 ff ff 81 e7 fb { 99 ff - 1f fe
dd e7 c9 k a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb = 87 ff o 95 ff ff 8d / ff
dd e7 af 83 01 V 89 ff w de m e4 ed cb 83 ff ff 81 e7 fb { 99 ff e9 d1 ff
dd e7 af 83 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff o 95 ff ff % ; fe
dd e7 f5 3 01 bf 6 fe w ^ df d3 ed e5 83 ff ff 81 e7 fb { 99 ff 93 a7 fe
dd e7 f5 3 a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 85 87 ff o 95 ff ff d3 fb ff
dd e7 f7 m 01 ce f6 fe ff ff ff ff ` ff ff
dd e7 f7 m a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb y 87 ff o 95 ff ff 15 d3 fe
dd e7 f7 + 01 aa 6 fe
dd e7 f7 + a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb w 87 ff o 95 ff ff Q 11 ff
dd e7 f7 u 01 da f6 fe w de _ c7 ed ? 87 ff ff 81 e7 fb { 99 ff bd i ff
dd e7 f7 u a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb 07 87 ff o 95 ff ff w 9b ff
dd e7 f7 I 01 fe v ff w de _ e2 ed u 83 ff ff 81 e7 fb { 99 ff cf a1 ff
dd e7 f7 I a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb y 87 ff o 95 ff ff eb 9d ff
dd e7 f5 E 01 99 f6 fe w ^ _ d4 ed a7 83 ff ff 81 e7 fb { 99 ff 85 0f ff
dd e7 f5 E a5 01 01 85 ff ff e7 ff b7 91 fd cb 8f f9 93 89 fb = 87 ff o 95 ff ff bf \r ff
Uponor Smatrix Base X-245. Some sites claim it communicates over RS485. Do not confuse with the PRO version that supports Modbus.
The thermostats are Uponor Smatrix Base T-146 Bus, which have a Renesas RL78/L13 chipset which is used for serial communication (I think). From the datasheet:
[80-pin]
• CSI: 1 channel/UART (UART supporting LIN-bus): 1 channel/simplified I2C: 1 channel
• CSI: 1 channel/UART: 1 channel/simplified I2C: 1 channel
• UART: 2 channels
Raspberry Pi 3B+ X-245 T-146
GPIO 14 (UART TX) <--> A <--> A
GPIO 15 (UART RX) <--> B <--> B
+ <--> +
- <--> -
Who recognizes a protocol or can help me decode it? I've tried:
Upvotes: 1
Views: 644
Reputation: 21
So like Marcos suggested, the problem with sending was me not realising that for RX the RE should have been low and for TX the DE should have been high. Now I can read/write at the same time using this small class:
import time
import serial
import serial.rs485
import RPi.GPIO as GPIO
from crc import crc16
TX_DE = 11
RX_RE = 13
baud = 19200
T1_5 = 16500000 / baud / 1000
T3_5 = 38500000 / baud / 1000
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(TX_DE, GPIO.OUT, initial=GPIO.HIGH) # HIGH enables TX
GPIO.setup(RX_RE, GPIO.OUT, initial=GPIO.LOW) # LOW enables RX
ser = serial.rs485.RS485(port="/dev/serial0", baudrate=baud, timeout=T3_5)
ser.rs485_mode = serial.rs485.RS485Settings(
rts_level_for_tx=False,
rts_level_for_rx=False,
loopback=True,
delay_before_tx=T3_5,
delay_before_rx=T3_5,
)
def write(command, direct=False):
command_bytes = bytes.fromhex(command)
if not direct:
crc = crc16(command_bytes.decode("latin-1"))
ser.write(command_bytes + bytes.fromhex(crc[-2:]) + bytes.fromhex(crc[:2]))
else:
ser.write(command_bytes)
def read():
while True:
x = ser.read(4095)
print(x.hex())
How ever now I can see the commands on the serial bus e.g. write(b'\x01\x04\x00\x01\x00\x0c\xA1\xCF')
, but nothing happens (i.e. no Modbus response), what am I missing?
Upvotes: 0
Reputation: 21
So it turns out that I was missing a TTL > RS485 converter, so I added that and now I can clearly read the data, and it turns out to be Modbus after all. This article helped me to setup a stable serial reader and this one helped me to get to the Modbus result. This is the output now:
110c28beff6abb
110c28be4002753e00003f0c0242b3003f71
110c28be2d7fff3d00000c002437019a3803b63b023c3c0048358000fd22
110c0566ffa0b2
110c05664002623e00003f0c0242b30082ca
110c05662d7fff3d00000c002437019a3803b63b024e3c004835800054c5
110c04c9ff8c82
110c04c94002c53e00003f0c0242b300a1fd
110c04c92d7fff3d00000c002437019a3803b63b02c43c00483580008356
110c04eaff95b2
110c04ea4002c43e00003f0c0242b3008a9b
110c04ea2d7fff3d00000c002437019a3803b63b02c43c0048358000d777
110c04c5ff8982
110c04c54002a03e00003f0c0242b300a39f
110c04c52d7fff3d00000c002437019a3803b63b027c3c00483580004432
110c04dbff8022
110c04db4002c73e00003f0c0242b30039e5
110c04db2d7fff3d00000c002437019a3803b63b02c33c00483580000ab1
110c055dffb382
110c055d4002843e00003f0c0242b3003df8
110c055d2d7fff3d00000c002437019a3803b63b027c3c0048358000edf8
Now that I have a readable result, I do have another problem: The serial bus keeps sending the event log for all thermostats i.e. function code 12 (0x0C) Get Comm Event Log. I have no idea how to get rid of this as all the responses start with \x11\x0c minimalmobus can't match a request to the right slave (\x11 will be slave number 17, while I request data from slave number 1). What to do here?
minimalmodbus config
import minimalmodbus
from gpiozero import OutputDevice
de = OutputDevice(23)
re = OutputDevice(24)
de.off()
re.off()
instrument = minimalmodbus.Instrument('/dev/serial0', 1, minimalmodbus.MODE_RTU)
instrument.serial.timeout = None
instrument.debug = True
read_register output
>>> instrument.read_register(40006,0,3,True)
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 9C 46 00 01 4B 8F (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/serial0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 2965.81 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: 11 0C 1B CA FF BD B4 (7 bytes), roundtrip time: 7.0 ms. Timeout for reading: 0.0 ms.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 486, in read_register
payloadformat=_Payloadformat.REGISTER,
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1245, in _generic_command
payload_from_slave = self._perform_command(functioncode, payload_to_slave)
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1330, in _perform_command
response, self.address, self.mode, functioncode
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1875, in _extract_payload
responseaddress, slaveaddress, response
minimalmodbus.InvalidResponseError: Wrong return slave address: 17 instead of 1. The response is: '\x11\x0c\x1bÊÿ½´'
Do you guys know what to do? Is it possible that the Uponor Smatrix Base X-245 only has a subset of the Modbus functions implemented? If so, what would my best shot be to write something back?
I tried to capture a possible request to change the temperature by adjusting it on the thermostat, but all I can see is the log where I went from 21,5°C (707°K, \x02\xc4) to 25,0°C (770°K, \x03\x02)
110c04eaff95b2
110c04ea4002c43e00003f0c02 42b3008a9b
110c04ea2d7fff3d00000c002437019a3803b63b02c43c0048358000d777
110c04eaff95b2
110c04ea4002c43e00003f0c02 3c00483b030242b3004466
110c04ea2d7fff3d00000c002437019a3803b63b03023c0048358000b0b7
110c04eaff95b2
110c04ea4002c43e00003f0c023c00483b030242b3004466
110c04ea2d7fff3d00400c002437019a3803b63b03023c0048358000a578
110c04eaff95b2
110c04ea4002c43e00003f0c0242b3008a9b
110c04ea2d7fff3d00400c002437019a3803b63b03023c0048358000a578
Upvotes: 1