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

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

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

8.1.3.10. Виджет воспроизведения

Виджет воспроизведения появляется только в режиме воспроизведения (рис. 8.31). Виджет позволяет выбрать другой файл для воспроизведения без необходимости останавливать всю систему. В правом верхнем углу виджета есть кнопка, позволяющая выбрать любой файл для воспроизведения записей с плат OpenBCI (.txt или .csv). Выбор других типов файлов может вызвать ошибку программы.

Рис. 8.31. Виджет воспроизведения

8.1.3.11. Виджет пульса

Данный виджет будет отображаться только для плат Cyton в режиме Live. Виджет использует режим аналогового чтения для получения данных с вывода, отмеченного как D11 на плате Cyton. Используя полученные данные, виджет рассчитает количество ударов в минуту (BPM) и интервал между ударами (IBI). При использовании виджета «Сеть» расчитанные данные BPM и IBI можно отправлять в стороннее программное обеспечение.

8.1.3.12. Пользовательский виджет

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

Для начала необходимо сделать дублирование и переименование файла

“W_template.pde”.

200

Файл “W_template.pde” предназначен для использования в качестве простой отправной точки для создания собственных виджетов. Данный файл необходимо скопировать и переименовать так, как будет называться новый виджет (например, “W_myNewWidget.pde”). Чтобы переименовать класс, необходимо убедиться, что он является уникальным и не совпадает с классом W_template.pde. Первая некомментированная строка файла должна выглядеть так:

