Skip to content

Commit dec6b30

Browse files
committed
Update auto detection arduino code
1 parent 4df4ad1 commit dec6b30

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
## BioAmp Tool - Python
1+
# BioAmp Tool - Python
22

33
The BioAmp Tool is a Python script designed to interface with an Arduino-based bioamplifier, read data from it, optionally log this data to CSV or stream it via the Lab Streaming Layer (LSL), and visualize it through a graphical user interface (GUI) with live plotting.
44

5+
**_Note_**: Flash Arduino code to your hardware from [Chords Arduino Firmware](https://github.com/upsidedownlabs/Chords-Arduino-Firmware) to use this python tool.
6+
57
## Features
68

79
- **Automatic Arduino Detection:** Automatically detects connected Arduino devices via serial ports.
@@ -13,7 +15,7 @@ The BioAmp Tool is a Python script designed to interface with an Arduino-based b
1315

1416
## Requirements
1517

16-
- Python 3.x
18+
- Python 3.x
1719
- `pyserial` library (for serial communication)
1820
- `pylsl` library (for LSL streaming)
1921
- `argparse`, `time`, `csv`, `datetime` (standard libraries)
@@ -102,7 +104,8 @@ Handles command-line argument parsing and initiates data processing.
102104
- **Stream Name**: `BioAmpDataStream`
103105
- **Stream Type**: `EXG`
104106
- **Channel Count**: `6`
105-
- **Sampling Rate**: `250 Hz`
107+
- **Sampling Rate**: `250 Hz` for `UNO-R3`
108+
: `500 Hz` for `UNO-R4`
106109
- **Data Format**: `float32`
107110
108111
If GUI is not enabled, you can use an LSL viewer (e.g., BrainVision LSL Viewer) to visualize the streamed data in real-time.

bioamptool.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import numpy as np # For handling numeric arrays
3939
import pyqtgraph as pg # For real-time plotting
4040
from pyqtgraph.Qt import QtWidgets, QtCore # PyQt components for GUI
41-
import msvcrt #for keyboard interruptions
41+
import msvcrt #For keyboard interruptions
4242

4343
# Initialize global variables for tracking and processing data
4444
total_packet_count = 0 # Total packets received in the last second
@@ -48,30 +48,40 @@
4848
previous_sample_number = None # Store the previous sample number for detecting missing samples
4949
missing_samples = 0 # Count of missing samples due to packet loss
5050
buffer = bytearray() # Buffer for storing incoming raw data from Arduino
51+
NUM_CHANNELS = 6 #Number of Channels being received
52+
data = np.zeros((6, 2000)) # 2D array to store data for real-time plotting (6 channels, 2000 data points)
53+
samples_per_second = 0 # Number of samples received per second
54+
55+
# Initialize gloabal variables for Arduino Board
56+
board = "" # Variable for Connected Arduino Board
57+
boards_sample_rate = {"UNO-R3":250, "UNO-R4":500} #Standard Sample rate for Arduino Boards Different Firmware
58+
59+
# Initialize gloabal variables for Incoming Data
5160
PACKET_LENGTH = 16 # Expected length of each data packet
5261
SYNC_BYTE1 = 0xc7 # First byte of sync marker
5362
SYNC_BYTE2 = 0x7c # Second byte of sync marker
5463
END_BYTE = 0x01 # End byte marker
55-
NUM_CHANNELS = 6
56-
HEADER_LENGTH = 3
64+
HEADER_LENGTH = 3 #Length of the Packet Header
65+
66+
## Initialize gloabal variables for Output
5767
lsl_outlet = None # Placeholder for LSL stream outlet
5868
verbose = False # Flag for verbose output mode
59-
data = np.zeros((6, 2000)) # 2D array to store data for real-time plotting (6 channels, 2000 data points)
6069
csv_filename = None # Store CSV filename
61-
samples_per_second = 0 # Number of samples received per second
62-
6370

6471
# Function to automatically detect the Arduino's serial port
6572
def auto_detect_arduino(baudrate, timeout=1):
6673
ports = serial.tools.list_ports.comports() # List available serial ports
6774
for port in ports: # Iterate through each port
6875
try:
6976
ser = serial.Serial(port.device, baudrate=baudrate, timeout=timeout) # Try opening the port
77+
ser.write(b'WHORU\n')
7078
time.sleep(1) # Wait for the device to initialize
71-
response = ser.readline().strip() # Try reading from the port
79+
response = ser.readline().strip().decode() # Try reading from the port
7280
if response: # If response is received, assume it's the Arduino
81+
global board
7382
ser.close() # Close the serial connection
74-
print(f"Arduino detected at {port.device}") # Notify the user
83+
print(f"{response} detected at {port.device}") # Notify the user
84+
board = response
7585
return port.device # Return the port name
7686
ser.close() # Close the port if no response
7787
except (OSError, serial.SerialException): # Handle exceptions if the port can't be opened
@@ -211,7 +221,7 @@ def log_ten_minute_data(verbose=False):
211221
print(f"Total data count after 10 minutes: {cumulative_packet_count}") # Print cumulative data count
212222
sampling_rate = cumulative_packet_count / (10 * 60) # Calculate sampling rate
213223
print(f"Sampling rate: {sampling_rate:.2f} samples/second") # Print sampling rate
214-
expected_sampling_rate = 250 # Expected sampling rate
224+
expected_sampling_rate = boards_sample_rate[board] # Expected sampling rate
215225
drift = ((sampling_rate - expected_sampling_rate) / expected_sampling_rate) * 3600 # Calculate drift
216226
print(f"Drift: {drift:.2f} seconds/hour") # Print drift
217227
cumulative_packet_count = 0 # Reset cumulative packet count
@@ -225,7 +235,7 @@ def parse_data(port, baudrate, lsl_flag=False, csv_flag=False, gui_flag=False, v
225235

226236
# Start LSL streaming if requested
227237
if lsl_flag:
228-
lsl_stream_info = StreamInfo('BioAmpDataStream', 'EXG', 6, 250, 'float32', 'UpsideDownLabs') # Define LSL stream info
238+
lsl_stream_info = StreamInfo('BioAmpDataStream', 'EXG', 6, boards_sample_rate[board], 'float32', 'UpsideDownLabs') # Define LSL stream info
229239
lsl_outlet = StreamOutlet(lsl_stream_info) # Create LSL outlet
230240
print("LSL stream started") # Notify user
231241
time.sleep(0.5) # Wait for the LSL stream to start

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
numpy==2.1.1
22
pylsl==1.16.2
33
pyqtgraph==0.13.7
4-
pyserial==3.5
4+
pyserial==3.5
5+
PySide2==5.15.2.1

0 commit comments

Comments
 (0)