Skip to content

Uploading Custom Firmware

The NeuroPawn Arduino library keeps EEG acquisition, packet generation, and host commands running while your sketch performs its own non-blocking work. The smallest complete firmware is:

Minimal Knight Board firmware
#include <NeuroPawn.h>
void setup() {
neuropawn.setup();
}
void loop() {
neuropawn.acquire_data();
}
  • Disconnect all electrodes and accessories while uploading firmware.
  • Never connect mains-powered or non-isolated equipment while electrodes are in contact with a person.
  • Use only an ATmega328P Arduino Nano target and keep the serial monitor at 115200 baud.
  • Read the firmware resource and pin limits before adding peripherals.

In Arduino IDE, install NeuroPawn Knight Board from Library Manager. If you downloaded a release archive instead, choose Sketch > Include Library > Add .ZIP Library and select NeuroPawn-<version>-arduino.zip.

Start with the minimal firmware above. To add application behavior, keep neuropawn.acquire_data() at the start of every loop and schedule work with millis():

Non-blocking custom firmware
#include <NeuroPawn.h>
unsigned long last_update = 0;
void setup() {
neuropawn.setup(NP_DEFAULT);
if (NeuroPawnBoard::pin_available(5)) {
pinMode(5, OUTPUT);
}
}
void loop() {
neuropawn.acquire_data();
if (millis() - last_update >= 250) {
last_update = millis();
digitalWrite(5, !digitalRead(5));
}
}
  1. Connect the board directly by USB.
  2. Select Tools > Board > Arduino AVR Boards > Arduino Nano.
  3. Select the ATmega328P processor and the board’s serial port.
  4. Select Sketch > Upload.

After upload, the firmware begins streaming automatically. All EEG channels are powered down after setup(); activate the required channels from the host with the chon_<channel>_<gain> commands.

Create a PlatformIO Arduino project with this platformio.ini:

platformio.ini
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
monitor_speed = 115200
lib_deps =
neuropawn/NeuroPawn@^1.0.0

Put the minimal firmware in src/main.cpp, then run PlatformIO: Upload or:

Terminal window
pio run --target upload

IMU support is a build-time option. It adds about 13 kB of flash use and 640 bytes of RAM use, even before NP_IMU is selected at runtime.

Add NEUROPAWN_IMU to the build flags and start the library in NP_IMU mode:

platformio.ini
[env:nanoatmega328_imu]
platform = atmelavr
board = nanoatmega328
framework = arduino
monitor_speed = 115200
build_flags = -DNEUROPAWN_IMU
lib_deps =
neuropawn/NeuroPawn@^1.0.0
src/main.cpp
#include <NeuroPawn.h>
void setup() {
neuropawn.setup(NP_IMU);
}
void loop() {
neuropawn.acquire_data();
}

Arduino IDE does not expose project build flags. In the installed library folder, usually Documents/Arduino/libraries/NeuroPawn_Knight_Board/:

  1. Open src/NeuroPawn.h and uncomment #define NEUROPAWN_IMU near the top.
  2. In library.properties, change the linker setting to ldflags=-lNeuroPawn_imu.
  3. Restart Arduino IDE, then compile a sketch that calls neuropawn.setup(NP_IMU).

To return to an EEG-only build, comment out the define and restore ldflags=-lNeuroPawn.

  1. Call acquire_data() on every loop iteration. At 125 samples per second, blocking for roughly 8 ms can miss a sample.
  2. Do not call delay() or perform long blocking reads. Use millis()-based scheduling and short state machines.
  3. Never call Serial.print() or write unrelated bytes to Serial; it is the binary data link.
  4. Use only pins reported as available by NeuroPawnBoard::pin_available(pin).
  5. Keep interrupt service routines short.

Use neuropawn.quiet(true) before setup() when a host parser must receive only binary data. See Knight Board Firmware for the API, modes, status helpers, and complete hardware limits.