Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Учебное пособие 2232

.pdf
Скачиваний:
26
Добавлен:
30.04.2022
Размер:
14.85 Mб
Скачать

всех 4-х каналов последовательнои входа REF в конце каждой серии, пока не получит команду “Z”. Эти значения “Packet ID” перечислены в таблице ниже. Данные импеданса отправляются в виде строки ASCII, представляющей измеренное значение в омах (табл. 4.2).

 

 

 

Таблица 4.2

 

Значения поля Packet ID

Десятичный

Байт ID

Тип

 

 

идентификатор байта

HEX

данных

Описание

 

 

 

 

 

 

0

00

24bit

Данные без сжатия

 

 

 

 

 

 

1-100

0x01-0x64

18bit

18-битное сжатие с акселерометром

 

 

 

 

 

 

 

 

 

19-битное сжатие без

 

101-200

0x65-0xC8

19bit

акселерометра

 

 

 

 

 

 

201

0xC9

impedance

Канал импеданса 1

 

 

 

 

 

 

202

0xCA

impedance

Канал импеданса 2

 

 

 

 

 

 

203

0xCB

impedance

Канал Импеданса 3

 

 

 

 

 

 

204

0xCC

impedance

Канал импеданса 4

 

 

 

 

 

 

205

0xCD

impedance

Ссылка на канал импеданса

 

 

 

 

 

 

206

0xCE

multi

Часть сообщения ASCII

 

 

 

 

 

 

207

0xCF

multiStop

Конец сообщения ASCII

 

 

 

 

 

 

4.6.7. Вывод протокола

Плата Ganglion иногда отправляет подробные данные через соединение BLE. В этом случае Ganglion может отправлять от 1 до многих пакетов подробных данных в формате ASCII. “Packet ID” для ASCII сообщений проинформирует компьютер, если сообщение не будет сделано и он должен ожидать другой пакет “206” или “0xCE”. Когда Ganglion отправляет последний пакет сообщений ASCII, то “Packet ID” будет иметь значение “207” или “0xCF”.

100

4.6.8. Примеры интерпретации данных с платы Ganglion

При передаче 24-х битных необработанных данных без сжатия они всегда сохраняются, если приходит “Byte ID” равный “0”.

4.6.8.1. 18-битное дельта-сжатие

Далее рассмотрим практический пример передачи 18-битных данных на основе автоматизированного теста, используемого в драйвере Ganglion NodeJS, для объяснения стратегии 18-ти разрядного дельта-сжатия.

