Альтернативное ПО (FW) для счетчика Гейгера от RadioHobbyStore.

Это не первый (и не последний) из моих «радиолюбительских» дозиметров. Мысль необходимости создания адекватной прошивки для него родилась фактически с момента его первого включения после сборки. Автор данного устройства, вполне неплохо конструктивно (не схемотехнически) спроектированного – по недоброй но почти традиции всех PIC-программистов зажал исходники примитивненькой прошивки, видать стыдно показывать было …

Однако возвращаться к программированию PIC-контроллеров, с которых я когда-то (20-лет назад) начинал знакомство с контроллерами – не очень хотелось … Но тут выдались свободные деньки и появилось желание все же довести до ума и работоспособно-юзабельного состояния сей дозиметр.

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

 

На чем писать код? Конечно же на Си! А что заморачиваться? – скачиваем последнюю MPLABX (5.35) и к ней free-версию компилятора xc8 (2.10). Аналогичный контроллер pic16f628a нашелся новый в моих запасах. Да, как выяснилось позже у него слишком мало памяти программ (всего 2k инструкций), а сишный компилятор генерирует весьма объемный код даже на целочисленной арифметике (с учетом 8-битности контроллера), «плавающую» арифметику вообще лучше не трогать. Благо можно обойтись псевдо целочисленной даже на операциях деления и умножения на дробные константы (это требует меньше памяти, хоть и выглядит громоздко). Заменить контроллер? – навскидку у меня не оказалось PIC-контроллера в подобном корпусе (DIP-18) и с памятью, более 2k (хотя есть, например, 16f88 с 4k инструкций или 16f1847 даже с 8k).

Пишем код: изобретать велосипед с нуля или … PIC контроллеры умерли и фактически канули в лету (в отличии от ардуины, продолжающей жить и развиваться) уверен в первую очередь из-за отсутствия поддержки комьюнити. Для ардуины куча библиотек описывающих функционал и протоколы работы почти с любой периферией! Куча готовых примеров, также в сети немало готовых описаний (в том числе русскоязычных) и обсуждений нюансов программирования в Arduino IDE, документация на официальном сайте Ардуино чего только стоит! Для PIC-контроллеров ничего подобного даже близко нет! Даташит на контроллер – и ВСЕ! (благо на некоторые контроллеры, в том числе на 628-ой есть русскоязычные переводы). Ни то что библиотек, примеров-то не найдешь почти толковых! Почти каждая сука пишущая код под PIC считает (т.е. считала – т.к. все это более чем 10 летней давности) чуть ли не святым долгом распространять к радиолюбительским поделкам на базе таких контроллеров только скомпиленный бинарник (без исходников)! Типа – собираешь схему и прошиваешь контроллер как черный ящик … а «горшки обжигать» – удел богов, не иначе (как можно подумать). Тем не менее кривые ошметки (иначе не скажешь) кода найти все же можно, только большинство из них под различные (а их не мало было) древние компиляторы, и даже не просто так, а с пониманием, их порой в новой среде сразу так и не соберешь. Можно найти примеры к книгам – или, так сказать «цитаты» кода из этих примеров кочующие по веткам разных форумов в виде сухих ответов на разумные вопросы. Интереснее оказалось другое: что кусок кода инициализации дисплея LCD1602 (двухстрочного, 16-ти символьного) упорно копируемый и приводимый на многих ресурсах неработоспособен сам по себе в принципе из-за маленьких, но важных нюансов. Т.е. те бездари которые мнят из себя гуру, надувая на форумах щеки, не то что не компилировали подобный код, а даже близко не программировали такие дисплеи на низком уровне! Вобщем пришлось писать правильный код по даташиту на контроллер дисплея (HD44780 иже с ним) для верности отлаживать его на ардуине – сишный исходник он почти везде одинаков (что радует). Короче оказалось, что программить для PIC на Си в среде MPLABX под xc8 – почти тоже самое что писать низкоуровневый код для ардуино без библиотек – т.е. именно изобретаем велосипед почти с нуля.

