Skip to content

FFT Visualizer-Multiple EEG & FFT Visualization #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9c7d6a7
Connection timeout increase to 15 as wifi takes time to connect
PayalLakra May 10, 2025
f44cbb7
Serial Connection Disconnection issue resolved
PayalLakra May 10, 2025
8a1730b
Serial Connection Disconnection issue resolved
PayalLakra May 10, 2025
053fd6a
Merge branch 'new' of https://github.com/PayalLakra/Chords-Python int…
PayalLakra May 10, 2025
f269693
Updated UI for fft visualizer(Multi channels)
PayalLakra May 10, 2025
2d70312
UI is done
PayalLakra May 12, 2025
0388aaa
Remove not required things
PayalLakra May 12, 2025
9776489
Adding functionality- When an app is running then a green tick is sho…
PayalLakra May 12, 2025
00ba008
Opacity reduces when an app is running
PayalLakra May 12, 2025
ebbba0e
CSV Filename can't be editable when recording is On.
PayalLakra May 12, 2025
cde94b3
Toast for Recording started, Recording stopped added(also timeout inc…
PayalLakra May 12, 2025
409ea22
CSV Filename timer update regularly
PayalLakra May 12, 2025
44fb655
Disconnect toast added with colour green(white text)
PayalLakra May 12, 2025
5e98400
logging.txt file is created that logs all the errors with timestamp
PayalLakra May 13, 2025
b818ce2
Merge branch 'upsidedownlabs:main' into new
PayalLakra May 13, 2025
325362a
Updated Readme
PayalLakra May 13, 2025
090a55c
Merge branch 'new' of https://github.com/PayalLakra/Chords-Python int…
PayalLakra May 13, 2025
15dc4c2
Updated Readme
PayalLakra May 13, 2025
f4e16c1
Updated Readme
PayalLakra May 13, 2025
8ae4832
Worked but issue is(On 10 hz it shoes peak at 8 hz)
PayalLakra Jun 14, 2025
eddadf0
for testing only
PayalLakra Jun 17, 2025
ef34cee
Removed unnecessary files
PayalLakra Jun 18, 2025
e0604b5
Timestamp based approach for lsl
PayalLakra Jun 18, 2025
720c5e1
Update chords_ble in standard form
PayalLakra Jun 18, 2025
b406ebc
Updated FFT, that works fine with all ble,serial,wifi and also now th…
PayalLakra Jun 18, 2025
4f41625
Changing the sampling rate
PayalLakra Jun 19, 2025
8cf5ee4
Worked- Smoothing is donw only once after fft is calculated then the …
PayalLakra Jun 19, 2025
0aaf8db
Skip DC Component(1st value)
PayalLakra Jun 19, 2025
ae8c37b
Corrected number of channels
PayalLakra Jun 19, 2025
a9b8b9d
Remove unnecessary files
PayalLakra Jun 19, 2025
f92d4e2
Applying Counter based lsl stream approach to ensure lsl stream sends…
PayalLakra Jun 19, 2025
75e7c8d
Adding Comments
PayalLakra Jun 19, 2025
ba9951e
Merge branch 'main' of https://github.com/upsidedownlabs/Chords-Pytho…
PayalLakra Jun 19, 2025
8a0fbd6
Updated Readme
PayalLakra Jun 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ async def scan_ble_devices():

@app.route('/check_stream')
def check_stream():
if connection_manager and connection_manager.stream_active:
return jsonify({'connected': True})
return jsonify({'connected': False})
is_connected = connection_manager.stream_active if hasattr(connection_manager, 'stream_active') else False
return jsonify({'connected': is_connected})

@app.route('/check_connection')
def check_connection():
Expand Down
62 changes: 43 additions & 19 deletions connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def __init__(self):
self.num_channels = 0
self.stream_active = False
self.recording_active = False
self.usb_thread = None
self.usb_running = False

async def get_ble_device(self):
devices = await Chords_BLE.scan_devices()
Expand Down Expand Up @@ -154,6 +156,25 @@ def notification_handler(sender, data):
print(f"BLE connection failed: {str(e)}")
return False

def usb_data_handler(self):
while self.usb_running:
try:
if self.usb_connection and hasattr(self.usb_connection, 'ser') and self.usb_connection.ser.is_open:
self.usb_connection.read_data()

if hasattr(self.usb_connection, 'data'):
sample = self.usb_connection.data[:, -1]
if self.lsl_connection:
self.lsl_connection.push_sample(sample)
if self.recording_active:
self.log_to_csv(sample.tolist())
time.sleep(0.001) # Small delay to prevent CPU overload
else:
time.sleep(0.1)
except Exception as e:
print(f"USB data handler error: {str(e)}")
break

def connect_usb(self):
self.usb_connection = Chords_USB()
if self.usb_connection.detect_hardware():
Expand All @@ -162,19 +183,12 @@ def connect_usb(self):

self.setup_lsl(self.num_channels, sampling_rate)

original_read_data = self.usb_connection.read_data
def wrapped_read_data():
original_read_data()
if hasattr(self.usb_connection, 'data') and self.lsl_connection:
sample = self.usb_connection.data[:, -1]
self.lsl_connection.push_sample(sample)
if self.recording_active:
self.log_to_csv(sample.tolist())

self.usb_connection.read_data = wrapped_read_data
# Start the USB streaming command
self.usb_connection.send_command('START')

# Start streaming in a separate thread
self.usb_thread = threading.Thread(target=self.usb_connection.start_streaming)
# Start the data handler thread
self.usb_running = True
self.usb_thread = threading.Thread(target=self.usb_data_handler)
self.usb_thread.daemon = True
self.usb_thread.start()
return True
Expand Down Expand Up @@ -213,7 +227,7 @@ def connect_wifi(self):
self.log_to_csv(channel_data)

except KeyboardInterrupt:
self.wifi_connection.disconnect()
self.wifi_connection.cleanup()
print("\nDisconnected")
finally:
self.stop_csv_recording()
Expand All @@ -223,22 +237,27 @@ def cleanup(self):

if self.lsl_connection:
self.lsl_connection = None
self.stream_active = False
print("LSL stream stopped")

if self.usb_connection:
try:
self.usb_connection.cleanup()
self.usb_running = False # Signal the thread to stop
if self.usb_thread and self.usb_thread.is_alive():
self.usb_thread.join(timeout=1)

if hasattr(self.usb_connection, 'ser') and self.usb_connection.ser.is_open:
self.usb_connection.send_command('STOP')
self.usb_connection.ser.close()
print("USB connection closed")
if hasattr(self, 'usb_thread') and self.usb_thread.is_alive():
self.usb_thread.join(timeout=1) # Wait for thread to finish
except Exception as e:
print(f"Error closing USB connection: {str(e)}")
finally:
self.usb_connection = None

if self.ble_connection:
try:
self.ble_connection.disconnect()
self.ble_connection.stop()
print("BLE connection closed")
except Exception as e:
print(f"Error closing BLE connection: {str(e)}")
Expand All @@ -247,7 +266,7 @@ def cleanup(self):

if self.wifi_connection:
try:
self.wifi_connection.disconnect()
self.wifi_connection.cleanup()
print("WiFi connection closed")
except Exception as e:
print(f"Error closing WiFi connection: {str(e)}")
Expand All @@ -270,7 +289,10 @@ def main():

try:
if args.protocol == 'usb':
manager.connect_usb()
if manager.connect_usb():
# Keep the main thread alive while USB is running
while manager.usb_running:
time.sleep(1)
elif args.protocol == 'wifi':
manager.connect_wifi()
elif args.protocol == 'ble':
Expand All @@ -279,6 +301,8 @@ def main():
print("\nCleanup Completed.")
except Exception as e:
print(f"Error: {str(e)}")
finally:
manager.cleanup()

if __name__ == '__main__':
main()
Loading