|  | 
|  | 1 | +import logging | 
|  | 2 | +logging.basicConfig(level=logging.DEBUG) | 
|  | 3 | + | 
|  | 4 | +# import serial | 
|  | 5 | +import matplotlib.pyplot as plt | 
|  | 6 | + | 
|  | 7 | +# from matplotlib.animation import FuncAnimation, FFMpegWriter | 
|  | 8 | +import ffmpegio as ff | 
|  | 9 | + | 
|  | 10 | +from datetime import datetime, timedelta | 
|  | 11 | +import numpy as np | 
|  | 12 | +import schedule | 
|  | 13 | +import time | 
|  | 14 | + | 
|  | 15 | +# Constants | 
|  | 16 | +GRAVITY = 9.81  # Standard gravity in m/s² | 
|  | 17 | + | 
|  | 18 | +# Initialize serial connections to HC-06 devices | 
|  | 19 | +# ser_x_accel = serial.Serial('COM4', 9600, timeout=1)  # X-axis acceleration data | 
|  | 20 | +# ser_y_angle = serial.Serial('COM11', 9600, timeout=1)  # Y-axis angle data | 
|  | 21 | + | 
|  | 22 | +# Initialize empty lists to store data | 
|  | 23 | +x_accel_data = [] | 
|  | 24 | +y_angle_data = [] | 
|  | 25 | +timestamps = [] | 
|  | 26 | + | 
|  | 27 | +# Initialize Excel workbook | 
|  | 28 | +# wb = openpyxl.Workbook() | 
|  | 29 | +# ws = wb.active | 
|  | 30 | +# ws.title = "Sensor Data" | 
|  | 31 | +# ws.append(["Timestamp", "X Acceleration (m/s²)", "Y Angle (degrees)"]) | 
|  | 32 | + | 
|  | 33 | + | 
|  | 34 | +# Function to update the plot and log data | 
|  | 35 | +def update(f): | 
|  | 36 | +    # Read data from serial connections | 
|  | 37 | +    line_x_accel = np.random.randn(1)  # ser_x_accel.readline().decode('utf-8').strip() | 
|  | 38 | +    line_y_angle = np.random.randn(1)  # ser_y_angle.readline().decode('utf-8').strip() | 
|  | 39 | + | 
|  | 40 | +    try: | 
|  | 41 | +        # Parse and process X-axis acceleration data | 
|  | 42 | +        x_accel_g = float(line_x_accel)  # Acceleration in g read from serial | 
|  | 43 | +        x_accel_ms2 = x_accel_g * GRAVITY  # Convert from g to m/s² | 
|  | 44 | +        x_accel_data.append(x_accel_ms2) | 
|  | 45 | + | 
|  | 46 | +        # Parse and process Y-axis angle data | 
|  | 47 | +        y_angle = float(line_y_angle) | 
|  | 48 | +        y_angle_data.append(y_angle) | 
|  | 49 | + | 
|  | 50 | +        # Append timestamp | 
|  | 51 | +        timestamps.append(datetime.now()) | 
|  | 52 | + | 
|  | 53 | +        # Limit data points to show only the latest 100 | 
|  | 54 | +        if len(x_accel_data) > 100: | 
|  | 55 | +            x_accel_data.pop(0) | 
|  | 56 | +            y_angle_data.pop(0) | 
|  | 57 | +            timestamps.pop(0) | 
|  | 58 | + | 
|  | 59 | +        # Log data to Excel with timestamp | 
|  | 60 | +        # timestamp_str = timestamps[-1].strftime("%H:%M:%S") | 
|  | 61 | +        # ws.append([timestamp_str, x_accel_data[-1], y_angle_data[-1]]) | 
|  | 62 | + | 
|  | 63 | +        # Clear and update plots | 
|  | 64 | +        ax1.clear() | 
|  | 65 | +        ax1.plot(timestamps, x_accel_data, label="X Acceleration", color="b") | 
|  | 66 | +        ax1.legend(loc="upper left") | 
|  | 67 | +        ax1.set_ylim([-20, 20])  # Adjust based on expected acceleration range in m/s² | 
|  | 68 | +        ax1.set_title("Real-time X Acceleration Data") | 
|  | 69 | +        ax1.set_xlabel("Time") | 
|  | 70 | +        ax1.set_ylabel("Acceleration (m/s²)") | 
|  | 71 | +        ax1.grid(True) | 
|  | 72 | + | 
|  | 73 | +        ax2.clear() | 
|  | 74 | +        ax2.plot(timestamps, y_angle_data, label="Y Angle", color="g") | 
|  | 75 | +        ax2.legend(loc="upper left") | 
|  | 76 | +        ax2.set_ylim([-180, 180]) | 
|  | 77 | +        ax2.set_title("Real-time Y Angle Data") | 
|  | 78 | +        ax2.set_xlabel("Time") | 
|  | 79 | +        ax2.set_ylabel("Angle (degrees)") | 
|  | 80 | +        ax2.grid(True) | 
|  | 81 | + | 
|  | 82 | +        # Update text boxes with latest values | 
|  | 83 | +        text_box.set_text(f"X Acceleration: {x_accel_data[-1]:.2f} m/s²") | 
|  | 84 | +        text_box2.set_text(f"Y Angle: {y_angle_data[-1]:.2f}°") | 
|  | 85 | + | 
|  | 86 | +        # Save the workbook periodically (every 100 updates) | 
|  | 87 | +        # if frame % 100 == 0: | 
|  | 88 | +        # wb.save("sensor_data.xlsx") | 
|  | 89 | + | 
|  | 90 | +        # plt.draw() | 
|  | 91 | + | 
|  | 92 | +        # print("update", datetime.now()) | 
|  | 93 | +        f.write(fig) | 
|  | 94 | + | 
|  | 95 | +    except ValueError: | 
|  | 96 | +        pass  # Ignore lines that are not properly formatted | 
|  | 97 | + | 
|  | 98 | + | 
|  | 99 | +# Setup the plots | 
|  | 100 | +# with plt.ion(): | 
|  | 101 | +fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8)) | 
|  | 102 | +text_box = ax1.text( | 
|  | 103 | +    0.05, | 
|  | 104 | +    0.95, | 
|  | 105 | +    "", | 
|  | 106 | +    transform=ax1.transAxes, | 
|  | 107 | +    fontsize=12, | 
|  | 108 | +    verticalalignment="top", | 
|  | 109 | +    bbox=dict(boxstyle="round", facecolor="wheat", alpha=0.5), | 
|  | 110 | +) | 
|  | 111 | +text_box2 = ax2.text( | 
|  | 112 | +    0.05, | 
|  | 113 | +    0.95, | 
|  | 114 | +    "", | 
|  | 115 | +    transform=ax2.transAxes, | 
|  | 116 | +    fontsize=12, | 
|  | 117 | +    verticalalignment="top", | 
|  | 118 | +    bbox=dict(boxstyle="round", facecolor="wheat", alpha=0.5), | 
|  | 119 | +) | 
|  | 120 | + | 
|  | 121 | +with ff.open( | 
|  | 122 | +    "sandbox/test.mp4|[f=mpegts]udp://127.0.0.1:1234?pkt_size=1316", | 
|  | 123 | +    "wv", | 
|  | 124 | +    rate_in=10, | 
|  | 125 | +    y=ff.FLAG, | 
|  | 126 | +    show_log=True, | 
|  | 127 | +    preset="ultrafast", | 
|  | 128 | +    tune="zerolatency", | 
|  | 129 | +    vcodec="libx264", | 
|  | 130 | +    map= '0:v', | 
|  | 131 | +    f="tee", | 
|  | 132 | +) as f: | 
|  | 133 | +    s = schedule.every(0.1) | 
|  | 134 | +    s.seconds.until(datetime.now() + timedelta(seconds=10)).do( | 
|  | 135 | +        update, f | 
|  | 136 | +    )  # minutes=1) | 
|  | 137 | + | 
|  | 138 | +    while True: | 
|  | 139 | +        n = schedule.idle_seconds() | 
|  | 140 | +        if n is None: | 
|  | 141 | +            # no more jobs | 
|  | 142 | +            break | 
|  | 143 | +        elif n > 0: | 
|  | 144 | +            # sleep exactly the right amount of time | 
|  | 145 | +            time.sleep(n) | 
|  | 146 | +        schedule.run_pending() | 
|  | 147 | +        time.sleep(0.1) | 
|  | 148 | + | 
|  | 149 | +    print("schedule complete") | 
|  | 150 | + | 
|  | 151 | +# # Animate the plots | 
|  | 152 | +# ani = FuncAnimation(fig, update, interval=100)  # Update interval of 100ms | 
|  | 153 | + | 
|  | 154 | +# # Save the animation as a video file | 
|  | 155 | +# writer = FFMpegWriter(fps=10, metadata=dict(artist='Me'), bitrate=1800) | 
|  | 156 | +# ani.save("sensor_data.mp4", writer=writer) | 
|  | 157 | + | 
|  | 158 | +# plt.tight_layout() | 
|  | 159 | +# plt.show() | 
0 commit comments