102 lines
4.3 KiB
Python
102 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!)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|