Last updated:
0 purchases
neurosdk2
neurosdk2 #
Documentation #
Overview #
Neurosdk is a powerful tool for working with neuro-sensors BrainBit, BrainBitBlack, Callibri and Kolibri. SDK allows you to connect, read the parameters of devices, as well as receive signals of various types from the selected device.
Supported platforms:
Android
Errors #
Here is a list of exceptions that occur when working with SDK. You need to be guided by this list in order to understand what happened in the process of executing a particular method.
Code
Description
100
Invalid scan parameters are specified
101
Invalid sensor types are specified for the search
102
Failed to create sensor scanner
103
Failed to started sensor scanner
104
Failed to stopped sensor scanner
105
Failed to get a list of sensors
106
Failed to get a list of sensors
107
Invalid parameters for creating a sensor
108
Failed to create sensor
109
Sensor not founded
110
Failed to connect the sensor
111
Failed to disconnect the sensor
112
Failed to get a list of sensor features
113
Invalid parameters for get a list features of the sensor
114
Invalid parameters for get a list commands of the sensor
115
Failed to get a list of sensor commands
116
Invalid parameters for get a list parameters of the sensor
117
Failed to get a list of sensor parameters
118
Failed to execute the sensor command
119
Failed read the sensor parameter
120
Failed read the sensor parameter
121
Failed write the sensor parameter
122
Failed write the sensor parameter
123
Failed add callback the sensor
124
Failed add callback the sensor
Usage #
Scanner #
The scanner allows you to find devices nearby, it is also responsible for the first creation of the device. Whatever type of device you work with, the use of the scanner will be the same.
The scanner works like this:
Create scanner.
When creating a scanner, you need to specify the type of device to search. It can be either one device or several. Here is example for two type of devices - BrainBit and Callibri.
Scanner sc = await Scanner.create([SensorFamily.leBrainBit, SensorFamily.leCallibri]);
copied to clipboard
During the search, you can get a list of found devices using a callback. To do this, you need to subscribe to receive the event, and unsubscribe after the search is completed:
StreamSubscription<List<SensorInfo>>? scannerSubscription = scanner.sensorsStream.isten((foundedSensors) {
for (SensorInfo info in foundedSensors) {
print("${info.name}");
}
});
// remove subscription after use
scannerSubscription.cancel();
copied to clipboard
Start search
await scanner.start();
copied to clipboard
Stop search
await scanner.stop();
copied to clipboard
Additionally, a list of found devices can be obtained using a separate method.
List<SensorInfo?> sensors = await scanner.getSensors();
copied to clipboard
Sensor info
SensorInfo contains information about device:
Field
Type
Description
name
String
the name of device
address
String
MAC address of device (UUID for iOS/MacOS)
serialNumber
String
device's serial number
sensFamily
SensorFamily
type of device
sensModel
int
numerical value of the device model
pairingRequared
bool
whether the device needs to be paired or not
rssi
int
current signal strength in dBm. The valid range is [-127, 126]
Important!
The serial number of the Callibri and Kolibri does not appear in the SensorInfo recieving during the search. To get this value, you need to connect to the device and request the serial number manually:
String serialNumber = await sensor.serialNumber.value;
copied to clipboard
After you finish working with the scanner, you need to clean up the resources used.
scanner.dispose();
copied to clipboard
Important!
When restarting the search, the callback will only be called when a new device is found. If you need to get all devices found by the current scanner instance, call the appropriate method.
Sensor #
Creating
You need to create a device using a scanner and info about device receiving while search. All manipulations with the device will be performed without errors only if the device is connected. When created, the device is automatically connected. In the future, the connection state can be controlled through the sensor object. The sensor allows you to monitor the status of the device, set parameters, receive a signal of various types.
// retrieve information from a list or retrieve stored information from a callback
List<SensorInfo?> sensors = await scanner.getSensors();
SensorInfo? sensorInfo = sensors[0];
// BrainBit
BrainBit? sensor = await scanner.createSensor(info!) as BrainBit;
// Callibri
Callibri? sensor = await scanner.createSensor(info!) as Callibri;
copied to clipboard
Device creation is a blocking method, so it must be called from separate thread.
For all types of devices, you can use the same methods to control the device's connection status, invoke commands, and check for functionality.
Manage connection state
Connection status can be obtained in two ways. The first one is using the sensor property State.
The second way is in real time using a callback:
StreamSubscription<SensorState>? stateSubscription = sensor.sensorStateStream.listen((state) => print("State: $state"));
...
stateSubscription.cancel();
copied to clipboard
Important!
The state change callback will not come after the device is created, only after disconnecting (device lost from the scope or using a method) and then connected. The device does not automatically reconnect.
You can connect and disconnect from device manually by methods Connect() and Disconnect(). To receive connection state in real time you need to subscribe to stateChanged event. Also you can get connection state by sensor's property.
await sensor.disconnect();
...
await sensor.connect();
copied to clipboard
Method Connect is blocking too, so it need to be call from separate thread.
Device finalization
When you are done with the device, it is recommended to disconnect from the device and clear the taken resources.
await sensor.disconnect();
sensor.dispose();
copied to clipboard
Manage device parameters
Battery
Also, you can get power value from each device by sensor property BattPower or by callback in real time:
StreamSubscription<int>? powerSubscription = sensor.batteryPowerStream.listen((power) => print("Battery: $power"));
...
powerSubscription.cancel();
copied to clipboard
Parameters
Each device has its own settings, and some of them can be configured as you need. Not all settings can be changed and not every device supports all settings.
First you need to find out what parameters the device supports and whether they can be changed:
List<ParameterInfo?> pInfos = await sensor.parameters.value;
copied to clipboard
Info about parameter includes two fields:
ParameterInfo
Field
Type
Description
param
SensorParameter
the name of the parameter, represented by an enumeration
paramAccess
SensorParamAccess
parameter availability for manipulation
SensorParamAccess
Field
Value
Description
read
0
read-only
readWrite
1
parameter can be changed
readNotify
2
parameter is updated over time
You can also check if the parameter is supported, for example Gain:
if(await sensor.isSupportedParameter(SensorParameter.gain)){
...
}
copied to clipboard
Parameter description
Name
Name of device.
String name = await sensor.name.value;
...
await sensor.name.set("newName").onError((error, stackTrace) => print(error)); // <- catch an exception
copied to clipboard
State
Information about the connection status of a device. Can take two values:
InRange - Device connected
OutOfRange - The device is turned off or out of range
SensorState state = await sensor.state.value;
if (state == SensorState.inRange) {
print("connected");
} else {
print("disconnected");
}
copied to clipboard
Address
MAC-address of device. For iOS/MacOS represents by UUID. String value.
String address = await sensor.address.value;
copied to clipboard
SerialNumber
Serial number of device. String value.
For callibri device families, this field is empty in SensorInfo when searching, and you can get it immediately after connecting using this property.
String serialNumber = await sensor.serialNumber.value;
copied to clipboard
Firmware mode
Information about the current mode of operation of the device firmware. It can be in two states:
ModeBootloader - the device is in bootloader mode
ModeApplication - normal operation
SensorFirmwareMode mode = await sensor.firmwareMode.value;
// only for Callibri/ Kolibri
await sensor.firmwareMode.set(SensorFirmwareMode.modeApplication);
copied to clipboard
Sampling frequency
An property that is used to set or get the sample rate of a physiological signal. The higher the value, the more data flow from the device to the application, which means the higher the power consumption, but also the higher the range of measured frequencies. And there are also limitations on the physical communication channel (BLE) in terms of bandwidth.
Recommendations for choosing a value:
For EEG signals not less than 250 Hz;
For ECG signals 125 Hz;
For EMG not less than 1000 Hz. When working with several devices at the same time, it is not recommended to increase the frequency above 1000 Hz;
The breath channel has a fixed sampling rate of 20 Hertz. MEMS channels have a fixed sampling rate of 100 Hertz.
It is unchanged for BrainBit and BrainBitBlack and is 250 Hz. Can be changed for Signal Callibri/Kolibri and can take on the following values:
125 Hz
250 Hz
500 Hz
1000 Hz
2000 Hz
If you try to set an unsupported value to the device, an exception will be thrown.
SensorSamplingFrequency samplingFrequency = await sensor.samplingFrequency.value;
// set only for Callibri/Kolibri MF
await callibri.samplingFrequency.set(SensorSamplingFrequency.hz1000);
copied to clipboard
Gain
Gain of an ADC signal. The higher the gain of the input signal, the less noise in the signal, but also the lower the maximum amplitude of the input signal. For signal Callibi/Kolibri you can set the desired value. Not available for Callibi/Kolibri EMS.
The device uses a 24-bit ADC, but the last 3 bits are not used (discarded) to optimize the data flow over the radio channel. The weight of one bit is calculated using the following formula Wbit = (2*2.4) / ( (pow(2,21) - 1) * Gain ) volt
Available values for Callibri MF and BrainBit:
1
2
3
4
6
8
12
SensorGain gain = await sensor.gain.value;
...
await sensor.gain.set(SensorGain.gain6);
copied to clipboard
If you try to set an unsupported value to the device, an exception will be thrown.
Offset
Signal offset. It is unchanged for BrainBit and BrainBitBlack and is 0. For Callibi/Kolibri MF you can set the desired value. Not available for Callibi/Kolibri EMS.
Available values for Callibri MF:
0
1
2
3
4
5
6
7
8
SensorDataOffset offset = await sensor.dataOffset.value;
// set only for Callibri/Kolibri MF
await sensor.dataOffset.set(SensorDataOffset.dataOffset3);
copied to clipboard
If you try to set an unsupported value to the device, an exception will be thrown.
Firmware version
Information about the device firmware version.
SensorVersion version = await sensor.version.value;
copied to clipboard
SensorVersion:
Field
Type
Description
fwMajor
int
firmware major
fwMinor
int
firmware minor
fwPatch
int
firmware patch
hwMajor
int
hardware major
hwMinor
int
hardware minor
hwPatch
int
hardware patch
extMajor
int
extension major
Battery power
Battery power value. Integer value.
int battery = await sensor.battPower.value;
copied to clipboard
Sensor family
Type of device. Enumeration.
SensorFamily sensFamily = await sensor.sensFamily.value;
copied to clipboard
Features
Each device has a specific set of modules. You can find out which modules the device has using the property Feature:
Set<SensorFeature> features = await sensor.features.value;
copied to clipboard
You can also check if the feature is supported, for example Signal:
if (await callibri.isSupportedFeature(SensorFeature.signal)) {
...
}
copied to clipboard
Commands
The device can execute certain commands. The list of supported commands can be obtained as follows:
Set<SensorCommand> commands = await sensor.commands.value;
copied to clipboard
And also check if the device can execute the desired command:
if(await sensor.isSupportedCommand(SensorCommand.startSignal)){
...
}
copied to clipboard
BrainBit, BrainBitBlack #
The BrainBit and BrainBitBlack is a headband with 4 electrodes and 4 data channels - O1, O2, T3, T4. The device has a frequency of 250 Hz, which means that data on each of the channels will come at a frequency of 250 samples per second. You can only change the gain of the signal. The other parameters cannot be changed and you will get an exception if you try.
You can distinguish BrainBit device from Flex by the firmware version number: if the SensorVersion.FwMajor is more than 100 - it's Flex, if it's less than BrainBit.
BrainBitBlack, unlike BrainBit, requires pairing with a PC/mobile device. So, before connecting to the BrainBitBlack, you must put it into pairing mode. SDK starts the pairing process automatically.
Receiving signal
To receive signal data, you need to subscribe to the corresponding callback. The values will be received as a packet from four channels at once, which will avoid desynchronization between them. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the execute command. This method is also recommended to be run in an separate thread.
StreamSubscription<List<BrainBitSignalData>>? signalSubscription = sensor.signalDataStream.listen((data) => print("Signal values: $data"));
await sensor.execute(SensorCommand.startSignal);
...
signalSubscription.cancel();
await sensor.execute(SensorCommand.stopSignal);
copied to clipboard
You get signal values as a list of samples, each containing:
Field
Type
Description
packNum
int
number for each packet
marker
int
marker of sample, if it was sent and this feature is supported by the device
o1
double
value of O1 channel in V
o2
double
value of O2 channel in V
t3
double
value of T3 channel in V
t4
double
value of T4 channel in V
PackNum cannot be more then 2047
Ping signal
Some devices support signal quality check functions using signal ping. You can send a specific value (marker) to the device and it will return that marker with the next signal data packet. Marker is small value one byte in size.
Available to BrainBitBlack and BrainBit2 / Flex / Pro
await sensor.pingNeuroSmart(5);
copied to clipboard
Recieving resistance
BrainBit and BrainBitBlack also allow you to get resistance values. With their help, you can determine the quality of the electrodes to the skin. Initial resistance values are infinity. The values change when the BB is on the head.
For BrainBit the upper limit of resistance is 2.5 ohms.
StreamSubscription<BrainBitResistData>? resistSubscription = sensor.resistDataStream.listen((data) => print("resist values: $data"));
await sensor.execute(SensorCommand.startResist);
...
resistSubscription.cancel();
await sensor.execute(SensorCommand.stopResist);
copied to clipboard
You get resistance values structure of samples for each channel:
Field
Type
Description
o1
double
value of O1 channel in Ohm
o2
double
value of O2 channel in Ohm
t3
double
value of T3 channel in Ohm
t4
double
value of T4 channel in Ohm
BrainBit 2/Flex/Pro #
The BrainBit2 class is designed to work with several device families: BrainBit 2, BrainBit Pro, BrainBit Flex, BrainBit Flex Pro. All devices have a sampling frequency of 250Hz. All devices can work in two modes - signal and resistance separately. These devices have different number of channels - BrainBit2, BrainBit Flex have 4 channels each and BrainBitPro, BrainBit FlexPro have 8 channels each. The main difference from BraibBit of the first version is that they do not support gain property, but have the ability to set gain for each channel separately using BrainBit2AmplifierParam structure. Also, these types of devices support the ping command.
Info about channels
The device can have 4 or 8 channels. The number of channels can be determined as follows:
List<EEGChannelInfo?> channels = await sensor.supportedChannels.value;
copied to clipboard
EEGChannelInfo contains some info:
Field
Type
Description
id
EEGChannelId
physical location of the channel. You will receive the values o1, o2, t3, t4 or unknown. unknown means that the position of a specific electrode is free.
chType
EEGChannelType
type of channel, possible values singleA1, singleA2, differential or ref
name
String
channel name
num
int
channel number. By this number the channel will be located in the array of signal or resistance values
Also you can check only channels count without info:
int channelsCount = await sensor.channelsCount.value;
copied to clipboard
AmpMode
This device can show it's current amplifier mode. It can be in the following states:
Invalid
PowerDown
Idle
Signal
Resist
You can check amp. mode by two ways:
by callback:
StreamSubscription<SensorAmpMode>? ampModeSubscription = sensor.ampModeStream.listen((mode) => print("Amp mode: $mode"));
...
ampModeSubscription.cancel();
copied to clipboard
get value at any time:
SensorAmpMode mode = await sensor.ampMode.value;
copied to clipboard
It is very important parameter for BrainBit2 device because you can set amplifier parameters only if device into PowerDown or Idle mode.
Amplifier parameters
You can configure each channel and whole device settings by setting amplifier parameters.
int chCount = await sensor.channelsCount.value;
BrainBit2AmplifierParam param = BrainBit2AmplifierParam(
chSignalMode: List.filled(chCount, BrainBit2ChannelMode.chModeNormal),
chResistUse: List.filled(chCount, true),
chGain: List.filled(chCount, SensorGain.gain3),
current: GenCurrent.genCurr6nA);
await sensor.amplifierParam.set(param);
copied to clipboard
BrainBit2AmplifierParam contains:
Field
Type
Description
chSignalMode
List
input type
chResistUse
List
dont used for current version
chGain
List
gain of an ADC signal for each channel
current
GenCurrent
setting parameters of the probe current generator
Possible values for Current:
0nA
6nA
12nA
18nA
24nA
Signal modes:
Short - shorted input
Normal - bipolar input mode (used for EEG)
Possible Gain values:
1
2
3
4
6
8
12
Receiving signal
To receive signal data, you need to subscribe to the corresponding callback. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the execute command. This method is also recommended to be run in an separate thread.
StreamSubscription<List<SignalChannelsData>>? signalSubscription = sensor.signalDataStream.listen((data) => print("Signal values: $data"));
await sensor.execute(SensorCommand.startSignal);
...
signalSubscription.cancel();
await sensor.execute(SensorCommand.stopSignal);
copied to clipboard
You get signal values as a list of samples (SignalChannelsData), each containing:
|--|--|--|
|packNum|int|number for each packet|
|marker|int|marker of sample|
|samples|List
Receiving resistance
BrainBit2 also allow you to get resistance values. With their help, you can determine the quality of the electrodes to the skin. Initial resistance values are infinity. The values change when the device is on the head.
StreamSubscription<List<ResistRefChannelsData>>? resistSubscription = sensor.resistDataStream.listen((data) => print("resist values: $data"));
await sensor.execute(SensorCommand.startResist);
...
resistSubscription.cancel();
await sensor.execute(SensorCommand.stopResist);
copied to clipboard
You get resistance values structure of samples (ResistRefChannelsData) for each channel:
Field
Type
Description
packNum
int
number for each packet
samples
List
array of samples in V. Each sample number into array consistent with Num value of EEGChannelInfo from supportedChannels field.
referents
List
array of values for referents channels. For BrainBit2 sensor is empty now.
Callibri MF/ Kolibri MF #
The Callibri family of devices has a wide range of built-in modules. For each of these modules, the SDK contains its own processing area. It is recommended before using any of the modules to check if the module is supported by the device using one of the methods IsSupportedFeature, IsSupportedCommand or IsSupportedParameter
Parameters
Motion counter parameter pack
Parameters for motion counter.
// check supported
if (await sensor.isSupportedParameter(SensorParameter.motionCounterParamPack)) {
// get
CallibriMotionCounterParam param = await sensor.motionCounterParam.value;
// set
await sensor.motionCounterParam.set(CallibriMotionCounterParam(insenseThresholdMG: 100, insenseThresholdSample: 200));
}
copied to clipboard
CallibriMotionCounterParam:
Field
Type
Description
insenseThresholdMG
int
Insense threshold mg. 0..500
insenseThresholdSample
int
Algorithm insense threshold in time (in samples with the MEMS sampling rate) 0..500
Motion counter
Contains the number of motions. This parameter is available only to Callibi/Kolibri. A numeric value that cannot be changed.
// check supported
if (await sensor.isSupportedParameter(SensorParameter.motionCounter)) {
// get
int = await sensor.motionCounter.value;
}
copied to clipboard
Hardware filters
Device signal filter activity states. If the parameter is supported by the device, it becomes possible to set the desired filters using the HardwareFilters property. The next filters are available:
HPFBwhLvl1CutoffFreq1Hz - high-pass filter with a frequency of 1Hz
HPFBwhLvl1CutoffFreq5Hz - high-pass filter with a frequency of 5Hz
BSFBwhLvl2CutoffFreq45_55Hz - 50Hz notch filter
BSFBwhLvl2CutoffFreq55_65Hz - 60Hz notch filter
HPFBwhLvl2CutoffFreq10Hz - high-pass filter with a frequency of 10 Hz
LPFBwhLvl2CutoffFreq400Hz - low-pass filter with a frequency of 400 Hz. Only for 1000 Hz sampling
HPFBwhLvl2CutoffFreq80Hz - high-pass filter with a frequency of 80Hz
Before enabling filters, check whether the device supports the required filters.
NOTE:
Setting a hardware filter list that contains LPFBwhLvl2CutoffFreq400Hz will not occur in a Callibri MF sensor at a frequency other than 1000Hz
// supported filters
Set<SensorFilter> filters = await sensor.supportedFilters.value;
// read enabled filters
Set<SensorFilter> filtersOn = await sensor.hardwareFilters.value;
// enable filters
if(await sensor.isSupportedFilter(SensorFilter.BSFBwhLvl2CutoffFreq45_55Hz)){
await sensor.hardwareFilters.set({SensorFilter.BSFBwhLvl2CutoffFreq45_55Hz});
}
copied to clipboard
External switch state
Switched signal source. This parameter is available only to Callibi/Kolibri. It is can take on the following values:
ExtSwInElectrodesRespUSB - Respiratory channel data source is USB connector. The source of myographic channel data are terminals.
ExtSwInElectrodes - Terminals are the source of myographic channel data. The breathing channel is not used.
ExtSwInUSB - The source of myographic channel data is the USB connector. The breathing channel is not used.
ExtSwInRespUSB - Respiratory channel data source is USB connector. Myographic channel is not used.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.externalSwitchState)) {
// get
SensorExternalSwitchInput sensorExternalSwitchInput = await sensor.extSwInput.value;
// set
await sensor.extSwInput.set(SensorExternalSwitchInput.electrodesRespUSB);
}
copied to clipboard
ADC input state
State value of an ADC (Analog to Digital Converter) input of a device. This property is available only to Callibi/Kolibri. It is can take on the following values:
Electrodes - Inputs to electrodes. This mode is designed to receive a physiological signal from the place of application.
Short - Inputs are short-circuited. This mode is designed to close the outputs. The output will have noise at the baseline or 0 volt level.
Test - Inputs to the ADC test. This mode is intended for checking the correctness of the ADC operation. The output should be a square wave signal with a frequency of 1 Hz and an amplitude of +/- 1 mV.
Resistance - Inputs for measuring the interelectrode resistance. This mode is designed to measure the interelectrode resistance, as well as to obtain a physiological signal. This is the recommended default mode.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.adcInputState)) {
// get
SensorADCInput sensorAdcInput = await sensor.adcInput.value;
// set
await sensor.adcInput.set(SensorADCInput.electrodes);
}
copied to clipboard
Accelerometer sensitivity
The sensitivity value of the accelerometer, if the device supports it. This property is available only to Callibi/Kolibri. It is recommended to check the presence of the MEMS module before use. It is can take on the following values:
2g - Normal sensitivity. Minimum value. Sufficient for practical use
4g - Increased sensitivity.
8g - High sensitivity.
16g - Maximum sensitivity.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.accelerometerSens)) {
// get
SensorAccelerometerSensitivity sensorAccelerometerSensitivity = await sensor.accSens.value;
// set
await sensor.accSens.set(SensorAccelerometerSensitivity.accSens2g);
}
copied to clipboard
Gyroscope sensitivity
The gyroscope gain value, if the device supports it. It is recommended to check the presence of the MEMS module before use. It is can take on the following values:
250Grad - The range of measured values of the angular velocity is from 0 to 2000 degrees per second. Recommended for measuring angles.
500Grad - The range of measured values of the angular velocity is from 0 to 1000 degrees per second.
1000Grad - The range of measured values of the angular velocity is from 0 to 500 degrees per second.
2000Grad - The range of measured values of the angular velocity is from 0 to 250 degrees per second.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.gyroscopeSens)) {
// get
SensorGyroscopeSensitivity gyroSens = await sensor.gyroSens.value;
// set
await sensor.gyroSens.set(SensorGyroscopeSensitivity.gyroSens250Grad);
}
copied to clipboard
MEMS calibration status
Calibration status of MEMS sensors. Available only to Callibri/Kolibri MF. Conditional type.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.memsCalibrationStatus)) {
// get
if(await sensor.memsCalibrateState.value){
...
}
}
copied to clipboard
SamplingFrequency MEMS
Frequency of updating MEMS values. Immutable value. Available for Callibri/Kolibri supporting MEMS.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.samplingFrequencyMEMS)) {
// get
SensorSamplingFrequency memsFrequency = await sensor.samplingFrequencyMEMS.value;
}
copied to clipboard
SamplingFrequency respiration
Frequency of updating breath values. Immutable value. Available for Callibri/Kolibri supporting breath.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.samplingFrequencyResp)) {
// get
SensorSamplingFrequency respFrequency = await sensor.samplingFrequencyResp.value;
}
copied to clipboard
SamplingFrequency envelope
Frequency of updating envelope values. Immutable value. Available for Callibri/Kolibri supporting envelope.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.samplingFrequencyEnvelope)) {
// get
SensorSamplingFrequency envFreq = await sensor.samplingFrequencyEnvelope.value;
}
copied to clipboard
Electrode state
Electrode state of Callibri/Kallibri MF devices. You can check electrodes state during signal receiving.
// check supported parameter
if (await sensor.isSupportedParameter(SensorParameter.electrodeState)) {
// get
CallibriElectrodeState electrodeState = await sensor.electrodeState.value;
}
copied to clipboard
Receiving signal
To receive signal data, you need to subscribe to the corresponding callback. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the execute command. This method is also recommended to be run in an separate thread.
The sampling rate can be controlled using the SamplingFrequency property. For example, at a frequency of 1000 Hz, the device will send 1000 samples per second. Supports frequencies 125/250/500/1000/2000 Hz. You can also adjust the signal offset (DataOffset) and signal power (Gain).
StreamSubscription<List<CallibriSignalData>>? signalSubscription = sensor.signalDataStream.listen((data) => print("Signal values: $data"));
await sensor.execute(SensorCommand.startSignal);
...
signalSubscription.cancel();
await sensor.execute(SensorCommand.stopSignal);
copied to clipboard
You get signal values as a list of samples, each containing:
Field
Type
Description
packNum
int
number for each packet
samples
List
array of samples in V
Signal settings
By default, the Callibri/Kolibri gives a signal without filters. In order to receive a certain type of signal, for example, EEG or ECG, you need to configure the device in a certain way. For this there is a property SignalTypeCallibri. Preset signal types include:
EEG - parameters: Gain6, Offset = 3, ADCInputResistance
EMG - parameters: Gain6, Offset = 3, ADCInputResistance
ECG - parameters: Gain6, Offset = 3, ADCInputResistance
EDA (GSR) - parameters: Gain6, Offset = 8, ADCInputResistance, ExternalSwitchInElectrodes. By default the input to the terminals is set. If you want to change it to USB use the ExtSwInput property.
TenzoBreathing - parameters: Gain8, Offset = 4, ADCInputResistance, ExternalSwitchInUSB
StrainGaugeBreathing - parameters: Gain6, Offset = 4, ADCInputResistance, ExternalSwitchInUSB
ImpedanceBreathing - parameters: Gain6, Offset = 4, ADCInputResistance, ExternalSwitchInRespUSB
Hardware filters disabled by default for all signal types. You can enable filters by HardwareFilters property, for example LP filter.
Important!
When using an LP filter in the sensor, you will not see the constant component of the signal.
SignalTypeCallibri:
Field
Value
EEG
0
EMG
1
ECG
2
EDA
3
strainGaugeBreathing
4
impedanceBreathing
5
tenzoBreathing
6
unknown
7
// get
CallibriSignalType signalType = await sensor.signalType.value;
// set
await sensor.signalType.set(CallibriSignalType.EMG);
copied to clipboard
Receiving envelope
To get the values of the envelope, you need to subscribe to a specific event and start pickup. The channel must be configured in the same way as for a normal signal, and all parameters work the same way. Then the signal is filtered and decimated at 20 Hz.
StreamSubscription<List<CallibriEnvelopeData>>? envelopeSubscription = sensor.envelopeDataStream.listen((data) { print(data); });
await sensor.execute(SensorCommand.startEnvelope);
...
envelopeSubscription.cancel();
await sensor.execute(SensorCommand.stopEnvelope);
copied to clipboard
You get signal values as a list of samples, each containing:
PackNum - number for each packet
sample in V
Field
Type
Description
packNum
int
number for each packet
sample
double
sample in V
Check electrodes state
Allows you to determine the presence of electrical contact of the device electrodes with human skin. It can be in three states:
Normal - The electrodes have normal skin contact. Low electrical resistance between electrodes. The expected state when working with physiological signals.
Detached - High electrical resistance between electrodes. High probability of interference in the physiological signal.
HighResistance - There is no electrical contact between the electrodes of the device.
To receive data, you need to subscribe to the corresponding callback and start signal pickup.
StreamSubscription<CallibriElectrodeState>? electrodeSubscription = callibri.electrodeStateStream.listen((state) { print(state); });
await sensor.execute(SensorCommand.startSignal);
...
electrodeSubscription.cancel();
await sensor.execute(SensorCommand.stopSignal);
copied to clipboard
Receiving Respiration
The breathing microcircuit is optional on request. Its presence can be checked using the IsSupportedFeature method. To receive data, you need to connect to the device, subscribe to the notification of data receipt and start picking up.
StreamSubscription<List<CallibriRespirationData>>? respSubscription = sensor.respirationDataStream.listen((event) { print(event); });
await sensor.execute(SensorCommand.startRespiration);
...
respSubscription.cancel()
await sensor.execute(SensorCommand.stopRespiration);
copied to clipboard
You get signal values as a list of samples, each containing:
Field
Type
Description
packNum
int
number for each packet
samples
List
sample in V
MEMS
The MEMS microcircuit is optional on request. Its presence can be checked using the IsSupportedFeature method. This means that the device contains an accelerometer and a gyroscope. Contains information about the position of the device in space. Channel sampling frequency is 100 Hz.
MEMS data is a structure:
PackNum - number for each packet
Accelerometer - accelerometer data. Contains:
X - Abscissa Acceleration
Y - Y-axis acceleration
Z - Acceleration along the applicate axis
Gyroscope - gyroscope data
X - The angle of inclination along the abscissa axis
Y - Inclination angle along the ordinate axis
Z - Angle of inclination along the axis of the applicate
Quaternion data is a structure:
PackNum - number for each packet
W - Rotation component
X - Vector abscissa coordinate
Y - Vector coordinate along the ordinate axis
Z - The coordinate of the vector along the axis of the applicate
It is recommended to perform calibration on a flat, horizontal non-vibrating surface before starting work using the CalibrateMEMS command. Calibration state can be checked using the MEMSCalibrateStateCallibri property, it can take only two values: calibrated (true), not calibrated (false).
MEMS and quaternion available only to Callibri/Kolibri MF!
await sensor.execute(SensorCommand.calibrateMEMS);
bool isCalibrated = await sensor.memsCalibrateState.value;
// For receiving MEMS
StreamSubscription<List<MEMSData>>? memsSubscription = sensor.memsDataStream.listen((data) { print(data); });
await sensor.execute(SensorCommand.startMEMS);
...
memsSubscription.cancel()
await sensor.execute(SensorCommand.stopMEMS);
// For quarternion
StreamSubscription<List<QuaternionData>>? qSubscription = sensor.quaternionDataStream.listen((event) { print(event); });
await sensor.execute(SensorCommand.startAngle);
...
qSubscription.cancel()
await sensor.execute(SensorCommand.stopAngle);
copied to clipboard
Motion counter
Represents a motion counter. It can be configured using the CallibriMotionCounterParam property, in it:
InsensThreshmG – Threshold of the algorithm's deadness in amplitude (in mg). The maximum value is 500mg. The minimum value is 0.
InsensThreshSamp - Threshold of the algorithm's insensitivity in time (in samples with the MEMS sampling rate). The maximum value is 500 samples. The minimum value is 0.
You can find out the current number of movements using the MotionCounterCallibri property. You can reset the counter with the ResetMotionCounter command. No additional commands are needed to start the counter, it will be incremented all the time until the reset command is executed.
if (await sensor.isSupportedParameter(SensorParameter.motionCounter)) {
int motionCount = await sensor.motionCounter.value;
await sensor.execute(SensorCommand.resetMotionCounter);
}
copied to clipboard
Callibri/Kolibri EMS #
Kallibri is a EMS if it supports the stimulation module:
bool isStimulator = await sensor.isSupportedFeature(SensorFeature.currentStimulator);
copied to clipboard
Stimulation
Before starting the session, you need to correctly configure the device, otherwise the current strength may be too strong or the duration of stimulation too long. The setting is done using the StimulatorParamCallibri property. You can set the following options:
Current - stimulus amplitude in mA. 1..100
PulseWidth - duration of the stimulating pulse by us. 20..460
Frequency - frequency of stimulation impulses by Hz. 1..200.
StimulusDuration - maximum stimulation time by ms. 0...65535. Zero is infinitely.
You can start and stop stimulation with the following commands:
await sensor.execute(SensorCommand.startCurrentStimulation);
...
await sensor.execute(SensorCommand.stopCurrentStimulation);
copied to clipboard
Stimulation does not stop after the StimulusDuration time has elapsed.
You can check the state of stimulation using the StimulatorMAStateCallibri property. Contains two parameters:
StimulatorState - Stimulation mode state
MAState - Drive assistant mode state
Each of the parameters can be in 4 states:
NoParams - parameter not set
Disabled - mode disabled
Enabled - mode enabled
Unsupported - sensor unsupported
Motion assistant
The Callibri EMS, which contains the MEMS module, can act as a motion corrector. You can set the initial and final angle of the device and the limb on which the Callibri/Kolibri is installed, as well as a pause between stimulations and turn on the motion assistant. All the time while the device is tilted in the set range, stimulation will met. Stimulation will take place according to the settings of StimulatorParamCallibri.
The motion corrector works in the background. After turning on the motion assistant mode, it will work regardless of the connection to a mobile device/PC. You can turn on the motion corrector mode using a special command. When the device is rebooted, it is also reset.
Motion corrector parameters are a structure with fields:
GyroStart - Angle value in degrees at which the stimulation mode will start, if it is correctly configured.
GyroStop - Angle value in degrees above which the stimulation mode will stop, if it is correctly configured.
Limb - overlay location in stimulation mode, if supported.
MinPauseMs - Pause between starts of stimulation mode in milliseconds. Multiple of 10. This means that the device is using the (MinPauseMs / 10) value. Correct values: 10, 20, 30, 40 ...
await sensor.motionAssistantParam.set(CallibriMotionAssistantParams(gyroStart: 45, gyroStop: 10, limb: CallibriMotionAssistantLimb.rightLeg, minPauseMs: 10));
await sensor.execute(SensorCommand.enableMotionAssistant);
...
await sensor.execute(SensorCommand.disableMotionAssistant);
copied to clipboard
Parameters
Stimulator and motional assistant state
Parameter for obtaining information about the state of the stimulation mode and the motion assistant mode. This parameter is available only to Callibi/Kolibri EMS. Contains:
StimulatorState - Stimulation mode state
MAState - Drive assistant mode state
Each of the fields can be in four states:
Field
Type
Description
noParams
0
not set
disabled
1
disabled
enabled
2
enabled
unsupported
3
unsupported
// check supported future
if (await sensor.isSupportedFeature(SensorFeature.currentStimulator)) {
}
// get
CallibriStimulatorMAState stimMAState = await sensor.stimulatorMAState.value;
copied to clipboard
Stimulator parameter pack
Stimulation parameters. This property is available only to Callibi/Kolibri EMS. Parameters inncludes fields:
CallibriStimulationParams:
Field
Type
Description
current
int
stimulus amplitude in mA. 1..100
pulseWidth
int
duration of the stimulating pulse by us. 20..460
frequency
int
frequency of stimulation impulses by Hz. 1..200
stimulusDuration
int
maximum stimulation time by ms. 0...65535
// get
CallibriStimulationParams params = await sensor.stimulatorParam.value;
...
// set
await sensor.stimulatorParam.set(CallibriStimulationParams(current: 5, pulseWidth: 5, frequency: 5, stimulusDuration: 5));
copied to clipboard
Motion assistant parameter pack
Parameter for describing a stimulation mode, if the device supports this mode. This structure describes the parameters for starting the stimulation mode depending on the place of application of the device, the position of the limb in space and the pause between the starts of this mode while the specified conditions are met. The parameter is available only to Callibi/Kolibri EMS. Parameters include fields:
CallibriMotionAssistantParams:
Field
Type
Description
gyroStart
int
Angle value in degrees at which the stimulation mode will start, if it is correctly configured
gyroStop
int
Angle value in degrees above which the stimulation mode will stop, if it is correctly configured
limb
CallibriMotionAssistantLimb
overlay location in stimulation mode, if supported
minPauseMs
int
Pause between starts of stimulation mode in milliseconds. Multiple of 10. This means that the device is using the (MinPauseMs / 10) value. Correct values: 10, 20, 30, 40
CallibriMotionAssistantLimb:
Field
Value
Description
rightLeg
0
right leg
leftLeg
1
left leg
rightArm
2
right arm
leftArm
3
left arm
unsupported
4
unsupported
// get
CallibriMotionAssistantParams params = await sensor.motionAssistantParam.value;
// set
await sensor.motionAssistantParam.set(CallibriMotionAssistantParams(gyroStart: 45, gyroStop: 10, limb: CallibriMotionAssistantLimb.rightLeg, minPauseMs: 10));
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.