Two External Buttons on OpenBCI 32bit Board

Sometimes, when studying EEG or other biopotential signals, you will want to have precise timing between external events or stimulus and the data stream. For example, motor imagery based brain-computer interface (BCI) translates the subject’s motor intention into a control signal through real-time detection of characteristic EEG spatial distributions corresponding to motor imagination of different body parts. In this case, it is necessary to know the exact time that an external input has been presented to the subject to look for the tell-tale brain wave that happens about 400ms after the stimulus. Moreover, if you want to distinguish between right and left movements while you are studying motor imagery or motor execution, you better pay attention to the following steps.

This tutorial will cover a way that we implemented to add two external buttons to the OpenBCI data stream on our 32bit Board. Please read this entire page before jaunting off into hardware hacking.

External Buttons (Code)

The code used in this example is located here for those of you who want to play along at home. There’s a tutorial for how to program the 32bit Board here.

The OpenBCI 32bit Board comes with a user accessible pushbutton switch already on the board, wired right to the PIC32 microcontroller. However, since we need two buttons, we will have to use external breadboards. You will likely want to note the rising edge (pushed state) of the buttons press, so that’s the example code that we’ll work with.

int left = 17;  // left button
 int right = 18; // right button
 int leftButtonValue; // used to hold the latest left button reading
 int rightButtonValue; // used to hold the latest right button reading
 int lastLeftButtonValue; // used to remember the last left button state
 int lastRightButtonValue; // used to remember the last right button state

First thing is to establish the variables we need to read the pushbutton switches. The OpenBCI library already has a variable array for auxiliary data, called *auxData*, which we will use for logging.

In the setup function, we set the both right and left pins direction and prime the buttons variables. The startFromScratch() function resets the board peripheral devices and does some general housekeeping, along with making initial serial contact with any controlling program. The useAccel and useAux variables are inside the OpenBCI_32_Daisy library (hence the OpenBCI.) and it’s important to decide and select which kind of data you want to log. It is possible to do both, but you will need to manually operate the useAux or useAcel variables.

