Overview
This Python script is designed to establish a serial communication with a device
(referred to as the Burro IPA) over a specified serial port. The main purpose of
the script is to send a handshake message (@HLWD*) to the device and wait for an
acknowledgment response (#ACK*). If the acknowledgment is received, it indicates
that the device is ready for communication. The script includes error handling
mechanisms to manage issues with the serial connection and allows for graceful
termination via a keyboard interrupt.
Functions
- The main function establishes serial communication over a specified USB or TTL
connection using the provided port and baud rate.
- It enters a continuous loop to send a request message (@HLWD_) to the Burro
IPA robot, initiating a handshake to establish communication.
- Upon receiving a response from the robot, it processes the incoming data to
confirm if an acknowledgment (#ACK_) is received.
- If the acknowledgment is successful, the function prepares to send a status
check request (?STTN_) to the robot, querying its current station status.
- It reads the response from the robot, interprets the data, and checks if the
robot is stopped at a station.
- If the robot is confirmed to be stopped, the function sends a specific message
to the robot and activates an LED to indicate the status visually.
Example
example_client_handshake.py
import serial
import logging
import argparse
import sys
import time
def setup_logging():
""" Set up the logging format. """
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def parse_arguments():
""" Parse command line arguments. """
parser = argparse.ArgumentParser(description="Send a request for communication over serial to the Burro IPA.",
epilog="Example: python3 example_client_handshake.py --port /dev/ttyUSB1")
parser.add_argument("--port", default="/dev/ttyUSB0", help="Serial port to connect to.")
parser.add_argument("--baud", type=int, default=115200, help="Baud rate for the serial connection.")
parser.add_argument("--timeout", type=float, default=0.5, help="Read timeout for the serial connection.")
return parser.parse_args()
def main():
# Setup for some nice script tools
setup_logging()
args = parse_arguments()
logging.info(f"Open serial device: port={args.port}, baud={args.baud}, timeout={args.timeout}")
while True:
try:
# Initialize the serial connection
device = serial.Serial(args.port, args.baud, timeout=args.timeout)
except serial.SerialException as e:
logging.error(f"Failed to open serial port: {e}")
try:
# Send the greeting `@HLWD_` in order to let the robot know you are ready to communicate. Expect to get an
# `ACK_` in return if successful communication has been established.
handshake = "@HLWD_"
ack = "#ACK_"
# Send the greeting
device.write((handshake + '\r').encode())
tic = time.time()
# Read the response
incoming_data = device.read_until(b'\r').decode().strip()
toc = time.time()
logging.info(f"Received: {incoming_data} ({1000*(toc-tic):.3f}ms)")
# If the response is an ACK then you have made contact. You can exit this example if it is a seperate file
# or add onto it if you want this to be the main program you run.
if incoming_data == ack:
logging.info("ACK received.")
sys.exit(0)
# Sleep for a short duration before retrying to prevent spamming date along the connection.
time.sleep(0.5)
except KeyboardInterrupt:
# Quit if you get a `CTRL^C`.
logging.info("Exiting...")
sys.exit(0)
except Exception as e:
# Log any errors but do not crash.
logging.error(f"Error: {e}")
if __name__ == '__main__':
main()