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:
1from mindrove.board_shim import BoardShim, MindRoveInputParams, BoardIds
1// You need to import first mindrove.dll into your project by adding it to the Project's References
2using mindrove;
3using 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.
1BoardShim.enable_dev_board_logger() # enable logger when developing to catch relevant logs
2params = MindRoveInputParams()
3params.mac_address = "AABBCC" # replace with your device SSID
4board_id = BoardIds.MINDROVE_SYNCBOX_BOARD
5board_shim = BoardShim(board_id, params)
1BoardShim.enable_dev_board_logger(); // enable logger when developing to catch relevant logs
2MindRoveInputParams input_params = new MindRoveInputParams();
3input_params.mac_address = "AABBCC"; // replace with your device SSID
4int board_id = (int)BoardIds.MINDROVE_SYNCBOX_BOARD;
5BoardShim 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:
1board_shim.prepare_session()
2board_shim.start_stream()
1board_shim.prepare_session();
2board_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):
1eeg_channels = BoardShim.get_eeg_channels(board_id)
2accel_channels = BoardShim.get_accel_channels(board_id)
3sampling_rate = BoardShim.get_sampling_rate(board_id)
1int[] eeg_channels = BoardShim.get_eeg_channels(board_id);
2int[] accel_channels = BoardShim.get_accel_channels(board_id);
3int 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):
1window_size = 2 # seconds
2num_points = window_size * sampling_rate
3if board_shim.get_board_data_count() >= num_points:
4 data = board_shim.get_current_board_data(num_points)
1int window_size = 2 // seconds
2int num_points = window_size * sampling_rate ;
3if(board_shim.get_board_data_count() >= num_points){
4 double[,] data = board_shim.get_current_board_data(num_points);
5}
Second option is to get the data from the board`s buffer and delete it from the buffer itself.
1window_size = 2 # seconds
2num_points = window_size * sampling_rate
3if board_shim.get_board_data_count() >= num_points:
4 data = board_shim.get_board_data(num_points)
1int window_size = 2 // seconds
2int num_points = window_size * sampling_rate ;
3if(board_shim.get_board_data_count() >= num_points){
4 double[,] data = board_shim.get_board_data(num_points);
5}
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:
1eeg_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
2accel_data = data[accel_channels] # output of shape (3, num_of_samples)
1double[][] eeg_data = eeg_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();
2double[][] 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:
1from mindrove.board_shim import BoardShim, MindRoveInputParams, BoardIds
2
3BoardShim.enable_dev_board_logger() # enable logger when developing to catch relevant logs
4params = MindRoveInputParams()
5params.mac_address = "AABBCC" # replace with your device SSID
6board_id = BoardIds.MINDROVE_SYNCBOX_BOARD
7board_shim = BoardShim(board_id, params)
8
9board_shim.prepare_session()
10board_shim.start_stream()
11
12eeg_channels = BoardShim.get_eeg_channels(board_id)
13accel_channels = BoardShim.get_accel_channels(board_id)
14sampling_rate = BoardShim.get_sampling_rate(board_id)
15
16window_size = 2 # seconds
17num_points = window_size * sampling_rate
18
19while True:
20 if board_shim.get_board_data_count() >= num_points:
21 data = board_shim.get_current_board_data(num_points)
22 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
23 accel_data = data[accel_channels] # output of shape (3, num_of_samples)
24 # process data, or print it out
1// You need to import first mindrove.dll into your project by adding it to the Project's References
2using mindrove;
3using System.Linq; // will come in handy later
4
5BoardShim.enable_dev_board_logger(); // enable logger when developing to catch relevant logs
6MindRoveInputParams input_params = new MindRoveInputParams();
7input_params.mac_address = "AABBCC"; // replace with your device SSID
8int board_id = (int)BoardIds.MINDROVE_SYNCBOX_BOARD;
9BoardShim board_shim = new BoardShim(board_id, input_params);
10
11board_shim.prepare_session();
12board_shim.start_stream();
13
14int[] eeg_channels = BoardShim.get_eeg_channels(board_id);
15int[] accel_channels = BoardShim.get_accel_channels(board_id);
16int sampling_rate = BoardShim.get_sampling_rate(board_id);
17
18int window_size = 2 // seconds
19int num_points = window_size * sampling_rate ;
20
21while(true){
22 if(board_shim.get_board_data_count() >= num_points){
23
24 double[,] data = board_shim.get_current_board_data(num_points);
25 double[][] eeg_data = eeg_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();
26 double[][] accel_data = accel_channels.Select(index => Enumerable.Range(0, data.GetLength(1)).Select(colIndex => data[index, colIndex]).ToArray()).ToArray();
27
28 // process data, or print it out
29 }
30}