Skip to content

Latest commit

 

History

History
428 lines (336 loc) · 13.1 KB

File metadata and controls

428 lines (336 loc) · 13.1 KB

EEG Device Integration

🎯 Supported Devices

Manufacturer Device Channels Sample Rate Brainflow ID Protocol
OpenBCI Cyton 8 250 Hz 0 Serial/WiFi
OpenBCI Cyton + Daisy 16 125 Hz 2 Serial/WiFi
OpenBCI Ganglion 4 200 Hz 1 BLE
NeuroSky MindWave 1 512 Hz 18 Bluetooth
Muse Muse 2 4 256 Hz 22 BLE
Muse Muse S 4 256 Hz 21 BLE
Emotiv Insight 5 128 Hz 25 BLE
Emotiv EPOC X 14 128/256 Hz 26 BLE
PiEEG PiEEG 8 250-16000 Hz 46 SPI (Raspberry Pi)
PiEEG PiEEG-16 16 250-8000 Hz 47 SPI (Raspberry Pi)
PiEEG IronBCI 8 250 Hz N/A* BLE/WiFi
PiEEG IronBCI-32 32 250 Hz N/A* WiFi
PiEEG JNEEG 8 250-2000 Hz N/A* SPI (Jetson Nano)
PiEEG ardEEG 8 250 Hz N/A* Serial (Arduino)
PiEEG MicroBCI 8 250 Hz N/A* BLE (STM32)
Cerelog ESP-EEG 8 250 Hz N/A* WiFi (TCP)
LSL Generic (8-64ch) 8-64 Variable -2** Lab Streaming Layer
LSL Brain Products 32+ Up to 25kHz N/A* LSL
LSL BioSemi ActiveTwo 32+ Up to 16kHz N/A* LSL
LSL g.tec 16+ Up to 38kHz N/A* LSL
LSL Cognionics 20-30 500 Hz N/A* LSL
LSL ANT Neuro 32+ 2048 Hz 29 LSL
LSL NIRx fNIRS 16+ 10 Hz N/A* LSL
Brainflow Synthetic 8 250 Hz -1 Virtual

*Requires WebSocket bridge (included). **LSL streams can use Brainflow Streaming Board ID -2 for forwarding.

⚠️ Browser Connectivity

Browsers cannot open raw TCP, Serial, or Bluetooth connections directly.

For hardware devices, you need a WebSocket bridge that runs locally and proxies the device data to the browser. This project includes:

  1. lsl_ws_bridge.py - For any LSL source (130+ devices → WebSocket)
  2. pieeg_ws_bridge.py - For PiEEG devices (SPI/BrainFlow → WebSocket)
  3. cerelog_ws_bridge.py - For Cerelog ESP-EEG (TCP → WebSocket)

Bridge Architecture

EEG Device (TCP/Serial/BLE)
    ↓