void setup(void) {
 Serial0.begin(115200);  // using hardware uart number 0
 pinMode(LED, OUTPUT); digitalWrite(LED,HIGH);   // blue LED
 pinMode(PGCpin,OUTPUT); digitalWrite(PGCpin,LOW);
 // used to tell RFduino if we are in bootloader mode NOT IMPLEMENTED
 delay(1000);   // take a break

pinMode(leftButton, INPUT);   // set the left button pin direction
pinMode(rightButton, INPUT);   // set the left button pin direction
leftButtonValue = lastLeftButtonValue = digitalRead(left);  // seed
rightButtonValue = lastRightButtonValue = digitalRead(right);  // seed

startFromScratch(); // initialize OpenBCI, read device IDs
 // you can set EITHER useAccel or useAux to true
 // if you want both, you MUST set and clear one of the variables every sample
 OBCI.useAccel = true;  // option to add/remove accelerometer data to stream
 OBCI.useAux = false;  // option to add/remove auxiliary data to stream

Then, in the loop, we want to check for the rising edge of the buttons press, make note of it in the auxData array, and set the write-to-SD flag (if you like). Finally, we want to get the buttons press event into the data stream. (Reference the OpenBCI Data Format Doc for data packet anatomy). There are 6 bytes available in each data packet, and the default format is to read them as three 16bit integers (aka ‘words’ or ‘shorts’). You can decide to add your flags into the auxData array any way you choose. In this example, we are setting each short to the value 0x6620. That’s because our OpenBCI GUI converts these variables to Gs (the GUI is expecting accelerometer data) and 0x6620 converts to PI (3.14). Our sample rate of 250SPS gives us a 4mS resolution on external trigger events like the rising edge of the PROG button press.

leftButtonValue = digitalRead(left);    // feel the left button
 if (leftButtonValue != lastLeftButtonValue){  // if it's changed,
 if (leftButtonValue == HIGH){    // if it's gone from LOW to HIGH
 // 0x6220 converts to PI in GUI
 OBCI.auxData[0] = 0x6220;
 addAuxToSD = true;  // add Aux Data to the SD card if it's there }
 lastLeftButtonValue = leftButtonValue; // keep track of the changes }

rightButtonValue = digitalRead(right);   // feel the right button
 if (rightButtonValue != lastRightButtonValue){  // if it's changed,
 if (rightButtonValue == HIGH){    // if it's gone from LOW to HIGH
 // 0x6220 converts to PI in GUI
 OBCI.auxData[1] = 0x6220;
 addAuxToSD = true;  // add Aux Data to the SD card if it's there }
 lastRightButtonValue = rightButtonValue; // keep track of the changes }

In our sample code linked above, we save the left button data in the first auxData column, while the right button data is saved into the second auxData column.

Also, you can do the button feeling at any point in the loop() function. You could put it outside of the if (is-running) conditional so that you can see the LED toggle even when the board is not streaming data. That’s a nice way to know that you’ve got everything set up and working before starting a data logging session.

External Buttons (Boards Connection)

Sometimes a situation may arise where you need to interface OpenBCI with an existing system, for example, an audio or visual event-related potential (ERP). In such a case, it is most desirable to have the onset of the signal tightly bound, temporally, with the EEG data. It is possible to interface the OpenBCI 32bit Board with the external signal generating system using a few low-cost components.

Our goal with the OpenBCI board is to make biosensing safe and fun. The biggest part of the safety part is making sure that you can’t plug yourself accidentally into the mains electrical supply. If you are interfacing an external trigger that is NOT operating under a battery supply, we recommend thinking twice about incorporating it into your system/protocol. If you have thought through it twice, here’s how we do it when we need to.


For this assembly, we will need:

– OpenBCI 32bit Board
– 4 position female headers (2 pieces)
– 2 breadboards
– 2 momentary pushbutton switch

Before you get up and running, you will need to solder some header pins to your 32bit Board. Let’s do it! You will need 4 position female headers (2 pieces) to connect the OpenBCI 32bit Board with the electronic boards, such as it is also done for the assembly of the OpenBCI Daisy module explained here.

Figure 1. OpenBCI 32bit board with the header soldered.

Electronic Circuit

Once the headers are soldered, the next step is to build the electronic components in the breadboards. The image shown below gives a detailed connection of all the components. In this case, we use two different breadboards only to make more comfortable for the user the use of finger pressing.

Figure 2. Electric circuit of the buttons (in this case, left button)

Furthermore, the connection between the OpenBC 32bit board and the breadboards is simple:

– Left button to pin D17
– Right button to pin D18
– Ground to GND
– Voltage to VDD

Figure 3. Schematics of the buttons


Now would be the right moment to try the experiment. Start registering brain waves and push the buttons randomly. If you have followed the steps correctly, you will find the pi number “3.14” in the first auxData column the exact time when you have pressed the left button, and in the second one when you have pressed the right button.

Figure 4. Final connection between the EEG headset and the two external buttons.

Here’s an example of what the data looks like after it’s been logged by our GUI.

217, -18.08, -23.04, -21.59, -29.86, -23.76, -19.65, -28.79, -19.47, 0.00, 0.00, 0.00
 218, -18.17, -22.82, -21.59, -29.93, -23.85, -19.65, -28.72, -19.16, 0.00, 0.00, 0.00
 219, -17.97, -23.04, -21.39, -29.97, -23.92, -19.56, -28.74, -19.24, 3.14, 0.00, 0.00
 220, -17.99, -23.07, -21.61, -30.00, -23.72, -19.71, -28.52, -19.16, 0.00, 0.00, 0.00
 221, -17.90, -23.04, -21.48, -30.09, -23.85, -19.54, -28.43, -19.18, 0.00, 3.14, 0.00
 222, -17.90, -22.96, -21.48, -30.20, -23.72, -19.38, -28.57, -18.95, 3.14, 0.00, 0.00
 223, -17.93, -22.89, -21.26, -29.97, -23.96, -19.65, -28.54, -18.95, 0.00, 0.00, 0.00

Have fun, be safe, and, as always, we’re here to help.


One Comment Add yours

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s