Так вот к нашим баранам, а вернее к дисплею.  Дисплей LCD1602 (с контроллером, совместимым с HD44780) предусматривает несколько вариантов подключения интерфейса для взаимодействия с ним и требует от 11 (максимум) до 6 (минимум) ног управляющего контроллера (не считая ног питания, контрастности и подсветки). И если в большинстве случаев использование четырех-битного интерфейса является вполне оправданным с точки зрения быстродействие (о котором тут собственно речь вести вроде как странно), но не с точки зрения компактности кода, кстати – то вот отказ от линии R/W обоснован лишь в случае крайнего дефицита ног управляющего контроллера! Понятно, например, что в Arduino UNO ног «не густо», а периферии на одну плату вешается иногда много (ну или такой возможности пользователя не хотят лишать) – там R/W вешают на землю (исключая возможность чтения информации с модуля дисплея) и экономя 1 ногу. В случае же рассматриваемого дозиметра свободная нога есть! (висит в воздухе) – почему бы автору было не завести на нее сигнал R/W?

А фишка тут в следующем: собственно читать из дисплея особенно то и нечего, за исключением флага готовности к приему следующей команды. Разные команды дисплей выполняет за разное количество времени. Предусмотрено (документацией) что мы будем считывать состояния флага, чтобы точно знать когда можно посылать следующую команду. Если мы вешаем R/W на землю (экономя ногу) и лишаемся возможности анализа флага, то обязаны ждать максимальное время выполнения для каждой из команд к контроллеру дисплея (все что мы попытаемся «скормить» дисплею раньше, чем он будет готов – он просто проигнорирует). И все бы ничего – большинство команд выполняются весьма быстро (37мкс), алгоритмически на формирование новой команды может уйти больше времени, а инициализационную последовательность с заданными (длинными) таймингами посылаешь вообще единожды … Да вот команда очистки дисплея, применяемая регулярно, выполняется до 1520мкс (согласно документации)! Очень многие примеры кода для PIC-контроллеров не учитывают этого из-за чего неработоспособны как факт; также как многие, внезапно, забывают включить дисплей после инициализации … Вобщем не смешно совсем ;-)

С дисплеем разобрались, можно использовать код и в будущем ;-) С таймером и счетчиком импульсов на входе все намного проще. Правда длительные интервалы времени даже 16-битный счетчик все равно считать не позволяет (8-битный максимум ~15Гц, 16-битный – ~2Гц), т.е. даже секунду чисто-счетчиком не отмеряешь. Посему закрутил счетчик на 10Гц (для ровного счета) и отмеряем секунды им. Импульсы же от трубки гейгера-мюллера считаются по другому прерыванию независимо. «Приятное с полезным» сводится незамысловатым программным способом в бесконечном цикле – в нем же по мере обновления данных происходит и перерисовка экрана.

В стоковом примере реализации дозиметра автор не мудрствуя ни капли по тупому реализовал подсчет за 10сек с последующим умножением результата на 6. Топорно – слов нет! Конечно на больших числах оно и так сойдет, но при маленьком фоновом уровне радиации видеть всегда показания исключительно кратные 6 … извиняйте «мовитон» (6-12-18-24-…. и ничего другого)

