From 8abc3b07096e420b487f9c4cfaf9ce805cb4d2b0 Mon Sep 17 00:00:00 2001 From: vanyabeat Date: Wed, 24 Jan 2024 00:34:54 +0300 Subject: [PATCH] ADD: DEADBEEF packet and vizualize #8 --- vizualize.py | 116 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 38 deletions(-) diff --git a/vizualize.py b/vizualize.py index 5170bb0..816d0f1 100644 --- a/vizualize.py +++ b/vizualize.py @@ -1,48 +1,88 @@ import serial +import struct +import threading import matplotlib.pyplot as plt -import matplotlib.animation as animation -import numpy as np +from matplotlib.animation import FuncAnimation +# Configure your serial port settings. +SERIAL_PORT = '/dev/ttyUSB0' # Update to match your serial port. +BAUD_RATE = 115200 # Update to match your settings. +FLOAT_SIZE = 4 # Size of a float in bytes (usually 4 bytes) -# Open the serial port. Replace 'COM3' with your serial port name. -serial_port = '/dev/ttyUSB0' -baud_rate = 115200 # Adjust as per your device configuration -ser = serial.Serial(serial_port, baud_rate, timeout=1) +# Shared state, updated by the reading thread, read by the plotting function. +# Initialize values with None. +adc_values = [None, None, None] +angle = None -# Setup the matplotlib figure and axes for polar plot. -fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}) -line, = ax.plot([], [], 'b-', lw=2) # Line object to update the angle -ax.set_ylim(0, 1) # Set the radius range (fixed in this case) +# Define the thread that will read the serial data. +def read_serial_data(ser): + global adc_values, angle + try: + while True: + byte = ser.read(1) + if byte == b'\xDE': + next_byte = ser.read(1) + if next_byte == b'\xAD': + data = ser.read(FLOAT_SIZE * 4) + if len(data) == FLOAT_SIZE * 4: + floats = struct.unpack('<4f', data) + packet_end = ser.read(2) + if packet_end == bytes([0xBE, 0xAF]): + # Update our shared state. + adc_values = list(floats[0:3]) + angle = floats[3] + except serial.SerialException as e: + print("Serial exception:", e) + except struct.error as e: + print("Unpacking error:", e) + except: + print("Other error or thread exiting.") -# Adjust the orientation so that 0 is up and the angle proceeds clockwise. -ax.set_theta_zero_location('N') -ax.set_theta_direction(-1) +# Start the serial reader in a separate thread. +thread = threading.Thread(target=read_serial_data, args=(serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1),)) +thread.daemon = True # Thread will be killed when the main thread exits. +thread.start() -# Initialization function to clear the data. -def init(): - line.set_data([], []) - return (line,) +# Set up the Matplotlib figures and axes. +fig = plt.figure(figsize=(10, 5)) -# Update function that reads from the serial port -# and updates the plot with the new angle. -def update(frame): - line.set_data([], []) - raw_data = ser.readline().strip() - angle = 0 - if raw_data: - try: - angle = float(raw_data) - except: - angle = 0 - angle_rad = np.deg2rad(angle) # Convert to radians - # Update the plot with the new angle. - line.set_data([angle_rad, angle_rad], [0, 1]) - return (line,) +# Create a normal subplot for the bar graph. +ax_bar = fig.add_subplot(1, 2, 1) -# Create the animation object with a suitable update interval (ms). -ani = animation.FuncAnimation(fig, update, init_func=init, blit=True, interval=1) +# Create another subplot for the polar plot by specifying polar=True. +ax_polar = fig.add_subplot(1, 2, 2, polar=True) -# Start the plot animation +# Set the properties for polar plot. +ax_polar.set_theta_zero_location('N') +ax_polar.set_theta_direction(-1) + +# Bar plot axis. +bars = ax_bar.bar(['ADC0', 'ADC1', 'ADC2'], [0, 0, 0]) +ax_bar.set_ylim(0, 0.4) # Set the limit for your ADC values. + +# Polar plot axis. +ax_polar.set_theta_zero_location('N') +ax_polar.set_theta_direction(-1) +angle_plot, = ax_polar.plot([], [], 'go') # Initial empty plot. + +# Update function for the animation. +def update(i): + # Global variables holding the shared state. + global adc_values, angle + + # Check if we have received new data. + if all(v is not None for v in adc_values) and angle is not None: + # Update the bar plot. + for bar, value in zip(bars, adc_values): + bar.set_height(value) + + # Update the polar plot. + angle_rad = angle / 180.0 * 3.14159 # Convert degrees to radians. + angle_plot.set_data([angle_rad], [1]) # Set angle for the plot, using radial distance of 1. + + return bars.patches + [angle_plot] + +# Create the animation itself, which will call update function repeatedly. +ani = FuncAnimation(fig, update, blit=True, interval=1) # Update interval is in milliseconds. + +# Show the plot. plt.show() - -# Closing the serial port after the plot is closed. -ser.close() \ No newline at end of file