Введение
В этой статье я расскажу как подключить дозиметр AtomTag через Bluetooth модуль Bluegiga BLED112 к Raspberry PI для того, чтобы передавать результаты измерений на сервис «Народный Мониторинг» (http://narodmon.ru/).
AtomTag – Bluetooth Low Energy дозиметр для смартфона и планшета со счетчиком Гейгера СБМ-20. Устройство будет передавать на сервер: мощность дозы, статистическую погрешность и заряд аккумулятора. В конце статьи посмотрим как связаны показания дозиметра с погодными явлениями.
Generic Attribute Profile (GATT)
Дозиметр AtomTag поддерживает профиль GATT. По терминологии Bluetooth профиль – это набор функций или возможностей, доступных для определенного устройства Bluetooth.
GATT профиль определяет иерархическую структуру хранения данных. Структура представлена на рисунке:
Сервис – это контейнер, содержащий несколько атрибутов, которые называются характеристиками. Все сервисы имеют уникальные идентификаторы UUID и HANDLE. Например, дозиметр имеет 2 сервиса:
1. Сервис для пользователя, в котором содержатся характеристики для считывания результатов измерений и записи пользовательских настроек (настройки звуковой сигнализации).
2. Сервис, который содержит характеристики для хранения заводских настроек: калибровочные коэффициенты, имя устройства и т.д.
Характеристика – состоит из:
1. Значения (обычно не более 20 байт).
2. Дескриптора – здесь описано назначение характеристики, тип хранимых данных, а также настройки характеристики.
3. Уникального идентификатора UUID и HANDLE.
Интересующие нас данные: количество зарегистрированных импульсов и заряд батареи хранятся как раз в характеристиках.
BLED112
Модуль представляет из себя USB-CDC устройство, которое определяется в системе как /dev/ttyACM0 и не требует установки никаких драйверов на Raspbian Jessie Lite с версией ядра 4.4. Обмен данными с модулем производится также как с последовательным портом. Протокол обмена – бинарный. Мы не будем сами писать парсер протокола, т.к. команд у этого модуля довольно много и возьмем SDK на языке Си от производителя. Ссылка на SDK будет в конце статьи.
ПО для Raspberry PI
Нам потребуются следующие файлы из SDK:
1. cmd_defs.c, cmd_defs.h
2. apitypes.h
3. commands.c
4. uart.c, uart.c
API является callback-based. В файле commands.c объявлены реализации-«заглушки» для неиспользуемых коллбеков. В SDK определены 2 типа сообщений, которые могут прийти от модуля: событие и результат выполнения операции. В нашей программе мы будем получать данные от дозиметра при помощи оповещений, которые отправляются дозиметром каждые 2 секунды при изменении измерительной характеристики. В итоге раз в 2 секунды будет приходить событие от модуля и вызываться соответствующий коллбек.
Разберем алгоритм подключения и обмена данными с дозиметром:
1. Открывает порт /dev/ttyACM0
2. Перезагружаем Bluetooth модуль при помощи функции api ble_cmd_system_reset();
3. Подключаемся к устройству по его адресу при помощи ble_cmd_gap_connect_direct()
4. Запрашиваем список сервисов устройства и диапазоны значений, в которых лежат HANDL’ы характеристик в этих сервисах ble_cmd_attclient_read_by_group_type()
5. После события ble_evt_attclient_procedure_completed
запрашиваем список характеристик при помощи ble_cmd_attclient_find_information().
6. В событии ble_evt_attclient_find_information_found
запоминаем HANDL’ы измерительной характеристики и Client Characteristic Configuration Descriptor (CCCD).
7. В событии ble_evt_attclient_procedure_completed
включаем оповещения. В предыдущем пункте мы узнали HANDLE дескриптора CCCD и можем его прочесть или записать. Чтобы включить оповещения, нужно установить флаг «notifications enabled» в дескрипторе CCCD при помощи функции ble_cmd_attclient_attribute_write()
. После отключения от устройства значение этого дескриптора обнулится.
8. Теперь при изменении значений характеристик устройства будет вызываться событие ble_evt_attclient_attribute_value(const struct ble_msg_attclient_attribute_value_evt_t *msg)
. Отличить одну характеристику от другой можно по параметру:
msg->atthandle.
Определим структуру значения измерительной характеристики:
typedef struct __attribute__((__packed__)){
uint8 status_flags;
float dose; //накопленная доза с момента включения
float doserate_search; //мощность дозы в режиме поиска
uint16 pulses_last2sec; //кол-во импульсов со счетчика Гейгера за последние 2 секунды
uint8 battery; //заряд батареи в процентах от 0 до 100
uint8 temperature; //температура в градусах
} atomtag_measurement_t;
atomtag_measurement_t measurement_char;
Поскольку порядок байт в значении измерительной характеристики – little endian, то достаточно скопировать все эти байты в упакованную структуру:
memcpy((uint8 *)&measurement_char, msg->value.data, msg->value.len);
Мощность дозы будем рассчитывать на временном интервале 6 минут. Отправлять показания на сервер narodmon.ru будем не чаще, чем раз в 6 минут. Помимо мощности дозы будем отправлять заряд батареи и статистическую погрешность. Все расчеты происходят в коллбеке ble_evt_attclient_attribute_value()
в файле main.c.
Показания отправляются на порт 8283 narodmon.ru по протоколу tcp. Ответ от сервера не проверяется. Протокол текстовый:
#00:00:00:00:00:00n
#R1#10.5#err = 10%, batt = 100%n
##
Вначале следует MAC адрес устройства (6 байт). В исходниках MAC адрес вбит для примера, не забудьте его поменять! Далее, где 10.5 – это мощность дозы в мкР/ч, err – статистическая погрешность
Скомпилировал всё это при помощи gcc:
gcc -std=gnu99 -lm main.c cmd_def.c commands.c uart.c web.c -o narodmon-bin
Для того, чтобы программа автоматически запускалась после загрузки ОС, я добавил следующие строки перед exit 0 в файл rc.local:
cd /
./home/pi/narodmon/narodmon-bin /dev/ttyACM0 5c:31:3e:da:e8:9c
5c:31:3e:da:e8:9c – адрес устройства Bluetooth, который можно узнать, если запустить эту программу с параметром scan:
./narodmon-bin /dev/ttyACM0 scan
Результаты
Спустя пару дней работы устройства на графиках появились интересные вещи. Здесь видно, как изменилась мощность дозы во время снегопада. 11 ноября в ~17:00…18:00 часов прекратился ледяной дождь и начал идти снег. По мере роста толщины снежного покрова средняя мощность дозы уменьшалась. Дозиметр установлен на высоте 2 метра от земли.
Снижение мощности дозы объясняется тем, что слой снега частично экранирует естественное гамма излучение у поверхности земли. Также снежный слой перекрывает доступ газа радона на поверхность, дочерние продукты распада которого можно засечь обычным дозиметром.
Теперь мы можем оценить толщину снега :) В те дни выпало около 8-10 сантиметров снега. В мире практикуется аэрогаммасъемка для оценки толщины снега в районах где находятся ГЭС, чтобы понять какого наводнения ожидать весной. Только там применяются гамма спектрометры со сцинтилляционными детекторами из-за их большей чувствительности.
Аналогичная картина наблюдается и на остальных дозиметрах сервиса народный мониторинг, правда не все они отдают данные так часто и не понятно какие алгоритмы вычисления мощности дозы там используются.
Программу можно доработать, если добавить буфер, в который будут сохраняться показания дозиметра в моменты отсутствия подключения к интернету. API народного мониторинга позволяет отправлять показания «задним числом». Также стоит подключить raspberry pi к бесперебойнику. Несмотря на простоту конструкции удалось получить uptime около тридцати дней. Дозиметр на карте народного мониторинга можно найти здесь. Прошу не пинать — в linux я новичек.
Ссылки
1. Дозиметр AtomTag: youratom.com/#/store/atomtag
2. SDK и документация Bluegiga BLED112:
www.silabs.com/support/pages/document-library.aspx?p=Wireless%20-%20Bluetooth&f=Bluetooth%20Smart%20Modules&pn=BLED112
3. Сервис народный мониторинг narodmon.ru
4. Bluetooth LE, спецификации: www.bluetooth.com/specifications/gatt
5. Исходный код программы для Raspberry PI
Автор: KbRadar