Думал как правильнее организовать подсчет импульсов … И с учетом логики измерения и с учетом возможной программной реализации. В результате реализовал имхо единственным алгоритмически правильным способом. Т.к. единица измерения CPM предусматривает именно подсчет частиц (импульсов) за минуту, то правильнее всего, несомненно, и вести подсчет именно в этом интервале времени (т.к. равномерность в течение интервала вовсе необязательна). Но получать только раз в минуту обновленную информацию (новое показание) это скучно и неудобно, хоть и максимально точно. Поэтому решено сделать следующим образом. Минута условно разбивается на интервалы, например 2 секундные – которых получается 30 (как в версии 20.05). У нас есть циклический буфер (массив) в который мы поэлементно заносим количество импульсов накопившееся в течение каждого интервала за последнюю минуту. Таким образом, по прошествии минуты и далее каждые 2сек мы можем легко подсчитать актуальный CPM за последнюю минуту просто сложив все элементы массива. Но в первую минуту у нас нет достаточного количества информации. Можно конечно заставить пользователя подождать, как делают некоторые модели профессиональных дозиметров – но можно и эмпирически рассчитать CPM на основании уже поступивших данных. Т.е. после первого 2сек интервала его результат нужно умножить на 30. По прошествии 4сек – суммируем показания первого и второго интервала и умножаем уже на 15, далее суммируем показания трех интервалов и умножаем на 10 … И хоть с каждым интервалом в течении первой минуты точность увеличивается, мы подсказываем пользователю (в моем случае отображая символ звездочки) что информация не точная, а расчетная. Лишь по прошествии 60сек у нас есть информация за всю предыдущую минуту и мы рассчитываем истинный CPM (звездочка уже не рисуется). Количество импульсов подсчитанное в следующем 2сек интервале будет циклически переписывать самые старые из оставшихся данных.

Далее чтобы сконвертировать значение из расчетной величины CPM в системную uSv/h (мкЗв/ч – «микро зиверт в час») нужно произвести незамысловатую математическую операцию, воспользовавшись так сказать «табличным коэффициентом» для конкретной (используемой в качестве датчика) трубки гейгера-мюллера. Для СБМ20 – это 150. Т.е. CPM равный 150 (150 импульсов в минуту) соответствует 1 uSv/h. (Для перевода в «микро рентген в час» результат нужно еще разделить на 10 – т.к. мкР/ч в 10 раз «более крупная» величина, чем мкЗв/ч). Для других трубок коэффициенты могут быть другими, так же как и для конкретной трубки при различных источниках излучения коэффициент может (должен) незначительно корректироваться (для пущей точности).

Конструкция устройства имеет dil-преключатель. В моем ПО я использовал его для выбора одного из двух режимов отображения информации на дисплее: отладочном (ON) и основном. В основном режиме мы видим показания в CPM (первая строка) и в мкЗв/ч (вторая строка). В звездочка в течении первой минуты указывает на возможную неточность результата. В отладочном режиме (можно переключаться неограниченно в любое время) в первой строке дополнительно отображается счетчик секунд с момента включения устройства, а также (в квадратных скобках) количество пришедших импульсов в текущем 2сек интервале (по-прошествии которого это число ложится в соответствующую ячейку буфера). Помимо этого, в течении 2сек из 10-ти, показание второй строки меняется от «мкЗв/ч» в «мкЗв» – т.е. отображает полученную (накопленную) дозу с момента включения устройства (без привязки ко времени), что может быть актуально для осуществления замера в течении суток, например.

Остались неиспользованными 3 порта (3 ноги) контроллера, выведенные наружу (помеченные как RX, TX и Line) – полезного функционала я им навскидку не вижу (ровно как и дублирование стокового). Да и для реализации любого функционала нужна свободная память программ в контроллере (а в данном случае это дефицит). Хотя можно конечно в принципе припилить пользовательский интерфейс в виде кнопок или ИК-приемника, или реализовать I2C шину на которую повесить и календарь и память для накопления статистики – но все это уже явно выходит за пределы платы и может лишь изящно эксплуатироваться в рамках соответствующего корпуса (а не на весу). Поэтому если рассматривать данный дозиметр как законченное техническое решение, то все это не в тему.

Исходник прилагается ;-)

MiGeRA (апрель-май 2020)

Заглавная » Радиоэлектроника » Радиметрия - радиолюбительские дозиметры » Альтернативное ПО (FW) для счетчика Гейгера от RadioHobbyStore.