BrainBit foe developers Visit website
Home
SDK
Device

Tutorial .NET

Software development kit for Windows operating system is represented as native C++ libraries and .NET assemblies.

 

Platform requirements

OS: Windows 10 1803 or higher is required.

Software: Visual Studio 2015 or higher,  Download link

Hardware: Bluetooth v4.0, External USB Module with Chipset CSR8510 is recommended.

 

SDK Installer

To get latest release installers, use the following links:

neurosdk-setup-win-x86-v1.4.5.exe

neurosdk-setup-win-x64-v1.4.5.exe

These installers will create environment variables NEUROSDK_86 or/and NEUROSDK_64 linking the path to installed libraries. Installed samples use these variables to get libraries and it can be used in your custom project configurations. It’s also recommended to leave PATH-variable checkbox checked, to add SDK library directory to PATH.

 

Running .Net example applications

By default, example applications are installed in user Documents directory in samples\.net subfolder. You can find two solutions with console and WinForms examples. To build and run example applications first open one of the solutions in Visual Studio.




In the menu bar go to Build->Build Solution to build all examples or just press F6.

Select one of the samples from the dropdown list or mark one of the projects in solution explorer as Startup Project.

 

Click Start or press F5 to run application

 

DeviceInfo example will show you available devices and basic information about your device



Signal application allows you to see EEG signal received by your BrainBit device

Indices application will introduce you digital signal processing features of Brainbit SDK

 

Scanning for devices

To find nearby Brainbit devices use DeviceEnumerator

    
var enumerator = new DeviceEnumerator(DeviceType.Brainbit);
enumerator.DeviceListChanged += _enumerator_DeviceListChanged;
//Do work
enumerator.Dispose;
    


DeviceListChanged event will hit when a new device appears or one of the found devices disappears from range. DeviceEnumerator always works and scans for devices during its lifetime. It implements IDisposable interface, so don’t forget to call Dispose on it after all work is done or use using pattern.

    
using (var enumerator = new DeviceEnumerator(DeviceType.Brainbit))
{
    //All work is done here
}
//enumerator is no longer alive
    


To get information about nearby devices, use property Devices. You could read it every time DeviceListChanged event hits. 

    
private void _enumerator_DeviceListChanged(object sender, EventArgs e)
{
   if (sender is DeviceEnumerator enumerator)
   {
       var devices = enumerator.Devices;
   }

}
    


Devices property contains a list of simple device information records containing device name and address. 

    
public struct DeviceInfo
{
  public string Name;
  public ulong Address;
}
    


You could print device information in the following way 

    
var devices = enumerator.Devices;
foreach (var deviceInfo in devices)
{
  Console.WriteLine($"{deviceInfo.Name} [{deviceInfo.Address:x6}]");
}
    


Connecting to the device 

To receive data from the Brainbit device and to send commands to it first you need to connect to it

    
var device =  new Device(deviceInfo);
device.Connect();
//Do work
device.Disconnect();
device.Dispose();
    


You could read the device state to check whether it is connected or not. You also could subscribe ParameterChanged event to receive notifications when the device goes out of range. 

    
device.ParameterChanged += _device_ParameterChanged;
var state = device.ReadParam<DeviceState>(Parameter.State);
if (state == DeviceState.Connected)
{
    device.Connect();
}

private void device_ParameterChanged(object sender, Parameter parameter)
{
    if (parameter == Parameter.State)
    {
       var state = device.ReadParam<DeviceState>(Parameter.State);
    }
}
    

 

When the device is connected you could read lists of supported parameters, signal channels, available commands. You could read the device name and address in string format and firmware version. 

    
var name = device.ReadParam<string>(Parameter.Name);
var address = device.ReadParam<string>(Parameter.Address);
var firmwareVersion = device.ReadParam<FirmwareVersion>(Parameter.FirmwareVersion);
    


