Pymate-RS485-basic
The RS485 bus can be reached on A+, B- terminals.
This is an HALF-DUPLEX RS485 implementation using only 2 wires.
Accessing the RS485 bus
The RS485 bus is available through the Board.rs485 property from pymate.board library.
The property returns the UART object to communicates over the RS485 bus and the tx_mode pin to switch between RX (receiving) and TX (emitting) on the RS485 bus.
from pymate.board import Board
brd = Board()
rs485,tx_mode = brd.rs485(baudrate=9600)Switch on the tx_mode pin before emitting data on the bus then switch tx_mode off (receiving) immediately after to get ready for receiving the response.
Data emission and reception uses the micropython UART class as described in the MicroPython machine.UART documentation.
Practical example
The following example shows how to grab the data from a RS485 Wind Direction device.
The Wind Direction is a Modbus device. So the example script below will implements the raw Modbus request (without Modbus library) and decipher the Modbus response.
That example demonstrate RS485 direct access.
The master send the request to read register 0x0000 on slave 0x02. The function code 0x03 = 'read holding register'.
From that request we do expect the following response from the device.
The data contains the angular position in degrees * 10 the value is encoded as an uint16.
The angle can be converted to wind direction thanks to simple rule:
Code
The example is articulated around the:
- rs485 instance creation with rs485, tx_mode = brd.rs485
- send_request : emitting the request to the device over RS485 with tx_mode.on() then rs485.write() followed by tx_mode.off()
- read_response : receiving response over RS485 with rs485.readinto()
Remark: The two data bytes of the response are transformed to uint16 (Unsigned 16bit Integer) with the struct.unpack().
from pymate.board import Board
import time, struct
DIR_TO_TEXT = ['North', 'Northeast by North', 'Northeast', 'Northeast by east', 'East',
'Southeast by east', 'Southeast', 'Southeast by south', 'South', 'Southwest by south',
'Southwest', 'Southwest by west', 'West', 'Northwest by west', 'Northwest', 'Northwest by north' ]
def dir_as_text( value ):
if 0<=value<=len(DIR_TO_TEXT):
return DIR_TO_TEXT[value]
return '???'
def send_request( rs485, tx_mode ):
tx_mode.on()
request_msg = [0x02,0x03,0x00,0x00,0x00,0x01,0x84,0x39]
winddir_request = bytearray( request_msg )
rs485.write( winddir_request )
tx_mode.off()
def read_response(rs485, tx_mode ):
# Response in 7 bytes
buf = bytearray( 7 )
rs485.readinto( buf )
# Decode the response
# 0 & 1 are the slave addr + function code
if not( (buf[0]==0x02) and (buf[1]==0x03) ):
raise Exception( 'Invalid Slave/function' )
if buf[2] != 0x02:
raise Exception( 'Invalid response length' )
# bytes 3 & 4 are the data. With value in degree * 10.
# bytes 5 & 6 are CRC (not checked here)
# Decode unit16
value = struct.unpack('>H', buf[3:5])[0]
degree = value/10
orientation = int(degree/22.5) # from 0 to 15
# Returns the direction-value and direction-label
return degree, orientation, dir_as_text( orientation )
# === Main Program ===
brd = Board()
rs485,tx_mode = brd.rs485(baudrate=9600)
while True:
send_request( rs485, tx_mode )
time.sleep_ms( 100 ) # give sometime for the buffer to get data, Tune it as needed
try:
degree,value,label = read_response( rs485, tx_mode )
print( "Direction:",value,'=', label, "| Degree:", degree )
except Exception as err:
print( 'Error decoding response' )
print( '[ERROR]', err )
time.sleep_ms( 1000 )Once running, the script will return the following results
Direction: 4 = East | Degree: 100.2 Direction: 4 = East | Degree: 100.2 Direction: 4 = East | Degree: 100.2 Direction: 5 = Southeast by east | Degree: 129.6 Direction: 6 = Southeast | Degree: 135.2 Direction: 1 = Northeast by North | Degree: 43.2 Direction: 5 = Southeast by east | Degree: 119.8 Direction: 6 = Southeast | Degree: 153.7 Direction: 7 = Southeast by south | Degree: 174.8 Direction: 14 = Northwest | Degree: 333.7 Direction: 4 = East | Degree: 110.5 Direction: 8 = South | Degree: 199.5 Direction: 10 = Southwest | Degree: 242.7 Direction: 11 = Southwest by west | Degree: 264.8 Direction: 11 = Southwest by west | Degree: 268.4 Direction: 12 = West | Degree: 270.0
RS485 Errors
Unable to communicate over RS485
Sometime, it is necessary to give a little push to the RS485 bus to improve communication signal.
When the 120 Ω terminator resistor is not enough to a communication, you can add a 1 KΩ Pull-Up Resistor from A+ to 5V as well as a 1 KΩ pull-Down resistor to GND.
Here an example based on Power-Meter.
PymateIO all right reserved © 2026 - Written by MCHobby for PymateIO