WebSocket Bridge (Python/Node.js)
    ↓ (ws://localhost:876x)
PhantomLoop (Browser)

What's New

🌐 Universal Device Profiles (src/devices/)

  • Comprehensive device registry with specs for 10+ EEG devices
  • Brainflow board IDs for all supported devices
  • Auto-configuration based on device selection
  • Default montages with standard 10-20 electrode positions

🔌 Universal EEG Adapter (src/streams/UniversalEEGAdapter.ts)

  • Single adapter that works with all device profiles
  • Automatic protocol detection and parsing
  • Signal quality estimation from amplitude characteristics
  • Reconnection handling with exponential backoff

🎯 Electrode Placement Screen

  • Interactive electrode configuration UI with support for 1-16+ channel setups
  • Standard 10-20/10-10 montage with predefined positions
  • Device-specific defaults (Muse positions, Emotiv layout, etc.)
  • Real-time signal quality monitoring with color-coded indicators

📤 Enhanced Brainflow Export

  • Auto-detect board ID from device type
  • Device-aware Python code generation
  • Complete channel mapping with positions
  • Ready-to-run scripts for any Brainflow-compatible device

Quick Start

1. Select Your Device

import { createAdapterForDevice } from './streams';

// Create adapter for your device
const adapter = createAdapterForDevice('openbci-cyton');
// or: 'muse-2', 'emotiv-insight', 'neurosky-mindwave', etc.

// Connect to WebSocket bridge
await adapter.connect('ws://localhost:8766');

2. Bridge Setup by Device

OpenBCI Cyton/Ganglion

# Install brainflow
pip install brainflow

# Use brainflow-websocket-bridge (community)
# https://github.com/brainflow-dev/brainflow-websocket-bridge
python bridge.py --board-id 0 --serial-port COM3

Muse 2/S

# Install muselsl
pip install muselsl

# Stream via LSL, then use LSL-to-WebSocket bridge
muselsl stream

# In another terminal, run the LSL bridge
python scripts/lsl_ws_bridge.py --stream "Muse"

Lab Streaming Layer (130+ Devices)

# The LSL bridge supports any LSL-compatible device:
# Brain Products, BioSemi, g.tec, ANT Neuro, Cognionics, NIRx, etc.

# Install dependencies
pip install websockets pylsl numpy

# Auto-discover and connect to first EEG stream
python scripts/lsl_ws_bridge.py

# Connect to specific stream by name
python scripts/lsl_ws_bridge.py --stream "OpenBCI_EEG"

# List available LSL streams on your network
python scripts/lsl_ws_bridge.py --list

# Run with simulated data (for testing)
python scripts/lsl_ws_bridge.py --simulate

# Connect in PhantomLoop to ws://localhost:8767

WebSocket Commands:

{"command": "discover"}
{"command": "connect", "name": "OpenBCI_EEG", "stream_type": "EEG"}
{"command": "disconnect"}
{"command": "ping"}

Emotiv Insight/EPOC

# Use Emotiv's Cortex API with WebSocket bridge
# https://emotiv.gitbook.io/cortex-api/

PiEEG (Raspberry Pi)

# 1. Connect PiEEG shield to Raspberry Pi GPIO
# 2. Enable SPI: sudo raspi-config → Interface Options → SPI

# Install dependencies
pip install websockets spidev RPi.GPIO numpy

# Run the bridge
cd scripts
python pieeg_ws_bridge.py --rate 250 --gain 24

# Options:
#   --rate      Sample rate: 250, 500, 1000, 2000, 4000, 8000, 16000
#   --gain      PGA gain: 1, 2, 4, 6, 8, 12, 24
#   --channels  8 or 16 (for PiEEG-16)
#   --port      WebSocket port (default: 8766)
#   --brainflow Use BrainFlow instead of direct SPI

# Connect in PhantomLoop to ws://<raspberry-pi-ip>:8766

Development Mode (no hardware):

# On non-Raspberry Pi systems, the bridge auto-enables simulation mode
# Generates synthetic alpha waves for testing
python pieeg_ws_bridge.py

Cerelog ESP-EEG

# Connect to ESP-EEG WiFi (SSID: CERELOG_EEG, Password: cerelog123)

# Run the included bridge
cd scripts
pip install websockets
python cerelog_ws_bridge.py

# Connect in PhantomLoop to ws://localhost:8765

3. Access Electrode Placement

  1. WelcomeScreen → Click "Configure Electrodes"
  2. Select your device from the dropdown
  3. Configure electrodes and monitor signal quality
  4. Proceed to Dashboard when ready

Architecture

New Files

src/
├── devices/
│   ├── index.ts                   # Device exports
│   └── deviceProfiles.ts          # Universal device registry
├── streams/
│   └── UniversalEEGAdapter.ts     # Universal EEG stream adapter
├── types/
│   └── electrodes.ts              # Updated for multi-device support
└── utils/
    └── brainflowExport.ts         # Enhanced with device profiles

Device Profile Structure

interface DeviceProfile {
  id: string;                    // 'openbci-cyton', 'muse-2', etc.
  name: string;                  // Human-readable name
  manufacturer: string;          // 'OpenBCI', 'Muse', etc.
  channelCount: number;          // Number of EEG channels
  samplingRates: number[];       // Supported sample rates
  resolution: number;            // ADC resolution in bits
  brainflowBoardId?: number;     // Brainflow board ID
  protocols: string[];           // Supported protocols
  capabilities: {
    hasImpedanceMeasurement: boolean;
    hasAccelerometer: boolean;
    supportsBrainflow: boolean;
    // ...
  };
  defaultMontage?: {
    labels: string[];            // ['Fp1', 'Fp2', ...]
    positions: Position3D[];     // 3D positions
  };
}

Brainflow Board IDs Reference

import { BRAINFLOW_BOARD_IDS } from './devices';

// OpenBCI
BRAINFLOW_BOARD_IDS.CYTON           // 0
BRAINFLOW_BOARD_IDS.GANGLION        // 1
BRAINFLOW_BOARD_IDS.CYTON_DAISY     // 2

// NeuroSky
BRAINFLOW_BOARD_IDS.MINDWAVE        // 18

// Muse
BRAINFLOW_BOARD_IDS.MUSE_2          // 22
BRAINFLOW_BOARD_IDS.MUSE_S          // 21

// Emotiv
BRAINFLOW_BOARD_IDS.INSIGHT         // 25
BRAINFLOW_BOARD_IDS.EPOC            // 26

// PiEEG
BRAINFLOW_BOARD_IDS.PIEEG           // 46
BRAINFLOW_BOARD_IDS.PIEEG_16        // 47

// Testing
BRAINFLOW_BOARD_IDS.SYNTHETIC       // -1

Usage Examples

List All Supported Devices

import { listDeviceProfiles, getSupportedDevices } from './streams';

// Get all device profiles
const devices = getSupportedDevices();
console.log(devices);
// [{ id: 'openbci-cyton', name: 'OpenBCI Cyton', channelCount: 8, ... }, ...]

Create Device-Specific Adapter

import { createUniversalEEGAdapter } from './streams';

const adapter = createUniversalEEGAdapter({
  deviceId: 'muse-2',
  bridgeUrl: 'ws://localhost:8767',
  channelLabels: ['TP9', 'AF7', 'AF8', 'TP10'], // Optional override
});

adapter.onSample((sample) => {
  console.log('EEG data:', sample.channels);
});

await adapter.connect();

Export to Brainflow Python

import { 
  downloadBrainflowPythonCode,
  getBoardIdFromDeviceType 
} from './utils/brainflowExport';

// Auto-detects board ID from device type
downloadBrainflowPythonCode(electrodeConfig);

// Or specify explicitly
const boardId = getBoardIdFromDeviceType('openbci-cyton'); // Returns 0

Monitor Signal Quality

const adapter = createAdapterForDevice('openbci-cyton');
await adapter.connect();

// Get channel statistics
const stats = adapter.getChannelStats();
stats.forEach((ch, i) => {
  console.log(`Ch${i}: quality=${ch.quality}, std=${ch.std.toFixed(1)}µV`);
});

Device-Specific Notes

OpenBCI

  • Impedance check: Supported on Cyton/Ganglion
  • Accelerometer: Built-in 3-axis accelerometer
  • Markers: Supports event markers via aux channels

Muse

  • Positions: Non-standard (TP9, AF7, AF8, TP10)
  • Aux sensors: PPG, gyroscope, accelerometer
  • No impedance: Quality estimated from signal

Emotiv

  • Subscription: Requires Emotiv account for raw data
  • Impedance: Supported on all models
  • Motion: Gyroscope + accelerometer

PiEEG

  • ADS1299: 24-bit resolution, programmable gain (1-24x)
  • Sample rates: 250 Hz to 16 kHz configurable
  • Impedance: Supported via ADS1299 lead-off detection
  • Signals: EEG, EMG, ECG all supported
  • Raspberry Pi: Compatible with Pi 3, 4, and 5
  • Safety: Battery power only (5V) - never connect to mains!
  • BrainFlow: Supported (board ID 46 for PiEEG, 47 for PiEEG-16)
  • Variants:
    • PiEEG-16: 16-channel daisy-chain
    • IronBCI: Wearable with BLE/WiFi and mobile SDK
    • IronBCI-32: 32-channel high-density
    • JNEEG: Jetson Nano for GPU-accelerated DL
    • ardEEG: Arduino shield for beginners
    • MicroBCI: STM32 NUCLEO-WB55 compact BLE

Cerelog ESP-EEG

  • ADS1299: No impedance measurement (signal-based quality only)
  • WiFi AP: Device creates its own network
  • Binary protocol: Requires WebSocket bridge

Signal Quality Estimation

For devices without impedance measurement (Muse, Cerelog), quality is estimated:

Quality Std Dev (µV) Pseudo-Impedance Description
Good 5-100 <5 kΩ Normal EEG range
Fair 100-200 5-15 kΩ Slightly elevated noise
Poor 200-500 15-50 kΩ High noise/artifacts
Disconnected <5 or >500 >50 kΩ No signal or saturated

Spatial Features (Electrode-Aware Decoding)

When electrode configuration is available, decoders receive spatial features:

// In your decoder
return (input) => {
  const { spikes, spatialFeatures, channelMask } = input;
  
  // ROI averages by brain region
  if (spatialFeatures?.roiAverages) {
    const motorActivity = spatialFeatures.roiAverages.central;
    const visualActivity = spatialFeatures.roiAverages.occipital;
  }
  
  // Only use active channels
  const activeData = channelMask 
    ? spikes.filter((_, i) => channelMask[i])
    : spikes;
  
  return { x: 0, y: 0 };
};

Testing Without Hardware

Use Brainflow's synthetic board:

from brainflow import BoardShim, BrainFlowInputParams

board = BoardShim(-1, BrainFlowInputParams())  # -1 = Synthetic
board.prepare_session()
board.start_stream()

FAQ

Q: Can I add support for a new device?
A: Yes! Add a new entry to DEVICE_PROFILES in src/devices/deviceProfiles.ts.

Q: Do I need a bridge for all devices?
A: Yes, browsers can't access hardware directly. Each device type needs a bridge.

Q: Can I use multiple devices simultaneously?
A: Yes, create multiple adapter instances with different bridge URLs.

Q: What if my device isn't listed?
A: Use 'brainflow-generic' device type and configure manually, or add a new profile.

License

Same as PhantomLoop main project.