Hardware
Devices
IronBCI-32
Specification

Specification

Everything you need to know about the hardware, plus the serial data format for writing your own software.

IronBCI-32 board, top view

Hardware

Channels32 biosignal inputs (4 groups of 8)
Extra inputsReference and bias (on the CH 1–8 header)
Analog front end4 × Analog Devices AD7771, 8 channels each
Resolution24-bit
NoiseUltra-low-noise sources and references, measured below 0.22 µV (from the IronBCI-32 repository)
Sample rateAbout 500 SPS, fixed by the firmware (BrainFlow's board description lists 512 Hz)
MicrocontrollerSTM32H743 (Arm Cortex-M7), with real-time pre-processing
SignalsEEG, EMG, ECG, EOG
ElectrodesDry or wet Ag/AgCl
Electrode connectors4 × 2.54 mm double-row headers
Data portMicro USB, USB CDC virtual serial port
Power portMicro USB, 5 V from a USB battery only
ProgrammingSWD header (GND, RST, SWDIO, SWCLK) for an ST-Link
PCB70 × 70 mm, 4 layers, 1.6 mm, FR4
IsolationNone. Battery operation of the board and the laptop is required.
Hardware filesKiCad schematic and Gerber files in the repository (opens in a new tab)

Software support

SoftwareSetting
BrainFlow (opens in a new tab)BoardIds.IRONBCI_32_BOARD (65), serial_port
PiEEG Server--device ironbci32 --serial-port … (needs pieeg-server[ironbci32])
PiEEG CloudPiEEG Devices → IronBCI-32 (Web Serial)
JavaScript SDKconnectSerial({ device: 'ironbci-32' }) (default for Web Serial)

Serial data format

PortUSB CDC ACM (virtual COM port)
Baud rate921,600
StartStreams as soon as the board is powered. No start command.
Frame rateOne frame per sample, about 500 per second

Frame layout

BytesContent
10xA0 start marker
2Sample counter (0–255, wraps)
3–9832 channels × 3 bytes, 24-bit big-endian two's complement
99 … n−1Status and padding bytes (length depends on the firmware)
n0xC0 end marker

Frames observed on current firmware are 107 bytes long. Robust parsers find the frame length from the distance between consecutive 0xC0 0xA0 pairs instead of assuming a fixed size.

Converting to microvolts

This is the conversion used by PiEEG Server and BrainFlow's FreeEEG decoder (2.5 V reference, gain 8):

raw = (b[0] << 16) | (b[1] << 8) | b[2]   # 3 bytes of one channel
if raw & 0x800000:                       # negative value
    raw -= 1 << 24
uV = raw * 2.5 / 8388607 / 8 * 1_000_000 # about 0.03725 µV per count

Raw values carry a large DC offset (tens of thousands of µV) from the electrode contact. That is normal. Apply a high-pass or band-pass filter before looking at EEG.

Minimal reader

import serial
 
PORT = "COM3"                       # or "/dev/ttyACM0"
FRAME = 107                         # check with the 0xC0 0xA0 method if unsure
 
with serial.Serial(PORT, 921600, timeout=1) as s:
    buf = bytearray()
    while True:
        buf += s.read(1024)
        i = buf.find(b"\xA0")
        while i >= 0 and len(buf) - i >= FRAME:
            f = buf[i:i + FRAME]
            if f[-1] == 0xC0:
                ch = []
                for c in range(32):
                    b = f[2 + 3*c: 5 + 3*c]
                    raw = (b[0] << 16) | (b[1] << 8) | b[2]
                    if raw & 0x800000:
                        raw -= 1 << 24
                    ch.append(raw * 2.5 / 8388607 / 8 * 1e6)
                print(f[1], [round(v, 1) for v in ch[:4]], "...")
                buf = buf[i + FRAME:]
            else:
                buf = buf[i + 1:]
            i = buf.find(b"\xA0")

For real projects, use BrainFlow or PiEEG Server, which handle frame detection and errors for you.