diff --git a/esp32_readout/esp32_readout.ino b/esp32_readout/esp32_readout.ino index 35f900b..6139d67 100644 --- a/esp32_readout/esp32_readout.ino +++ b/esp32_readout/esp32_readout.ino @@ -5,7 +5,8 @@ Display display; Adafruit_NAU7802 nau; unsigned long _millis = 0; int32_t val = 0; -bool goToSleep = False; +bool goToSleep = false; + #if BLE BLEServer *pServer = NULL; BLECharacteristic *millisCharacteristic = NULL; @@ -127,6 +128,8 @@ void loop() { } val = nau.read(); + Serial.print(millis()); Serial.print(","); Serial.println(val); + #if BLE if (deviceConnected) { // Send the sensor reading @@ -148,7 +151,5 @@ void loop() { // do stuff here on connecting oldDeviceConnected = deviceConnected; } - #else - Serial.print(millis()); Serial.print(","); Serial.println(val); #endif } diff --git a/filter_dev/app.py b/filter_dev/app.py index 3d6116d..6cef755 100644 --- a/filter_dev/app.py +++ b/filter_dev/app.py @@ -1,6 +1,6 @@ import tkinter as tk import matplotlib.pyplot as plt -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import asyncio @@ -20,19 +20,9 @@ class FilterDevApp(tk.Tk): self.title("JannTers Filter Evaluation Tool") - # Create a frame for the plot and sliders - self.frame = tk.Frame(self) - self.frame.pack(side=tk.LEFT, fill=tk.BOTH) - - # Create a figure for plotting - self.fig, self.ax = plt.subplots() - self.ax2 = self.ax.twinx() - self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame) - self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH) - # Create a frame for sliders self.toolbar = tk.Frame(self, width=200, padx=10) - self.toolbar.pack(side=tk.RIGHT, fill=tk.Y) + self.toolbar.pack(side=tk.LEFT) # Device Settings self.record_form = RecordForm(self.toolbar, self.record_data) @@ -46,6 +36,16 @@ class FilterDevApp(tk.Tk): self.data_stats = DataStats(self.toolbar, self.reset) + # Create a figure for plotting + self.frame = tk.Frame(self) + self.frame.pack(side=tk.RIGHT) + + self.fig, self.ax = plt.subplots() + self.ax2 = self.ax.twinx() + self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame) + self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH) + NavigationToolbar2Tk(self.canvas, self.frame) + def update_plot(self): if self.filter is None: return @@ -61,19 +61,27 @@ class FilterDevApp(tk.Tk): # Generate data x = df['timestamps'] y1 = df['weights'] - # y1_g = df['calib_weights'] - # y2 = df['filtered'] + y2 = df['filtered'] y2_g = df['filtered_calib'] # Plot the data - self.ax.plot(x, y1) - # self.ax.plot(x, y2) + self.ax.plot(x, y1, label="raw") + self.ax.plot(x, y2, label="filtered") + + # self.ax2.plot(x, y1_g) + self.ax2.plot(x, y2_g, label="filtered", color='green') + self.ax2.set_ylabel("Weight", color="green") + self.ax.set_xlabel("Time in ms") self.ax.set_ylabel("Raw Weight") self.ax.grid() + self.ax.legend(loc='upper left') + self.ax2.yaxis.set_label_position("right") + self.ax2.yaxis.tick_right() + self.ax2.legend(loc='lower right') - # self.ax2.plot(x, y1_g) - self.ax2.plot(x, y2_g, color="orange") + self.fig.tight_layout() + self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH) # Draw the updated plot self.canvas.draw() diff --git a/filter_dev/config.py b/filter_dev/config.py index fdb7ba5..0a8e5c2 100644 --- a/filter_dev/config.py +++ b/filter_dev/config.py @@ -3,4 +3,4 @@ SERVICE_UUID = "9f0dfdb2-e978-494c-8f15-68dbe8d28672" MILLIS_UUID = "abb92561-a809-453c-8c7c-71d3fff5b86e" WEIGHT_UUID = "123e4567-e89b-12d3-a456-426614174000" -DEFAULT_CALIB = 104167.17 \ No newline at end of file +DEFAULT_CALIB = 307333.83 \ No newline at end of file diff --git a/filter_dev/filter/base.py b/filter_dev/filter/base.py index 7312a3e..3f8d2ae 100644 --- a/filter_dev/filter/base.py +++ b/filter_dev/filter/base.py @@ -32,6 +32,10 @@ class Filter: def __call__(self) -> pd.DataFrame: calib_factor = 100. / float(self.calib_entry.get()) df = self.device.data + + df = df[df['weights'] < 10e9] + df['timestamps'] -= df['timestamps'].min() + df['filtered'], df['filtered_calib'] = self.filter(df, calib_factor) df['calib_weights'] = df['weights'] * calib_factor return df diff --git a/filter_dev/gui/device.py b/filter_dev/gui/device.py index a5b5ce3..172eeef 100644 --- a/filter_dev/gui/device.py +++ b/filter_dev/gui/device.py @@ -2,8 +2,8 @@ from bleak import BleakClient, BleakScanner import pandas as pd from tkinter.ttk import Entry from tkinter.messagebox import showerror, showinfo -import asyncio from time import time +from serial import Serial from ..config import MILLIS_UUID, WEIGHT_UUID @@ -27,7 +27,12 @@ class Device: self.weights = [] async def connect(self): - self.device = await BleakScanner.find_device_by_name(self.device_name.get()) + device_name = self.device_name.get() + + if device_name.startswith('/dev'): + self.device = device_name + else: + self.device = await BleakScanner.find_device_by_name(self.device_name.get()) return self.device is not None @@ -35,25 +40,50 @@ class Device: self.device = None async def read_values(self, duration): + duration = int(duration) + if not await self.connect(): showerror("Record Data", f"Device {self.device_name.get()} not found!") return - - self.clear_data() - async with BleakClient(self.device.address) as client: - showinfo("Recording Data", f"Recording data for {duration} seconds.") + + if isinstance(self.device, str): + self._read_values_serial(duration) + else: + await self._read_values_ble(duration) + + def _read_values_serial(self, duration): + with Serial(self.device, baudrate=115200) as ser: + showinfo("Record Data", f"Recording data for {duration} seconds.") time_start = time() time_passed = 0 while time_passed < duration: - millis = await client.read_gatt_char(MILLIS_UUID) - millis = int.from_bytes(millis, byteorder='little') # Adjust based on your data format - weight = await client.read_gatt_char(WEIGHT_UUID) - weight = int.from_bytes(weight, byteorder='little') # Adjust based on your data format + line = ser.readline() + _timestamp, _raw_weight = line.decode('utf-8').split(',') - self.timestamps.append(millis) - self.weights.append(weight) + self.timestamps.append(int(_timestamp)) + self.weights.append(int(_raw_weight)) time_passed = time() - time_start + + async def _read_values_ble(self, duration): + self.clear_data() + try: + async with BleakClient(self.device.address) as client: + showinfo("Record Data", f"Recording data for {duration} seconds.") + time_start = time() + time_passed = 0 + while time_passed < duration: + millis = await client.read_gatt_char(MILLIS_UUID) + millis = int.from_bytes(millis, byteorder='little') # Adjust based on your data format + weight = await client.read_gatt_char(WEIGHT_UUID) + weight = int.from_bytes(weight, byteorder='little') # Adjust based on your data format + + self.timestamps.append(millis) + self.weights.append(weight) + + time_passed = time() - time_start + except: + showerror("Record Data", f"Client could not be started for {self.device_name.get()}: {self.device.address}.") def clear_data(self): diff --git a/filter_dev/gui/toolbar/record_form.py b/filter_dev/gui/toolbar/record_form.py index f68a696..fb43cec 100644 --- a/filter_dev/gui/toolbar/record_form.py +++ b/filter_dev/gui/toolbar/record_form.py @@ -3,17 +3,24 @@ from tkinter import ttk from ..slider import Slider +from serial.tools import list_ports + class RecordForm(tk.Frame): def __init__(self, master, record_command, **kwargs): super().__init__(master, **kwargs) - self.device_label = ttk.Label(self, text="Device Name:") + # get serial ports + serials = [d.device for d in list_ports.grep('usbmodem')] + devices = serials + ["Smaage"] + default_record_len = 10 if len(serials) > 0 else 30 + + self.device_label = ttk.Label(self, text="Device:") self.device_label.pack(pady=10) - self.device_name = ttk.Entry(self) - self.device_name.insert(0, "Smaage") # Set default value + self.device_name = ttk.Combobox(self, values=devices) + self.device_name.set(devices[0]) self.device_name.pack() - self.record_time = Slider(self, "Record Time:", 10, 30, 10, lambda: None) + self.record_time = Slider(self, "Record Time:", 10, 60, default_record_len, lambda: None) self.record_time.pack(pady=10) self.record_button = ttk.Button(self, text="Record Data", command=record_command) self.record_button.pack(pady=10) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 5f823fa..09b6d50 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ matplotlib bleak pandas tqdm -numpy \ No newline at end of file +numpy +pyserial \ No newline at end of file