let buffer = new Buffer(

[

0b00000001, // 0 0b00000000, // 1 0b00000000, // 2 0b00000000, // 3 0b00000000, // 4 0b00100000, // 5 0b00000000, // 6 0b00101000, // 7 0b00000000, // 8 0b00000100, // 9 0b10000000, // 10 0b00000000, // 11 0b10111100, // 12 0b00000000, // 13 0b00000111, // 14 0b00000000, // 15 0b00101000, // 16 0b11000000, // 17 0b00001010, // 18 0b00001110 // 19 ]);

let expectedValue = [[0, 2, 10, 4], [131074, 245760, 114698, 49162]];

Первый сжатый канал в первой выборке будет получен из первых двух байтов плюс первые два бита третьего байта: канал 1 - выборка 1 - “0b000000000000000000” или “0” в десятичном формате.

Второй сжатый канал в первой выборке будет получен из последних шести битов третьего байта, всех четырех байтов и первых четырех битов пятого байта: канал 2 - выборка 1 “0b000000000000000010” или “2” в

десятичном формате.

Третья сжатая выборка во второй выборке будет получена из последних четырех битов 14-го байта, всех битов 15-го байта и первых шести битов 16-го байта: канал 3 - выборка 2 “0b011100000000001010” или “114698” в десятичном виде.

Чтобы получить данные 8-битного акселерометра с частотой 10 Гц из 18битных пакетов, необходимо задать модуль 10-байтового идентификатора “Byte

101

ID”: если (идентификатор байта “% 10”) равен 1, 2 и 3, то необходимо брать последний байт, чтобы получить значения X, Y и Z.

В вышеприведенном примере байт 19 - это последний байт, он имеет значение 14, или “0x0E”, которое будет сохранено как значение оси X для этого образца акселерометра.

Номер образца для образца 1 будет “1” и номер образца для образца 2 будет “2”. Если идентификатор байта был 47, а номер образца был “1”, то получим номер 93, а номер образца 2 - 94.

Далее рассмотрим отрицательные значения.

let buffer = new Buffer(

[

0b00000001, // 0 0b11111111, // 1 0b11111111, // 2 0b01111111, // 3 0b11111111, // 4 0b10111111, // 5 0b11111111, // 6 0b11100111, // 7 0b11111111, // 8 0b11110101, // 9 0b00000000, // 10 0b00000001, // 11 0b01001111, // 12 0b10001110, // 13 0b00110000, // 14 0b00000000, // 15 0b00011111, // 16 0b11110000, // 17 0b00000001 // 18 ]);

let expectedValue = [[-3, -5, -7, -11], [-262139, -198429, -262137, -4095]];

Первый сжатый канал в первой выборке будет получен из первых двух байтов плюс первые два бита третьего байта для образования общего количества 19 бит: канал 1 - выборка 1 – “0b111111111111111101” – или “3” в

десятичном формате.

Второй сжатый канал в выборке два будет получен из последних шести битов 12-го байта, целого байта 13 и первых четырех битов из байта 14: канал 2 - выборка 2 – “0b001111100011100011” или “198429” в десятичном формате. “MSB” будет иметь значение “0”, но это будет отрицательное число, потому что значение “LSB” будет “1”.

4.6.8.2. 19-битное дельта-сжатие

Для объяснения стратегии 19-разрядного дельта-сжатия рассмотрим практический пример на основе автоматизированного теста, используемого в драйвере Ganglion NodeJS.

102

let buffer = new Buffer(

[

0b01100101, // 0 0b00000000, // 1 0b00000000, // 2 0b00000000, // 3 0b00000000, // 4 0b00001000, // 5 0b00000000, // 6 0b00000101, // 7 0b00000000, // 8 0b00000000, // 9 0b01001000, // 10 0b00000000, // 11 0b00001001, // 12 0b11110000, // 13 0b00000001, // 14 0b10110000, // 15 0b00000000, // 16 0b00110000, // 17 0b00000000, // 18 0b00001000 // 19 ]);

let expectedValue = [[0, 2, 10, 4], [262148, 507910, 393222, 8]];

Первый сжатый канал в первой выборке будет получен из первых двух байтов плюс первые три бита третьего байта для получения общего количества 19 битов: канал 1 - выборка 1 – “0b0000000000000000000” или “0” в десятичном формате.

Второй сжатый канал во второй выборке будет получен из последнего бита в байте №12, всех байтов №13 и №14 и только первых двух битов байта №15: канал 2 - выборка 2 – “0b1111100000000000110” или “507910” в десятичном формате. “MSB” будет иметь значение “1”, но это положительное число, потому что “LSB” будет иметь значение “0”.

Номер образца для образца 1 равен “1” и номер образца для образца 2 будет “2”. Если идентификатор байта был “104”, то номер выборки 1 будет “7а”, а номер выборки 2 будет “8”.

Далее рассмотрим отрицательные значения.

let buffer = new Buffer(

[

0b01100101, // 0 0b11111111, // 1 0b11111111, // 2 0b10111111, // 3 0b11111111, // 4 0b11101111, // 5 0b11111111, // 6 0b11111100, // 7 0b11111111, // 8 0b11111111, // 9 0b01011000, // 10 0b00000000, // 11 0b00001011, // 12 0b00111110, // 13

103

0b00111000, // 14 0b11100000, // 15 0b00000000, // 16 0b00111111, // 17 0b11110000, // 18 0b00000001 // 19 ]);

let expectedValue = [[-3, -5, -7, -11], [-262139, -198429, -262137, -4095]];

Обращение к LSB происходит для 19-битного числа. Первый сжатый канал в выборке №1 будет получен из первых двух байтов плюс первые три бита третьего байта: канал 1 - выборка 1 “0b1111111111111111101” или “3” в десятичном формате.

Четвертый сжатый канал в выборке №2 будет получен из последних трех битов байта №17 и всех байтов №18 и №19: канал 4 - выборка 2 “0b001111100011100011” или “198429” в десятичном формате. “MSB” будет иметь значение “0”, но это отрицательное число, так как “LSB” будет иметь значение “1”.

Значения импеданса отправляются с байтовыми идентификаторами в формате ASCII, заканчивающемся на “Z”. Разбор необходимо проводить от байта №1, пока не встретится “Z”.

4.6.8.3. 18-битные данные со знаком

Сжатые значения регистрируемых данных ЭЭГ передаются в виде 18разрядного целого числа со знаком, что немного необычно. Но используется этот числовой формат потому, что это родной формат, используемый A/D- чипом, который является основным на плате Ganglion. Чтобы преобразовать этот необычный числовой формат в более стандартное 32-разрядное целое число со знаком, можно взять некоторые идеи из примера кода NodeJS (он же JavaScript):

/**

*Converts a special ganglion 18 bit compressed number

*The compressions uses the LSB, bit 1, as the signed bit, instead of using

*the MSB. Therefore you must not look to the MSB for a sign extension, one

*must look to the LSB, and the same rules applies, if it's a 1, then it's a

*negative and if it's 0 then it's a positive number.

*@param threeByteBuffer {Buffer}

*A 3-byte buffer with only 18 bits of actual data.

*@return {number} A signed integer.

*/

function convert18bitAsInt32 (threeByteBuffer) { let prefix = 0;

if (threeByteBuffer[2] & 0x01 > 0) { // console.log('\t\tNegative number') prefix = 0b11111111111111;

}

return (prefix << 18) | (threeByteBuffer[0] << 16) | (threeByteBuffer[1] << 8) | threeByteBuffer[2];

}

104

4.6.8.4. 19-битные данные со знаком

Сжатые значения регистрируемых данных ЭЭГ передаются в виде 19разрядного целого числа со знаком, что немного необычно. Но этот числовой формат используется потому, что это родной формат, используемый АЦП, который используется на плате Ganglion. Чтобы преобразовать этот необычный числовой формат в более стандартное 32-разрядное целое число со знаком, можно воспользоваться примером кода NodeJS (он же JavaScript):

/**

*Converts a special ganglion 19 bit compressed number

*The compressions uses the LSB, bit 1, as the signed bit, instead of using

*the MSB. Therefore you must not look to the MSB for a sign extension, one

*must look to the LSB, and the same rules applies, if it's a 1, then it's a

*negative and if it's 0 then it's a positive number.

*@param threeByteBuffer {Buffer}

*A 3-byte buffer with only 19 bits of actual data.

*@return {number} A signed integer.

*/

function convert19bitAsInt32 (threeByteBuffer) { let prefix = 0;

if (threeByteBuffer[2] & 0x01 > 0) { // console.log('\t\tNegative number') prefix = 0b1111111111111;

}

return (prefix << 19) | (threeByteBuffer[0] << 16) | (threeByteBuffer[1] << 8) | threeByteBuffer[2];

}

4.6.8.5. Интерпретация данных ЭЭГ

После того, как регистрируемые данные ЭЭГ получены, проанализированы и пакеты данных распакованы, важно знать, как интерпретировать данные, чтобы значения ЭЭГ были полезны в количественном отношении. Важнейшим элементом полученной информации является коэффициент масштабирования.

Для коэффициента масштабирования это множитель, который используется для преобразования значений ЭЭГ из «счетчиков» (число формата int32, которое вы анализируется из двоичного потока) в единицы измерения, такие как «вольт». Коэффициент масштабирования установлен и встроен в аппаратное обеспечение, поэтому можно использовать коэффициент масштабирования:

Scale Factor (Volts/count) = 1.2 Volts * 8388607.0 * 1.5 * 51.0;

Это уравнение взято из таблицы в файле описания АЦП MCP3912. Этот масштабирующий коэффициент также был подтвержден экспериментально с использованием известных калибровочных сигналов.

105

Данные акселерометра также должны быть масштабированы, прежде чем их можно будет правильно интерпретировать. Уравнение, используемое для масштабирования данных акселерометра, выглядит следующим образом (принимаются данные 4G, то есть 2 мг на одну цифру):

Accelerometer Scale Factor = 0.032;

4.7. SDK для платы Ganglion

Платы OpenBCI обмениваются данными с помощью протокола команд байтовой строки (в основном ASCII). Далее описывается использование команд для платы OpenBCI Ganglion. Кроме того, будут описаны команды, необходимые для изменения системы радиосвязи. Во-первых, необходимо выполнить сброс и узнать версию прошивки платы Ganglion.

4.7.1. Обзор протокола команд Ganglion

Плата Ganglion оснащена мощным микроконтроллером на базе микросборки Simblee. Радиоканал Simblee использует стек Nordic Gazelle и библиотеку вместе со стеком BLE. Микроконтроллер программируется микропрограммой, которая взаимодействует между MCP (аналоговый интерфейс), LIS3DH (акселерометр) и микро SD (если она установлена). Пользователь, или приложение, управляет платой, отправляя команды через беспроводное последовательное соединение.

При запуске плата OpenBCI Ganglion отправляет по радио следующий текст:

OpenBCI Ganglion v2.0.0

ID LIS2DH: 0x33 MCP3912 CONFIG_1: 0xXX можно использовать @, #, $

для включения каналов. Команды:

'b' - начало передачи потока данных;

's' - остановка передачи потока данных;

1, 2, 3, 4 - для выключения каналов;

'?' - распечатать все регистры;

'v' - инициализация платы;

'[' ']' - включение / отключение синтетической прямоугольной волны;

'z' 'Z' - запуск / остановка теста импеданса;

'n', 'N' - включение / отключение акселерометра.

106

4.7.2. Набор команд

Выключение каналов:

1 2 3 4 - эти символы ASCII отключают соответствующие каналы [1-4]. Канал будет считывать в режиме streamData 0,00, когда он выключен. Эти команды работают в режиме StreamData и без этого режима.

Включение каналов:

! @ # $ - эти символы ASCII включают соответствующие каналы [1-4]. Канал будет читать выходные значения АЦП в режиме streamData. Эти команды работают в режиме StreamData и вне его.

Включение синтеза прямоугольного сигнала:

[ - этот символ включает создание генерируемого прямоугольного сигнала.

Выключение синтеза прямоугольного сигнала:

] - выключение генерации ложного прямоугольного сигнала. Измерение входного импеданса:

z - запуск тестирования импеданса и отправка обратно пакетов с данными измеренного импеданса;

Z - остановка тестирования входного импеданса. Включение акселерометра:

n - запуск акселерометра, что влечет за собой переход к 18-разрядному дельта-сжатию данных в канале;

N - остановка акселерометра, что влечет за собой возвращение к 19разрядному дельта-сжатию данных в канале.

Команды для SD-карты:

ASFGHJKL команды для того, чтобы начать запись данных SD-карты в течение указанного времени:

A = 5 мин;

S = 15 мин;

F = 30 мин;

G= 1 час;

H= 2 часа;

J= 4 часа;

K= 12 часов;

L= 24 часа;

а = около 14 секунд для тестирования;

j - остановка записи данных и закрытие файла на SD-карте. Команды потоковой передачи данных:

b - начало потоковой передачи данных; s - остановка потоковой передачи данных. Другие команды:

107

? - запрос настроек регистра. Чтение и сообщение всех настроек регистров для MCP и LIS3DH. Получение после недолгого ожидания подробного последовательного вывода данных о регистрах с платы OpenBCI;

v- программный сброс для периферийных устройств платы.

4.7.3. Новые команды для прошивок v2.xx

Микропрограмма версии 2.0.0 поддерживает все версии 1.0.0 и расширяет систему OpenBCI Ganglion для обеспечения изменяемой частоты

дискретизации.

 

 

 

 

Частота дискретизации:

 

 

 

~

-

команда

изменения

частоты

дискретизации.

Она работает аналогично командам настройки каналов, однако завершающего символа нет. Выключение питания платы OpenBCI Ganglion приведет к тому, что частота дискретизации вернется к значению по умолчанию 200 Гц.

Плата Ganglion по каналу BLE не может и не будет передавать данные со скоростью более 200 SPS (пактов в секунду (частота дискретизации 200 Гц)). Чтобы увеличить скорость передачи более 200 SPS необходимо подключить плату WiFi Shield.

Команды: 0 = 25600 Гц 1 = 12800 Гц 2 = 6400 Гц 3 = 3200 Гц 4 = 1600 Гц 5 = 800 Гц 6 = 400 Гц 7 = 200 Гц

~ = получение текущей частоты дискретизации.

Далее приведем пример использования команд изменения частоты дискретизации. Сначала пользователь отправляет “~” – возвращается “Sample rate is 200Hz”. Затем пользователь отправляет “~ 5” – возвращается “Sample rate set to 800Hz$$$”.

Команды работы с Wifi Shield:

После прикрепления платы Wifi Shield к плате Ganglion будет передан ответ “ Success: Wifi attached$$$” при успешном соединении или “Failure: Wifi not attached$$$” при не удачном соединении. Сбой происходит, когда на Wifi Shield не подается питание или Wifi Shield работает не правильно. Необходимо попробовать выключить и снова включить систему для устранения сбоя.

После снятия прикрепленной платы Wifi Shield будет передан ответ

“Success: Wifi removed$$$” при успешном отключении и “Failure: Wifi not removed$$$” при неудаче. Ошибка происходит, когда Wifi Shield уже отключен.

108

Команда “:” позволяет получить статус Wi-Fi Shield. Ответ будет либо подключен, либо не подключен. При успешно подключенном Wi-Fi Shield будет отправлен ответ “Wifi present$$$”. Если нет платы Wi-Fi Shield, то ответ будет “Wifi not present, send { to attach the shield$$$”.

Команда “;” выполняет мягкий сброс Wi-Fi Shield. Будет сделана мягкая перезагрузка только Wi-Fi Shield.

Неиспользуемые символы ASCII - это неиспользуемые (и доступные пользователю) символы в платформе OpenBCI Ganglion: a AB c C d D e E f F g G h H i I j J K K L L M M O O P P Q Q R RS T T U UV W W X X Y Y `5 6 7 8 9 0% ^ & * () - _ {} []; : '",. / \ | (пробел).

4.8. Программирование платы Ganglion

Далее будет описано, как обновить прошивку платы Ganglion. Загрузка последней версии программы прошивки и программирование через радиоканал (OTA) делает обновление платы Ganglion быстрым с помощью любого мобильного устройства. Можно также самостоятельно скомпилировать код в

Arduino Studio.

Также ниже будет описано, как программировать плату Ganglion с использованием аппаратного обеспечения.

4.8.1. Скачивание последней версии прошивки

Для начала необходимо загрузить последнюю версию прошивки платы v2.0.0 (https://github.com/OpenBCI/OpenBCI_Ganglion_Library/releases/latest).

Также можно прочитать заметки о выпуске и многое другое на Github или перейти ниже по разделам, чтобы настроить мобильное устройство для продолжения программирования OTA.

4.8.2. Сборка из источника данных

Радиомодуль Simblee (в настоящее время снят с производства), который находится в самом сердце платы Ganglion, предлагает возможность перепрограммирования Over The Air OTA методом. Этот метод позволяет сделать программирование простым, следуя шагам:

1.Создание новой прошивки Ganglion или изменение существующего кода

вArduino IDE.

2.Создание скомпилированного HEX-файла в Arduino IDE.

3.Сжатие этого файла в ZIP с некоторыми другими важными файлами.

4.Перенесение файла ZIP на смарт-телефон или планшет.

5.Подключение смарт-телефона или планшета к плате Ganglion.

6.Загрузка нового кода через Over The Air (по радиоканалу).

109