SyncBox

SyncBox Functionality

The SyncBox allows you to synchronize up to 4 MindRove devices, including EEG and EMG, via a USB connection. This enables access to raw data through the MindRove SDK.

Capabilities:

  • Automatically synchronizes up to 4 MindRove devices with each other.

  • Supports any combination of MindRove devices, whether EEG, EMG, or both.

  • The SyncBox can transmit and receive +3.3V trigger signals to and from third-party devices.

  • Connects to the computer via USB for power and data communication.

  • Compatible with Windows, Linux and MacOS.

For hardware related information, please read the user manual

Connecting to a device through SyncBox

In order to initialize the Mindrove WiFi Board, first the appropiate libraries have to be imported:

1
from mindrove.board_shim import BoardShim, MindRoveInputParams, BoardIds
1
2
3
// You need to import first mindrove.dll into your project by adding it to the Project's References
using mindrove;
using System.Linq; // will come in handy later

Next, we want to create a MindroveInputParam parameter and initialize the main board with the target device SSID (can be read from the device itself): For the sake of demonstration, we will use SSID of AABBCC.

1
2
3
4
5
BoardShim.enable_dev_board_logger() # enable logger when developing to catch relevant logs
params = MindRoveInputParams()
params.mac_address = "AABBCC" # replace with your device SSID
board_id = BoardIds.MINDROVE_SYNCBOX_BOARD
board_shim = BoardShim(board_id, params)
1
2
3
4
5
BoardShim.enable_dev_board_logger(); // enable logger when developing to catch relevant logs
MindRoveInputParams input_params = new MindRoveInputParams();
input_params.mac_address = "AABBCC"; // replace with your device SSID
int board_id = (int)BoardIds.MINDROVE_SYNCBOX_BOARD;
BoardShim board_shim = new BoardShim(board_id, input_params);

The rest is the same as dealing with a single device.

After creating the board, we need to prepare for the connection, after which we can start the stream:

1
2
board_shim.prepare_session()
board_shim.start_stream()
1
2
board_shim.prepare_session();
board_shim.start_stream();

It’s a good idea to get the indices of the parameters that we want to use in our project. Let’s say we want to use the EEG and Accelerometer data. To later process the EEG signal the sampling frequency will be important as well. In order to know which rows of the returned data contains the information relevant for us, we need to invoke specific functions to get the indices (for further options check the API):

1
2
3
eeg_channels = BoardShim.get_eeg_channels(board_id)
accel_channels = BoardShim.get_accel_channels(board_id)
sampling_rate = BoardShim.get_sampling_rate(board_id)
1
2
3
int[] eeg_channels = BoardShim.get_eeg_channels(board_id);
int[] accel_channels = BoardShim.get_accel_channels(board_id);
int sampling_rate = BoardShim.get_sampling_rate(board_id);

To get the data from the board itself we have two functions to choose from: # Note that for both functions we have to pass an integer, determining the maximum number of samples to be returned (it can be less).

  • Firstly, we can get data from the board buffer without deleting the data from the source buffer ( this can be useful if we want to accumulate a certain number of datapoints before going on with the processing of the data. This way we don’t have to handle the data preservation, but read out in a later stage the whole data again):

1
2
3
4
window_size = 2 # seconds
num_points = window_size * sampling_rate
if board_shim.get_board_data_count() >= num_points:
  data = board_shim.get_current_board_data(num_points)
1
2
3
4
5
int window_size = 2 // seconds
int num_points = window_size * sampling_rate ;
if(board_shim.get_board_data_count() >= num_points){
   double[,] data = board_shim.get_current_board_data(num_points);
}
  • Second option is to get the data from the board`s buffer and delete it from the buffer itself.

1
2
3
4
window_size = 2 # seconds
num_points = window_size * sampling_rate
if board_shim.get_board_data_count() >= num_points:
  data = board_shim.get_board_data(num_points)
1
2
3
4
5
int window_size = 2 // seconds
int num_points = window_size * sampling_rate ;
if(board_shim.get_board_data_count() >= num_points){
  double[,] data = board_shim.get_board_data(num_points);
}

The data obtained contains every information that the board transmits (like EEG, Accelerometer, Gyroscope, etc.). The data variable is a 2D array, with the shape of (num_of_parameters, number_of_samples). Previously we obtained the specific indices that we are intrested in, in the following step we will use these indices to get what we really need from the data array:

1
2
eeg_data = data[eeg_channels] # output of shape (8, num_of_samples) ## Beware that depending on the electrode configuration, some channels can be *inactive*, resulting in all-zero data for that particular channel
accel_data = data[accel_channels] # output of shape (3, num_of_samples)
1
2
double[][] eeg_data = eeg_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();
double[][] accel_data = accel_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();

Full code, where an infinite loop was introduced to query data continuously:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from mindrove.board_shim import BoardShim, MindRoveInputParams, BoardIds

BoardShim.enable_dev_board_logger() # enable logger when developing to catch relevant logs
params = MindRoveInputParams()
params.mac_address = "AABBCC" # replace with your device SSID
board_id = BoardIds.MINDROVE_SYNCBOX_BOARD
board_shim = BoardShim(board_id, params)

board_shim.prepare_session()
board_shim.start_stream()

eeg_channels = BoardShim.get_eeg_channels(board_id)
accel_channels = BoardShim.get_accel_channels(board_id)
sampling_rate = BoardShim.get_sampling_rate(board_id)

window_size = 2 # seconds
num_points = window_size * sampling_rate

while True:
  if board_shim.get_board_data_count() >= num_points:
    data = board_shim.get_current_board_data(num_points)
    eeg_data = data[eeg_channels] # output of shape (8, num_of_samples) ## Beware that depending on the electrode configuration, some channels can be *inactive*, resulting in all-zero data for that particular channel
    accel_data = data[accel_channels] # output of shape (3, num_of_samples)
    # process data, or print it out
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// You need to import first mindrove.dll into your project by adding it to the Project's References
using mindrove;
using System.Linq; // will come in handy later

BoardShim.enable_dev_board_logger(); // enable logger when developing to catch relevant logs
MindRoveInputParams input_params = new MindRoveInputParams();
input_params.mac_address = "AABBCC"; // replace with your device SSID
int board_id = (int)BoardIds.MINDROVE_SYNCBOX_BOARD;
BoardShim board_shim = new BoardShim(board_id, input_params);

board_shim.prepare_session();
board_shim.start_stream();

int[] eeg_channels = BoardShim.get_eeg_channels(board_id);
int[] accel_channels = BoardShim.get_accel_channels(board_id);
int sampling_rate = BoardShim.get_sampling_rate(board_id);

int window_size = 2 // seconds
int num_points = window_size * sampling_rate ;

while(true){
  if(board_shim.get_board_data_count() >= num_points){

    double[,] data = board_shim.get_current_board_data(num_points);
    double[][] eeg_data = eeg_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();
    double[][] accel_data = accel_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();

    // process data, or print it out
  }
}