class W_myNewWidget extends Widget {

Затем надо добавить новый виджет в файл “widgetManager.pde”. Перед добавлением любого необычного кода, который захватывает локальные структуры данных, надо убедиться, что новый виджет добавлен в файл “widgetManager.pde”. Сделав это, необходимо убедиться, что новый виджет добавлен в выпадающее меню каждого виджета. Это желательно делать для того, чтобы сразу смотреть, как добавляется график в виджет и продолжается его строение.

Далее надо следовать протоколу создания нового виджета в глобальных переменных:

// MAKE YOUR WIDGET GLOBALLY

W_timeSeries w_timeSeries;

W_fft w_fft;

W_networking w_networking;

W_BandPower w_bandPower;

W_accelerometer w_accelerometer;

W_ganglionImpedance w_ganglionImpedance;

W_headPlot w_headPlot;

W_template w_template1;

W_emg w_emg;

W_openBionics w_openbionics;

W_Focus w_focus;

W_PulseSensor w_pulsesensor;

W_myNewWidget w_myNewWidget;

Затем надо убедиться, что виджет настроен, добавлен в массив всех виджетов:

w_networking = new W_networking(_this); w_networking.setTitle("Networking"); addWidget(w_networking, w);

w_myNewWidget = new W_myNewWidget(_this); w_myNewWidget.setTitle("My New Widget"); addWidget(w_myNewWidget, w);

w_bandPower = new W_BandPower(_this); w_bandPower.setTitle("Band Power"); addWidget(w_bandPower, w);

201

Следующий шаг заключается в добавлении выпадающих списков, чтобы контролировать виджет, если это необходимо. Но прежде чем скомпилировать графический интерфейс, нужно переименовать глобальные функции внизу файла “W_myNewWidget.pde”, для того чтобы они отличались от глобальных функций внизу в файле “W_template.pde”. Во время работы графического интерфейса эти функции автоматически активируются, когда в навигационной панели виджета активируется соответствующий раскрывающийся список. Необходимо убедиться, что строка (например, «Dropdown1») в функции “addDropdown” конструктора - это та же строка, что и имя соответствующей глобальной функции в нижней части файла “.pde”. Индекс выбранного пункта меню - это то, что передается в функцию (т. е. «Int n»):

//These functions need to be global! These functions are activated when an item from the corresponding dropdown is selected

void Dropdown1(int n){

println("Item " + (n+1) + " selected from Dropdown 1"); if(n==0){

//do this

} else if(n==1){ //do this instead

}

closeAllDropdowns(); // do this at the end of all widget-activated functions to ensure proper widget interactivity ... we want to make sure a click makes the menu close

}

void Dropdown2(int n){

println("Item " + (n+1) + " selected from Dropdown 2"); closeAllDropdowns();

}

void Dropdown3(int n){

println("Item " + (n+1) + " selected from Dropdown 3"); closeAllDropdowns();

}

Далее можно запустить графический интерфейс и убедиться, что новый виджет виден в выпадающем меню виджетов в верхнем левом углу всех виджетов. Если его нет, то надо убедиться, что вышеуказанные шаги выполнены правильно.

После вышеуказанных шагов надо разобраться, как уже существующие виджеты обращаются к структурам данных, внутренним по отношению к программе GUI.

Каждый виджет имеет переменные x, y, w, h, которые соответствуют левому краю виджета (горизонтальное расположение пикселей), верхнему краю виджета (вертикальное расположение пикселей), ширине пикселей и высоте пикселей соответственно. Эти переменные обновляются автоматически при изменении размера экрана или при циклическом переключении виджетов через контейнеры макета. При добавлении графики в виджет все действия основываются на этих переменных.

202

Помимо настройки виджета в файле “widgetManager.pde”, весь код может находиться внутри файла “W_myNewWidget.pde” (если все сделано правильно).

Чтобы узнать, как получить доступ к глобальным структурам данных, таким как данные FFT (БПФ) и данные временных рядов, надо посмотреть, как другие виджеты обращаются к данным функциях update().

Одним из способов добавления в виджеты таких функций, как выпадающие списки и переключатели, является библиотека “ControlP5”. Чтобы узнать больше о том, как работают виджеты, надо изучить файл widget.pde.

Следующий шаг в разработке виджета это добавление любых выпадающих настроек в “SoftwareSettings.pde”. Начиная с версии v4 программы GUI, приложение пытается автоматически сохранить и автоматически загрузить настройки пользователя. Если этого не будет происходить, то пользователям придется каждый раз переконфигурировать графический интерфейс. Поэтому, если используются раскрывающиеся списки в новом виджете, то нужно включить эти настройки в файле “SoftwareSettings.pde” в

функциях save () и load ().

Вверху файла “SoftwareSettings.pde” есть несколько подробностей, которые могут быть полезны. Необходимо придерживаться стиля, который уже используется для сохранения и загрузки данных из “JSON”. Пролистав код в функциях save () или load (), можно найти настройки некоторых известных виджетов. Эти настройки и надо использовать в качестве примера.

После выполнения вышеуказанных шагов можно приступить к начальному тестированию. Если при отладке добавить какую-либо функцию println() или verbosePrint() в разработанный виджет, то можно будет использовать функцию “Console Log”, чтобы увидеть эти сообщения или просто посмотреть на консоль в IDE. Размеры экрана и некоторые объекты нужно будет изменить или повторно позиционировать при смене размера экрана графического интерфейса. Вот почему класс виджетов имеет

“screenResized()” метод. Как правило, объекты x, y, width и height объявляются при создании экземпляра виджета и затем снова при использовании “screenResized()” при относительном позиционировании.

После настроек необходимо проверить, что все работает. Настройки можно увидеть в файле настроек JSON для каждого режима данных в папке

“Documents/OpenBCI_GUI/Settings/”. Файлы JSON можно просматривать как текст. Необходимо убедиться, что новый объект JSON и данные записываются в файл. Наконец, надо убедиться, что настройки работают правильно при настройке виджета, сохранении и загрузке.

Одним из наиболее распространенных способов сбоя графического интерфейса, связанных с работой нового виджета, является рисование “null” данных или появление других ошибок, связанных с функцией draw(). Еще одна распространенная ошибка – это отображение “Exception” на консоли “Atom”, “VSCode” или “Processing IDE”.

203

8.1.4. Программа OpenBCI Hub

Программа OpenBCI Hub это промежуточное программное обеспечение, используемое для организации связи с платами OpenBCI через протокол команд TCP / IP. Версия v2.0.0 программы OpenBCI Hub выпущена в сентябре 2018 года, версия v1.0.0 выпущена 3 января 2017 года.

OpenBCI Electron Hub (или просто «Hub») это сервер TCP / IP, который прослушивает клиентов через порт 10996 на localhost по адресу 127.0.0.1. Broadcast/multicast никогда не используется для передачи информации клиентам. Исходящие данные передаются только запрашивающему клиенту. В программе используется семантическое управление версиями, протокол всегда указывается в первую очередь в любой документации. Необходимо следовать правилам семантического управления версиями, чтобы не нарушать изменения.

Концентратор может использоваться в двух режимах работы:

Собственно, приложение, такое как приложение обработки данных OpenBCI, запускает и останавливает концентратор.

Концентратор работает непрерывно, и сторонние приложения могут просто подключаться как клиенты, использовать платы OpenBCI для приема данных, отключаться и продолжать работу, не закрывая при этом концентратор.

Уникальный порт 10996 критически важен, потому что приложения должны иметь возможность подключаться к известному номеру порта на локальном компьютере. Спецификация по использованию порта доступна на ресурсе github.com (https://github.com/OpenBCI/OpenBCI_Hub).

Начиная с версии 2.0.0, концентратор использует формат JSON для передачи и получения сообщений по протоколу TCP. Каждая строка JSON должна заканчиваться символом “\n”. Необходимо выполнить синтаксический анализ по наличию «\n», а затем зачистить начало строк до символов \n и использовать те языки программирования, которые встроены в анализатор JSON. Содержимое буфера после этого можно считать сообщением. Буфер может быть очищен, а сообщение может быть обработано. Для анализа остальной части сообщения всегда используется клавишная команда с клавиатуры. Оставшаяся часть сообщения будет обработана по заданной команде на основе протокола, описанного в спецификации. Все команды, отправленные клиенту, будут отвечать асинхронно.

Например, если клиент отправляет запрос-сообщение {"type":"scan", "action":"start"}\n на концентратор 127.0.0.1:10996, то в ответ будет получено либо сообщение {"type":"scan", "action":"start", "code":200}\n с вопросом началось ли сканирование, либо сообщение об ошибке вида

{"type":"scan","code":412,"message":"unable to start scan"}\n, если не удалось запустить сканирование.

204

Все команды отправляются от клиента к хабу. Каждая команда получает асинхронный ответ со значимым кодом. Когда это возможно, ошибки отправляются со строковыми сообщениями об ошибках.

Далее рассмотрим команды для управления акселерометром (тип: accelerometer). Для того чтобы остановить или запустить акселерометр, надо выполнить команды: action – start или action - stop. Запуск акселерометра актуален только для плат Ganglion и в версии программного обеспечения v1.0.0.

Например, посылается команда {"type":"accelerometer", "action": "start"}.

Вслучае успешного выполнения приходит ответ: {"type":"accelerometer", "action": "start", "code": 200}. В случае неудачи приходит ответ следующего содержания: {"type":"accelerometer", "action": "start", "code": 416, "message": "string error message"}.

Остановка акселерометра тоже полезна только для плат Ganglion.

Например, отправляется команда вида {"type":"accelerometer", "action": "stop"}.

Вслучае успешного выполнения будет получен ответ: {"type":"accelerometer", "action": "stop", "code": 200}. В случае невыполнения команды будет получен следующий ответ: {"type":"accelerometer", "action": "stop", "code": 417, "message": "string error message"}.

Далее рассмотрим команды установки типа платы (тип boardType). Команда устанавливает тип платы принудительно в соответствии с запрошенным пользователем типом платы, например, когда пользователь запрашивает использование платы Cyton в 16-канальном исполнении. Эта команда полезна только для плат Cyton из-за использования вместе с ними и плат Daisy .

Команда “boardType – cyton” служит для установки 8-канальной платы Cyton с версией прошивки v2.0.0. Команда при выполнении запроса выглядит следующим образом: {"type":"boardType", "boardType": "cyton"}. В случае успешного выполнения команды будет получен следующий ответ: {"type":"boardType", "boardType": "cyton", "code": 200}. В случае неудачи будет получен ответ: {"type":"boardType", "boardType": "cyton", "code": 421, "message": "string error message"}.

Команда “boardType – daisy” применяется для установки конфигурации 16-канальной платы Cyton с версией прошивки v2.0.0. Пример отправляемой команды следующий: {"type":"boardType", "boardType": "daisy"}. В случае успешного выполнения будет ответ: {"type":"boardType", "boardType": "daisy", "code": 200}. При неудаче будет следующий ответ: {"type":"boardType", "boardType": "daisy", "code": 421, "message": "string error message"}.

Далее рассмотрим команды настройки канала (тип channelSettings). Команды используются для настройки параметров канала на плате Cyton (с версией прошивки v2.0.0) с установленными протоколами WiFi или Serial.

Команда “action – start” используется для запуска синхронизации настроек канала. Её выполнение приводит к успешной настройке канала.

205

Пример отправляемой команды следующий: {"type":"channelSettings", "action": "start"}. В случае успеха выполнения команды выводится сообщение

{"type":"channelSettings", "action": "start", "code": 200}. При ошибке выполнения,

в случае, когда синхронизация установки канала уже выполняется, будет выведено сообщение {"type":"channelSettings", "action": "start", "code": 422, "message": "Sync in progress"}.

Команда “action – set” используется для установки канала для плат Cyton

или Ganglion через Wi-Fi канал.

Параметр “channelNumber” (номер_канала) нумеруется начиная с нуля, т.е. 0-7 или 0-15 для плат Cyton и Cyton + Daisy соответственно.

Параметр “powerDown” (выключить) имеет значение либо “true”, если канал выключен, либо “false”, если канал включен, как положено.

Параметр “gain” (коэффициент усиления) это целочисленное значение усиления: 1, 2, 4, 6, 8, 12, 24.

Параметр “inputType” (тип ввода) служит для выбора канала АЦП. Данный параметр это строка, которая должна быть одной из следующих: «normal», «shorted», «biasMethod», «mvdd», «temp», «testsig», «biasDrp», «biasDrn».

Параметр “bias” (смещение) устанавливает для входа конкретного канала некое смещение. Это число, на которое происходит смещение всех данных в канале при установленном значении “true”. При значении “false” данные с канала принимаются без смещения.

Параметр “srb2”, если выставлен как “true”, служит для установки соединения входа “P” соответствующего канала с выводом SRB2. Фактически происходит замыкание входа P и вывода SRB2 для данного канала, это позволяет входу P также оставаться подключенным к АЦП. Данный параметр это целое число, где значение “true” означает, что вход будет соединен с выводом SRB2 (по умолчанию). Значение “false” означает, что вход будет отключен от вывода SRB2.

Параметр “srb1” служит для подключения N входов всех каналов к выводу SRB1, если установлен в значение “true”. Параметр влияет на все N входы одновременно, подключая или отключая их одновременно от АЦП. Параметр это целое число, где значение “true” означает соединение всех N входов с выводом SRB1 и значение “false” означает отсоединение всех N входов от вывода SRB1 (значение “false” используется по умолчанию).

Ниже приведен пример использования параметров:

{

"action": "set",

"type": "channelSettings", "channelNumber": 3, "powerDown": false, "gain": 24,

"inputType": "normal", "bias": true,

206

"srb2": true, "srb1": false

}

После выполнения вышеприведенных команд будет получен следующий ответ в случае успеха: {"type":"channelSettings", "action": "set", "code": 200}. При невозможности выполнить команду будет дан ответ: {"type":"channelSettings", "action": "set", "code": 424, "message": "verbose error message here"} Ответ при неудачном разборе входных команд будет выглядеть следующим образом: {"type":"channelSettings", "action": "set", "code": 425, "message": "more verbose error message"}. Это означает, что ввод строки через запятую не содержал правильных позиций, и следует проверить синтаксис.

Команда “command” передает один символ или строку на подключенное устройство (с прошивкой версии v2.0.0). Синтатксис данной команды следующий: “command - *”. Команда использует для передачи через модуль на подключенную плату один или несколько символов. Режим мультипередачи ограничен 30-ю символами по WiFi и 19-ю по BLE.

Пример использования данной команды: {"type":"command", "command": "1"}. В случае успеха будет получен следующий ответ: {"type":"command", "command": "start", "code": 200}. При ошибке и невозможности записать команду на подключенное устройство будет выдано сообщение

{"type":"command", "command": "start", "code": 406, "message": "verbose error message"}. При сбое, когда протокол текущего устройства не выбран, будет сообщение {"type":"command", "command": "start", "code": 420, "message": "verbose error message"}.

Команда “Connect” (тип connect) осуществляет подключение к любому устройству с известным локальным именем или IP-адресом.

Параметр “name” (имя) это имя уникального локального USB-ключа для платы Cyton, периферийного устройства Ganglion или подключенного WiFi Shield.

Не обязательная команда “burst” применяется для использования пакетного режима. Она имеет значение либо “true”, либо “false”. Команда используется в том случае, если применяется протокол UDP.

Необязательная команда “sampleRate” представляет собой число, устанавливающее частоту запрошенной выборки, для подключенной платы Ganglion или Cyton. У платы Ganglion при этом должна быть прошивка не ниже версии v2.0.0, а у платы Cyton должна быть прошивка не ниже версии v3.0.0. Значение указывается в Гц и должно быть допустимой частотой дискретизации для выбранной платы.

Необязательная команда “latency” (задержка) это число, которое является задержкой для межпакетной отправки на плату WiFi Shield. Время задается в микросекундах.

Необязательная команда “protocol” (протокол) определяет тип используемого интернет-протокола: «udp» или «tcp».

207

Необязательная команда “ipAdderss” устанавливает IP-адрес устройства. Пример сформированной команды для плат Ganglion или Cyton выглядит следующим образом: {"type": "connect", "name": "Ganglion-XXXX"}. Пример

команды для передачи по WiFi через протокол “tcp” с установкой имени:

{

"type": "connect",

"name": "OpenBCI-XXXX", "latency": 1000, "sampleRate": 500, "protocol": "tcp"

}

Пример команды для передачи по WiFi через протокол “UDP” с пакетным режимом и IP-адресом:

{

"type": "connect", "ipAddress": "192.168.4.1", "latency": 1000, "sampleRate": 500, "protocol": "udp", "burst": true

}

В случае успеха выполнения команды будет получен следующий ответ: {"type":"connect", "firmware": "v2.0.0", "code": 200}. При невозможности подключения будет дан ответ вида {"type":"connect", "code": 402, "message": "verbose error message"}. Если происходит сбой из-за уже установленного соединения, то ответ будет следующий: {"type":"connect", "code": 408}.

Команда “Отключить” (тип disconnect) предназначена для отключения от подключенного устройства (начиная с версии программы v1.0.0).

Пример данной команды следующий: {"type":"disconnect"}. В случае успеха выполнения команды будет ответ: {"type":"disconnect", "code": 200}. В случае сбоя и невозможности отключиться от подключенного устройства будет следующий ответ: {"type":"disconnect", "code": 401, "message": "verbose error message"}.

Команда “Examine” служит для проверки-тестирования платы WiFi.

Пример команды с именем платы WiFi: {"type":"examine", "shieldName": "OpenBCI-XXXX"}. Пример команды с именем с IP-адресом {"type":"examine", "ipAddress": "192.168.4.1"}.

Если плата WiFi Shield обнаружена до посылки команды, то ответ будет следующего вида: {"type":"scan", "action": "stop", "code": 200}. В случае успеха будет следующий ответ: {"type":"examine", "code": 200}. Ответ при невозможности подключения к устройству будет такой: {"type":"examine", "code": 402, "message": "verbose error message"}. Если устройство уже подключено, то при ошибке ответ будет следующий: {"type":"examine", "code":

208

408, "message": "verbose error message"}. Ответ при невозможности остановить сканирование будет такой:{"type":"examine", "code": 411, "message": "could not stop error"}.

Команда impedance (полное сопротивление) останавливает или начинает тестирование импеданса для платы Ganglion или отправляет параметры настройки импеданса для платы Cyton.

Параметр “action – set” используется для установки регистров импеданса для платы Cyton (с прошивкой версии v2.0.0 и выше).

Параметр “channelNumber” (номер канала) начинает нумерацию значений с нуля, т.е. 0-7 для плат Cyton или 0-15 для плат Cyton совместно с Daisy.

Параметр “pInputApplied” используется в том случае, если сигнал импеданса направляется на вход P при выполнении параметра

“channelNumber”.

Параметр “nInputApplied” используется в том случае, если сигнал импеданса направляется на вход N при выполнении параметра

“channelNumber”.

Пример команды:

{

"action": "set", "type": "impedance", "channelNumber": 3, "pInputApplied": false, "nInputApplied": true

}

В случае успеха выполнения данной команды будет следующий ответ: {"type":"impedance", "action": "set", "code": 200}. При невозможности определить сопротивление будет выведено сообщение {"type":"impedance", "action": "set", "code": 424, "message": "verbose error message here"}. Ответ при неудачном выполнении входных команд будет следующий: {"type":"impedance", "action": "set", "code": 431, "message": "more verbose error message"}.

Параметр “action – start” используется для запуска тестирования импеданса на плате Ganglion (с версией программы v1.0.0).

Пример выполнения команды: {"type":"impedance", "action": "start"}.

В случае успеха выполнения команды будет следующий ответ: {"type":"impedance", "action": "start", "code": 200}. При невозможности запуска команды будет выдано сообщение {"type":"impedance", "action": "start", "code": 414, "message": "Error message"}.

Параметр “action – stop” используется для остановки тестирования импеданса на плате Ganglion (с версией прошивки v1.0.0).

Пример выполнения команды: {"type":"impedance", "action": "stop"}. В случае успеха будет ответ: {"type":"impedance", "action": "stop", "code": 200}.

209