Решил я на досуге поэкспериментировать с измерением радиации (а почему бы и нет?), посмотрел доступные девайсы, почитал статьи и пришёл к выводу, что мне нужен датчик уровня радиации, который я могу подключить к микроконтроллеру и интегрировать в свою IoT систему.
Выбор пал на сенсор RadSens компании ClimateGuard, а вот о том, что последовало за этим, о моих приключениях и о том, что из всего этого вышло вы узнаете из этой статьи.
❯ Зачем это нужно?
С одной стороны, миллионы людей живут без дозиметра и прекрасно себя чувствуют. С другой стороны, среди бытовых предметов встречаются экземпляры, которые излучают довольно значительный радиационный фон (некоторые модели часов, предметы посуды и т. п.), что очевидно не очень полезно для здоровья и, например, знать, что ты носишь на руке радиоактивные часы явно не помешает для принятия взвешенного решения продолжать ли это делать или лучше не стоит.
Кроме этого есть ещё всякие аномальные случаи типа радиоактивных стройматериалов, продуктов питания, загрязнённой почвы и т. п., в общем иметь прибор объективного контроля, который может тебя предупредить явно не помешает.
Ну и, кроме всего прочего, это просто
❯ D. I. Y. do or die
Поэкспериментировать с измерением радиации можно двумя способами: купить готовое устройство (дозиметр) или собрать его самостоятельно. Каждый из этих способов имеет свои достоинства и недостатки.
Готовое устройство. Тут не нужно ничего выдумывать и тратить время и силы на его изготовление. Можно подобрать любую модель дозиметра по цене, функциям и внешнему виду. Цена вопроса от 3 до 30++ тысяч рублей. Вариант неплохой, но не очень интересный и, я бы даже сказал, не спортивный.
DIY (do or die). Это вариант по принципу «удочка всегда лучше, чем просто рыба». Тут можно познакомиться со схемотехникой, датчиками, принципами измерения радиации, создать код для интеграции сенсора в свою IoT инфраструктуру и т. д., а также в дальнейшем создать «дозиметр своей мечты».
Кстати, одно не исключает другое: можно и купить готовый дозиметр и напрямую поэкспериментировать с датчиком радиации. Как говорится, кашу маслом не испортишь.
В общем, решил я начать с DIY варианта в том или ином виде и стал изучать доступные предложения. Вырисовалось два пути:
- купить один датчик, а весь обвес к нему сделать самому по одной из распространённых в интернете схем;
- купить готовый модуль сенсора на который достаточно подать питание и получать с него данные по тому или иному интерфейсу.
По здравому размышлению решил остановиться на втором варианте, как наилучшем с точки зрения соотношения затраченных усилий и получаемого результата. Осталось только выбрать и купить такой сенсор.
Примечание. В этой статье я непосредственно сам чувствительный элемент («трубку») называю датчиком, а комплект «трубка + обвес» — сенсором. Это не совсем корректно с лингвистической точки зрения, но позволяет разграничить в тексте два эти понятия.
❯ Почему RadSens?
Посмотрел я доступные предложения, и моим критериям соответствовали несколько безымянных китайских девайсов с AliExpress и довольно популярный сенсор RadSens компании ClimateGuard. Мне было всё равно, что покупать, но RadSens выглядел предпочтительнее, поскольку компания осуществляет техническую поддержку, консультирует в Telegram-канале и выполняет гарантийные обязательства.
И кроме всего прочего, сенсор RadSens имеет минимальные габариты (чуть больше трубки датчика радиации), I2C интерфейс и импульсный выход для прямой интеграции с контроллерами, что очень благоприятствует встраиванию этого сенсора в различные DIY устройства.
В качестве чувствительного элемента в RadSens используется трубка СБМ-20 (СБМ-20-1), которую можно назвать стандартом в непрофессиональном измерении радиации — она обеспечивает базовый уровень чувствительности к гамма-, бета- радиации и рентгену. Правда не реагирует на альфа- радиацию и мягкую бету, но для дозиметра начального уровня и экспериментов вполне подходит.
Для справки: есть ещё множество датчиков радиации, гораздо более профессиональных и чувствительных, но из-за их цены о них имеет смысл говорить только тогда, когда вы точно знаете что вы делаете и зачем вам это нужно.
Датчики (трубки) СБМ-20 и СБМ-20-1 — это практически одно и то же, они различаются только своими габаритами (СБМ-20 длиннее и имеет разъёмное крепление). RadSens также имеет «длинные» и «короткие» платы. Длинные более универсальны — они могут работать с обоими типами трубок (а также могут обрезаться без потери работоспособности до короткого варианта), а короткие более компактны и лучше подходят для встраивания в различные корпуса.
В случае RadSens цена вопроса — от 4 до 5 тыс. рублей в зависимости от торговой площадки, что для сенсора, я бы сказал, не так уж и мало (но чего не сделаешь ради науки).
❯ RadSens
Поставляется RadSens в очень внушительной упаковке — такое количество поролона и такая лаконичность (я бы даже сказал концептуальность) размещения намекают на исключительную ценность содержимого. Ну и повредить так упакованную трубку — тоже нужно очень постараться.
Я выбрал короткий вариант на СБМ-20-1. Достаём устройство, которое на деле оказывается довольно миниатюрным (что хорошо для встраивания). Пайка аккуратная, сама плата тоже производит благоприятное впечатление. Мне достался экземпляр последний на этот момент ревизии 1V7.
Примечание. Это, кстати, хороший пример того как не надо называть устройства. Оказывается 1 — это не номер версии, а использование короткой трубки. Правильное с маркетинговой и человеческой точки зрения название: «RadSens Mini V7».
Общая идея работы и взаимодействия с сенсором RadSens следующая: на плате имеется 4-контактный разъём 3V3, GND, SCL, SDA. Предполагается, что вы подадите на сенсор напряжение 3,3 В с вашего контроллера и будете получать с него данные по интерфейсу I2C (также есть возможность изменять некоторые настройки сенсора по этому интерфейсу).
Сам сенсор содержит трубку СБМ-20-1, высоковольтную часть (400 В) и микроконтроллер STM32, который обеспечивает логику работы устройства и его интерфейсные функции.
По интерфейсу I2C RadSens отдаёт 3 параметра:
- «Статическое» значение уровня радиации. Это усреднённое значение уровня радиации на интервале 500 секунд (около 8 минут). Предназначено для точного измерения уровня радиации;
- «Динамическое» значение уровня радиации. Это усреднённое значение уровня радиации на интервале до 123 сек. С «плавающим» (в зависимости от динамики излучения) окном. Предназначено для оперативного обследования объектов;
- Количество импульсов с последнего считывания по I2C. Предназначено для получения по I2C данных о количестве импульсов СБМ-20-1.
Для работы с сенсором существуют как фирменная, так и сторонние Arduino библиотеки, а также даташит с указанием регистров для непосредственного взаимодействия с сенсором любого микроконтроллера, управляемого любым кодом и имеющим интерфейс I2C.
Кроме этого, рядом с 4-пиновым разъёмом плата имеет ещё один контакт — INT, предназначенный для вывода информации об импульсах трубки СБМ-20-1. Важный момент: разница между получением данных об импульсах через интерфейс I2C и напрямую в том, что во втором случае нет задержки и мы получаем практически сырую (RAW) информацию об импульсах в реальном времени и можем делать с ней всё, что угодно: выводить на динамик, включать светодиоды или, самое главное, использовать в своём контроллере для любых расчётов радиации (по своим алгоритмам и в обход встроенного микроконтроллера STM32).
В целом, это полное описание концепции работы RadSens, но есть, как говорится, детали, о которых мы и поговорим далее.
❯ Паттерны использования
Как я уже заметил выше, использовать RadSens можно разными способами, меня в этом контексте интересуют два:
- Работа RadSens по интерфейсу I2C в качестве сенсора уровня радиации в проектах на Arduino.
- Работа RadSens в качестве сенсора и генератора сырых (RAW) данных об импульсах для последующей обработки в (моих) микроконтроллерах.
Примечание. Народ ещё любит использовать RadSens со «стоковой» прошивкой или с прошивкой WiFi-IoT и посылать данные на narodmon.ru, но я не являюсь поклонником ни первого, ни второго, ни третьего, поэтому никогда не использовал и не планирую использовать RadSens таким образом и, соответственно, не могу сказать об этом ничего содержательного.
В принципе, для большинства случаев вполне достаточно первого варианта, тем более, что он проще в реализации. Но в этом случае мы теряем контроль над реальной динамикой импульсов и всеми производными от этого, а также ограничены «сервисами», предоставляемыми софтом ClimateGuard (может кому-то это и «норм», но я явно не из таких).
Но начнём мы с первого варианта. Берём код официального примера и немного окультуриваем его:
/*
RadSens test
ESP32
*/
#include <Arduino.h>
#include <Wire.h>
#include "CG_RadSens.h"
#define I2C_SDA 33
#define I2C_SCL 32
CG_RadSens radSens(RS_DEFAULT_I2C_ADDRESS); // 0x66
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println(F("Start RadSens test..."));
Wire.begin(I2C_SDA, I2C_SCL);
delay(1000);
while(!radSens.init()) {
Serial.println("RadSens connectind error");
delay(1000);
}
set();
info();
delay(3000);
} // setup
void set() {
radSens.setSensitivity(105);
}
void info() {
uint8_t sensorChipId = radSens.getChipId(); // default 0x7D
uint8_t firmWareVer = radSens.getFirmwareVersion();
uint16_t sensitivity = radSens.getSensitivity();
bool hvGeneratorState = radSens.getHVGeneratorState();
bool ledState = radSens.getLedState();
Serial.print("Chip id: 0x"); Serial.println(sensorChipId, HEX);
Serial.print("Firmware: "); Serial.println(firmWareVer);
Serial.print("Sensitivity: "); Serial.println(sensitivity);
Serial.print("Generator: "); Serial.println(hvGeneratorState);
Serial.print("LED state: "); Serial.println(ledState);
Serial.println();
}
void generatorOn() {radSens.setHVGeneratorState(true);}
void generatorOff() {radSens.setHVGeneratorState(false);}
void ledOn() {radSens.setLedState(true);}
void ledOff() {radSens.setLedState(false);}
void loop() {
Serial.print("\tstt:"); Serial.print(radSens.getRadIntensyStatic()); // static
Serial.print("\tdyn:"); Serial.print(radSens.getRadIntensyDynamic()); // dynamic
Serial.print("\tpls:"); Serial.print(radSens.getNumberOfPulses()); // number of pulses
Serial.println();
delay(2000);
}
Запускаем скетч и убеждаемся, что это работает примерно так, как и ожидалось (уже хорошо). Но вот тут нас поджидают проблемы, которых, по идее, не должно быть (но они есть). Подробнее см. далее.
❯ Гладко было на бумаге
В принципе, по большому счёту, от RadSens больше ничего не нужно — он выдаёт три основных параметра, которые можно дальше использовать в своих проектах и всё бы было ничего, если бы он их выдавал стабильно.
Но — нет.
Первый звоночек прозвенел когда без каких-либо видимых причин параметр Sensitivity вместо нормальных 105 вдруг стал равен… нулю. Чего никогда и ни при каких обстоятельствах не должно быть. Пришлось его вручную установить в нормальное значение 105, а в сетапе добавить принудительную инициализацию, чтобы при каждом старте выставлять правильное значение. Это ни что иное как самый настоящий костыль на ровном месте.
void set() {
radSens.setSensitivity(105);
}
Ну, ОК, пусть будет костыль при инициализации, но если дальше RadSens будет работать адекватно, то с этим мелким неудобством можно смириться. Но снова — нет.
Следующим глюком было замечено внезапное скачкообразное изменение числа зарегистрированных импульсов с нормального значения до какого-то немыслимого, что-то вроде 352464. Это уже перевело RadSens в категорию приборов, которые требуют более пристального изучения и применения соответствующих инструментов для анатомирования (так, где мой скальпель?).
Пока я готовил инструменты для вскрытия, RadSens выкинул ещё один глюк: через примерно 10 минут нормальной работы статические и динамические данные вдруг стали равны нулю (все замеры, начиная с этого момента и до передёргивания питания сенсора).
Понятно, что при нормальной и исправной аппаратной части и корректно реализованной программной таких проблем возникнуть не может в принципе — это простейший случай датчика с I2C интерфейсом, коих на рынке миллион и все они работают нормально.
Примечание. У ClimateGuard есть Telegram-канал где инженеры компании отвечают на вопросы пользователей. Это отлично, но, если ознакомиться с этим каналом, то становится видно, что проблема с неадекватным поведением RadSens существует аж с 2019 года и пользователями зафиксированы десятки проявлений этой неадекватности.
В чём же причина этих глюков? Это отдельная тема, которую я постараюсь осветить далее.
❯ В чём проблема?
Для того, чтобы понять в чём проблема RadSens, нужно сказать несколько слов об архитектуре всей системы сенсора, а это именно «система», состоящая из нескольких частей:
- Высоковольтный драйвер трубки СБМ-20
- Микроконтроллерная часть с STM32 и его обвязкой
- Программный код прошивки STM32
- Интерфейсная часть I2C, её системная и прикладная имплементация
- Фирменная библиотека поддержки RadSens для Arduino
Уже из одного этого списка становится понятно, насколько это сложная система и что нормально она будет работать только при условии корректной реализации всех программно-аппаратных функций на всех её уровнях.
Теперь давайте разберём каждую часть по отдельности и назовём возможный вклад каждой подсистемы в общую нестабильность работы RadSens.
Высоковольтный драйвер трубки СБМ-20
Поскольку речь идёт о довольно высоком напряжении (400 В), то возможны наводки и помехи (при переходных процессах) в работе сенсора от высоковольтной части. Возможно дело в неправильном взаимном расположении низковольтных и высоковольтных элементов, в плохой фильтрации, пропускающей помехи или неправильном режиме работы высоковольтной части. Схема RadSens закрыта, поэтому невозможно сказать что-то более определённое по этому поводу.
Микроконтроллерная часть с STM32 и его обвязкой
Если есть огрехи в разводке проводников микроконтроллера STM32 или его обвязки, или применены ошибочные схемотехнические решения этой подсистемы, то возможны проблемы со стабильностью работы STM32 (особенно в соседстве с импульсной высоковольтной частью) и, соответственно, любые проявления этих проблем.
Программный код прошивки STM32
Качество работы программного кода прошивки зависит от квалификации программистов. Поскольку прошивка тоже закрыта, то сообщество не может провести аудит кода и помочь компании ClimateGuard устранить проблемы прошивки (если они там есть).
<h4Интерфейсная часть I2C, её системная и прикладная имплементация
Судя по всему, реализация I2C интерфейса RadSens (на системном или прикладном) уровне некорректна/не соответствует стандарту. Об этом косвенно говорят отзывы клиентов: с «родной» Arduino библиотекой RadSens работает более-менее нормально, а со сторонним кодом возникают проблемы.
Библиотека поддержки RadSens для Arduino
Судя по некоторым косвенным признакам, часть проблемы может быть на стороне Arduino библиотеки (что не исключает возможные проблемы с другими частями RadSens).
Итого, то, что проблема с RadSens существует у меня не вызывает никаких сомнений. В чём конкретно она заключается я сказать не могу — для этого требуются отдельные исследования, плюс всё это осложняется закрытостью как аппаратной, так и программной части RadSens.
Но что же делать?
Ну, во-первых, не факт, что описанные проблемы возникнут у вас — в Telegram-канале ClimateGuard есть множество отзывов о нормальной работе RadSens. Во-вторых, разработчики доступны для общения и стараются сделать всё, чтобы устранить возникающие проблемы.
Мне в этом смысле проще — я сам себе программист и от RadSens мне, по большому счёту, ничего не нужно, кроме прямого выхода RAW импульсов с трубки, а вот как раз этот выход, вроде бы, там работает нормально.
Теперь поговорим о работе с RAW импульсами напрямую, но перед этим ещё немного подробностей о RadSens.
❯ Немного технических подробностей
Начнём с того, что в моём распоряжении имеется RadSens версии 1V7 (в переводе на русский — V7), а в доступности на Гитхабе даташит только для версии 1v6/2v6 (в переводе на русский — RadSens V6/RadSens Mini V6). То есть информация по новым функциям и актуальный список регистров — отсутствуют. Вообще-то так не должно быть: если пользователям продаётся версия V7, то и даташит к ней должен быть доступен.
Чего ещё нет в старой версии даташита я сказать не могу, но очень хотелось бы не гадать, а увидеть даташит на RadSens версии V7, причём с подробным описанием всех реализованных функций.
И пара слов о схемотехнике. На плате имеется 5 интерфейсных контактов, а разъём имеет только 4 пина. По какой-то причине самый интересный пин INT не присутствует в разъёме и сиротливо торчит из-под него, наполовину закрытый пластмассой.
То есть питание и интерфейс I2C можно нормально подключить к сенсору, а INT контакт нужно паять партизанскими методами.
На этом с техническими подробностями пока всё, переходим к программированию работы с сырыми RAW импульсами. (Вообще-то можно сказать ещё много чего, но тогда статья будет похожа на диссертацию.)
❯ Работаем напрямую с RAW импульсами
Итак, мы имеем сенсор, который напрямую (на самом деле не совсем напрямую, но для точного ответа нужно либо видеть схему, либо проводить реверс-инжиниринг платы) выдаёт RAW импульсы с трубки СБМ-20-1. Наша задача заключается в том, чтобы получить эти импульсы в коде прошивки микроконтроллера ESP32 и правильно их интерпретировать (перевести в общепринятые единицы измерения радиации).
Задача не очень сложная: для этого нужно использовать прерывание и простую математику для преобразования количества импульсов за единицу времени в интенсивность излучения (в соответствии с нормированной чувствительностью трубки).
Прелесть этого метода заключается в том, что мы не зависим от встроенного в сенсор микроконтроллера STM32 и того набора функций, которые реализовал производитель сенсора. В этом случае мы можем как угодно интерпретировать импульсы и считать любую статистику (текущий уровень радиации, поисковый режим, накопленная доза и т. п. — всё, на что хватит фантазии).
В тестовом примере я не буду особо изощряться и приведу тут код «proof of concept», просто посчитав количество RAW импульсов за минуту и конвертировав эти данные в значения мкР/ч по приведённой в даташите формуле.
Всем заинтересованным не составит особого труда модернизировать этот пример до сколь угодно изощрённого подсчёта любых радиационно-ассоциированных параметров в своих проектах.
/*
RadSens RAW test
ESP32
*/
#define INT_PIN 25
volatile unsigned long intCount = 0;
unsigned long countOld = 0;
unsigned long timer1m;
boolean cycle1m = false;
void IRAM_ATTR addCount() {
intCount++;
}
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println(F("Start RadSens RAW test..."));
setInterrupt();
delay(1000);
}
void setInterrupt() {
pinMode(INT_PIN, INPUT_PULLUP);
attachInterrupt(INT_PIN, addCount, RISING);
}
void calc() {
unsigned long countM = intCount - countOld;
countOld = intCount;
float rad = (float)countM * 0.57142857; //3600/(105*60)
Serial.print(F(" cpm:")); Serial.print(countM);
Serial.print(F(" rad:")); Serial.println(rad);
}
void loop() {
unsigned long timeSec = millis() / 1000;
if (timeSec - timer1m >= 60) {
timer1m = timeSec;
calc();
}
}
Результат работы нашего скетча. Каждая строка — это данные о количестве импульсов, полученных от RadSens за минуту по RAW каналу и вычисленный по формуле из даташита уровень радиации.
В завершение отмечу ещё одну интересную замеченную деталь: в случае близкого по времени срабатывания нескольких импульсов, RAW канал регистрирует немного большее количество срабатываний, чем «официальный» I2C канал. То есть, чем более интенсивно происходят срабатывания, тем больше «официальный» счётчик отстаёт RAW счётчика.
Если рассматривать вопрос: «а какой счётчик более корректный?», — я склонен отдать пальму первенства именно RAW счётчику: судя по всему «официальный» алгоритм в STM32 «глотает» (не успевает реагировать на) некоторые импульсы при их частом следовании.
Если это так, то возникает парадоксальная ситуация: наш «самопальный» дозиметр на ESP32 будет работать точнее (корректнее), чем сам сенсор RadSens через свой I2C интерфейс.
❯ Заключение
В целом, RadSens можно использовать для измерения уровня радиации, вы (в вашей программно-аппаратной конфигурации) вполне можете и не встретиться с описанными проблемами, но хочется пожелать разработчикам всё-таки найти в себе силы и устранить наконец причины нестабильной работы RadSens.
А также выложить в свободный доступ даташит на актуальную версию V7 и возможно даже открыть схемотехнику и прошивку RadSens для сообщества, что только пойдёт всем на пользу.