1
0
micropython-rp2-rs485-examples/rs485_pingpong.py

95 lines
4.3 KiB
Python

'''
A program supposed to run on two RP2040 connected over two channel of an RS485 bus over TTL-UART-to-RS485 converters, and illustrates a simple ping-pong.
Copyright (C) 2024 Benjamin Burkhardt
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
from machine import UART, Pin
import time
# CHANGE THIS to 'True' on one of the machines (as it
# tells the rp2040 to do the first step in ping-pong communication ;)
INITIALIZER = True
# define the UART in-/outputs, named after their usage as either send or receive channels...
# ...depending on wether this is the INITIALIZER or not.
# sure, the in and out pins could be defined in other ways also, but this allows easy customizability...
# ...as just one variable needs to be changed.
print('[UART] Initializing UART for two channels...')
if INITIALIZER: # then read on ch0 and write on ch1
receiver = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
sender = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))
else:
sender = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
receiver = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))
print('[UART] Initialized UART for two channels.')
# initialize the read/write channels and set their value
print('[UART] Setting output/input for each channel...')
if INITIALIZER: # then enable read on ch0 and write on ch1
receiver_channel_mode = Pin(2, Pin.OUT) # define pinout for the receiver/driver enable pins of channel 0 (shortened together)
sender_channel_mode = Pin(3, Pin.OUT) # define pinout for the receiver/driver enable pins of channel 1 (shortened together)
else:
sender_channel_mode = Pin(2, Pin.OUT)
receiver_channel_mode = Pin(3, Pin.OUT)
receiver_channel_mode.low()
sender_channel_mode.high()
print(f'[UART] Set output/input for each channel. Pin 2 is now {"low" if INITIALIZER else "high"} (CH0 as {"input" if INITIALIZER else "output"}), Pin 3 is now {"high" if INITIALIZER else "low"} (CH1 as {"output" if INITIALIZER else "input"}).')
# some logging
print('[INFO] Set up RS485 ping-pong.')
# now, the REAL PING-PONG mechanism begins
# the counter variable will be increased with every ping
# received (which is a pong from the other side which resulted out of a ping there ;)
a = 0
# make the first step if INITIALIZER is True (see above at declaration)
if INITIALIZER:
sender.write(f'{a}\r\n')
sender.flush()
print(f'[UART] Sent initial ping: {a}')
print('[INFO] Now waiting for incoming pings/pongs.')
# now listen for a pong from the other side and answer to it
rxDataConcatenated = '' # to combine partial received data to one full packet (actually just a string that ends with \n :)
while True:
rxData = receiver.readline()
if rxData is not None:
rxDataDecoded = rxData.decode('utf-8')
if not '\n' in rxDataDecoded: # if the received data is not complete (does not end with a \n), just save the received part
rxDataConcatenated += rxDataDecoded
else: # if it's complete now, add the received part to the potentially saved parts and send the pong
rxDataConcatenated += rxDataDecoded
try:
a = int(rxDataConcatenated)
print(f"[UART] Received ping: {a}")
# send pong after some waiting (could also be left out completely!)
time.sleep(0.2)
a += 1
sender.write(f'{a}\r\n')
sender.flush()
print(f'[UART] Sent pong: {a}')
except:
receiver_error_details = repr(rxDataConcatenated)
print(f'[UART] Received invalid data? Wait until something good comes in! (received "{receiver_error_details}")')
rxDataConcatenated = '' # reset the received parts storage (see comments above!)