To get list of command and channels use appropriate properties. 

    
foreach (var cmd in device.Commands)
{
    Console.WriteLine(cmd.ToString());
}
foreach (var channel in device.Channels)
{
    Console.WriteLine($"{channel.Type}-{channel.Name}";
}
    


Retrieving signal data 

For Brainbit device, actual channels are Signal, Battery and Resistance. To get channel records from the device with a specific type, DeviceTraits class could be used. To subscribe for new data notifications Use AddIntDataListener and AddDoubleDataListener methods of Device class. There are four commands for managing device measuring state: StartSignal, StopSignal, StartResist, StopResist.

    
if (DeviceTraits.HasChannelsWithType(device, ChannelType.Battery))
{
   var batteryChannelInfo = 
       DeviceTraits.GetChannelsWithType(device, ChannelType.Battery)[0];
   device.AddIntChannelDataListener(OnBatteryChargeChanged, batteryChannelInfo);
}

if (DeviceTraits.HasChannelsWithType(device, ChannelType.Signal))
{
   var signalChannels = 
       DeviceTraits.GetChannelsWithType(device, ChannelType.Signal);
   foreach (var channelInfo in signalChannels)
   {
       device.AddSignalChannelDataListener(OnSignalReceived, channelInfo);
   }

}

device.Execute(Command.StartSignal);
    

 

Battery data channel contains data as int values, Resistance and Signal channels as double values. Write callback methods to handle new data. Information about the channel which triggered notification is contained in notification parameter.

    
private void OnBatteryChargeChanged(object device, Device.ChannelData<int> data)
{   
   var batteryCharge = data.DataArray[0];
}

private void OnSignalReceived(object device, Device.SignalChannelData data)
{   
    var channelName =  data.ChannelInfo.Name;
    var signalData = data.DataArray;
}
    


To simplify receiving and storing signal data you could use Channel buffer classes. There is a set of different channel buffers in the SDK. One of them is called EegChannel. This buffer receives data from the device and applies special filters to signal to get perfect EEG signal. Pass offset (samples count from buffer start) and length to readData method to get EEG signal.

    
var eegChannel = new EegChannel(device, channelInfo);
eegChannel.LengthChanged += (sender, length) => 
{
   //Handle changed data length event
}
var length = eegChannel.TotalLength;
var eegData = eegChannel.readData(0, length); //read all data from channel buffer
    


You could also use a channel buffer without filters or select filters you need. There are different variants of Signal channel to do it. You could use following filters for Brainbit signals: LowPass_30Hz_SF250, LowPass_30Hz_SF250_Reverse, HighPass_2Hz_SF250, HighPass_2Hz_SF250_Reverse, BandStop_45_55Hz_SF250. 

    
//Signal channel without filters
var signalChannel = new SignalChannel(device, channelInfo);
//Signal channel with 50 Hz bandstop filter
var filters = new Filter[1] { BandStop_45_55Hz_SF250 };
var signalChannel = new SignalChannel(device, channelInfo, filters);

signalChannel.Dispose();
    


Channel buffers collection 

There is a set of different channel buffers for storing and processing signal data. All channel buffers need to be disposed after work is finished.

    
//Resistance channel. Receives and stores information about the resistance of electrodes
var resistanceChannel = new ResistanceChannel(device, info);

//Bipolar channel. Calculates the difference between two EEG (or simple signal) channels. 
//Could be used to reduce some types of artifacts
var bipolarChannel = new BipolarDoubleChannel(eegChannel1, eegChannel2);

//Spectrum channel. Calculates signal spectrum for a selected signal region.
//readData returns array with spectrum samples of length provided in SpectrumLength property
//offset and length parameters relate to source signal channel which was used to make spectrum channel
var spectrumChannel = new SpectrumChannel(anyDoubleChannel);
var frequencyStep = spectrumChannel.HzPerSpectrumSample;
var spectrumLength = spectrumChannel.SpectrumLength;

//Spectrum power channel. Calculates and stores a power of spectrum on a selected frequency band
//You could use several spectrum channels for spectrum power calculation. Results will be joined into one
var spectrumPowerChannel = new SpectrumPowerChannel(arrayOfChannels, lowFrequency,                                                   
                                                    highFrequency, channelName);
    


Emulation of device
 

If you don’t have Brainbit device yet, you could try all signal processing features using emulation channel. You need to provide spectral components of an emulation signal to create this channel. You could use this channel for all calculations that receive channels of doubles.

    
var components = new EmulationSine[3];
components[0] = new EmulationSine
{
   AmplitudeV = 100e-6, //amplitude = 100uV;
   FrequencyHz = 10, //frequency = 10 Hz
   PhaseShiftRad = 0
};
components[1] = new EmulationSine
{
   AmplitudeV = 50e-6, 
   FrequencyHz = 18, 
   PhaseShiftRad = 0
};
components[2] = new EmulationSine
{
   AmplitudeV = 80e-6, 
   FrequencyHz = 30, 
   PhaseShiftRad = 0
};
var emulationChannel = new EmulationChannel(components, 250, 2000); //8 seconds of                        
                                                                   //signal
emulationChannel.LengthChanged += (sender, length) => 
{ 
   //handle new length event 
};
emulationChannel.StartTimer(); //begins emulation of receiving new signal
emulationChannel.StopTimer();

emulationChannel.Dispose();