
Привет, Хабр! Гроза - захватывающее явление… Раскаты грома, сверкание молний вызывает загадочную палитру чувств и желание понять, как рождается молния, в какой точке неба начинается ее путь и где заканчивается. А что если принять радиосигнал молнии и попытаться его запеленговать? Вот об этом и пойдет сегодняшний рассказ.
Мы могли бы принять участие в готовом проекте Blitzortung, купив у них детектор и разместив его у себя. Но… пошли своим путем.
Приемная часть
Молния - это искра, импульс. Как известно из теории радиосигналов, любой импульс имеет бесконечный спектр. Это означает, что принимать сигнал импульса можно в широком диапазоне частот, вплоть до гигагерц, на которых молнию слышно, но гораздо слабее, а длительность импульса короче, чем на участке от 0 до 30 кГц. Т.е. прием нужно вести именно в этом участке частот - от 0 до 30 кГц. Для этого радиосигнал нужно доставить от антенны по коаксиальному фидеру к блоку оцифровки, обработать в нем и визуализировать.

-
Антенна + малошумящий усилитель + полосовой фильтр (0..90 кГц)
В качестве антенны использовали MiniWhip с фильтром низких частот (ФНЧ) установленным внутри самой антенны. ФНЧ имеет частоту среза около 90 кГц, ниже опускать частоту среза не следует, - зарежем частотный спектр принимаемой молнии, а выше нет необходимости, - будем иметь ненужные данные, которые в ЦОС будут откинуты. Антенна MiniWhip - активная, ей требуется питание для работы. Напряжение питания 12В поступает на антенну по коаксиальному кабелю. По этому же кабелю идет высокочастотный сигнал от антенны, который отделяется от питания при помощи эжектора, и поступает на модуль АЦП. Такие антенны с ФНЧ 0..90 кГц для нас сделал Антон (RA0SMS), спасибо ему огромное!

Антенна MiniWhip. Размещена на своей собственной мачте. Дерево - калина -
Модуль АЦП
На хабре попалась статья, как из недорогого высокоскоростного АЦП AD9200 сделать SDR приемник (https://habr.com/ru/articles/204310/), схема их этой статьи была взята за основу модуля АЦП.

Схема модуля АЦП Несколько модернизировали входную часть АЦП, приведя вход к 50 Ом при помощи трансформатора. 50 Ом - это стандарт, коаксиальные кабели и разъемы имеют такое волновое сопротивление, не внося потери в сигнал. Все должно быть согласовано! Вначале согласующий трансформатор сделали на ферритовом кольце марки 6000НН. Его частотный диапазон, где КСВ был меньше 2.0, составлял от 15 кГц до 1000 кГц - это нас не устроило! Нужный нам частотный диапазон 0..30 кГц с максимумом энергии молнии частично выпал. Заменили этот трансформатор на низкочастотный звуковой ТОТ-4 и согласование с входом АЦП достигнуто!

График КСВ входа детектора с трансформатором ТОТ-4 на плате АЦП. КСВ увеличивается с ростом частоты, и на 37 кГц оно составляет 2.0 Модуль АЦП теперь может принять аналоговый сигнал, оцифровать его и передать на обработку. Когда грозовой фронт близко, в момент мощного разряда, сигнал молнии приводит к переполнению АЦП. При этом АЦП устанавливает бит - “переполнение”. Этот бит нужно передать вместе с данными АЦП.
Получается, с модуля АЦП выходят сигналы:
10 бит данных - 1 сэмпл АЦП
1 бит - переполнение АЦП
-
1 бит - тактовый генератор

Внешний вид модуля АЦП на базе AD9200
Прием данных от модуля АЦП и их дальнейшая обработка
В сигнале с модуля АЦП требуется найти импульс и сохранить его. Этим будет заниматься приемная часть, за основу которой был взят одноплатный компьютер OrangePi One с шиной GPIO

Как будем использовать этот одноплатник:
обработка поступающего от АЦП цифрового сигнала по шине GPIO
детекция молнии и сохранение этого сигнала
веб сервер с админкой и визуализацией сохраненных снимков молний, с возможностью экспорта сигнала на свой ПК или телефон
АЦП AD9200 может тактировать частотой до 20 МГц. Требуется понять, с какой частотой сможем работать по шине GPIO. Пробовали:
написать модуль ядра на прерываниях - очень медленно
работа с sysfs - медленно
библиотека wiringOP - быстро
Из готовых решений можно взять только wiringOP. По нашим замерам, она справляется примерно с 200 кГц, но нам нужно быстрее. Да и библиотека заточена под управление пинами по отдельности. А нам нужно использовать 10 пинов как набор бит одного числа. Поэтому спускаемся в недра документации на процессор и ищем разметку памяти GPIO и пишем свою реализацию работы с пинами.
С GPIO работаем напрямую, читая и записывая память ОЗУ, через /dev/mem. Это позволило нам считывать за раз 4 байта, биты которых показывают, в каком состоянии находится пин. За одно такое считывание мы получаем 10 бит АЦП, 1 бит переполнения АЦП и 1 бит PPS с GPS модуля. Чтобы получить все данные с модуля АЦП за одно считывание, требуется использовать один чип GPIO. Мы выбрали GPIO A, - на плате большая часть ножек с него, на изображении ниже выделены красным.

Проверка скорости шины GPIO
А как же проверить скорость шины GPIO? Потребуется две программы:
ПЛИС. На языке Verilog HDL была написана простая программа для ПЛИС. Программа с заданной нами частотой увеличивает число (от 0 до 1023) и выводит его на свои пины
OrangePi One. Программа на C++, в цикле без пауз считывает состояние шины GPIO. Формирует из бит шины число и сохраняет в массив. После нескольких секунд работы цикл прерывается. В консоль выводится записанный массив чисел.
Соединяем пины ПЛИС с шиной GPIO платы OrangePi One. Запускаем программы.

Таким образом, если мы обнаруживали, что числа пропускаются (например в выводе консоли 1, 2, 5, 6, 8, 9), то мы понимаем, что частота смены числа в ПЛИС высокая. Если значения идут четко друг за другом (1, 2, 3, 4, 5) без пропусков, значит мы идем на пределе. И вот только когда мы видим повторения чисел (1, 1, 2, 2, 2), мы понимаем, насколько быстрее генератора ПЛИС мы считываем шину GPIO. При частоте смены числа в 1 МГц, мы видели повторения каждого числа по 4-6 раз. Это означает, что наш цикл в пять раз быстрее генератора ПЛИС и точно не пропустит смену состояния тактора АЦП.
Поэтому мы выбрали частоту генератора АЦП 500 кГц. Это дает нам понимание, что мы считываем 10 бит данных правильно без ошибок, при этом успеваем рассчитывать динамический порог срабатывания детектора, и сохранять сигнал. В нашем подходе есть нюанс: загрузка одного из четырех ядер процессора OrangePi One всегда составляет 100%
Прием и обработка данных модуля АЦП
Модуль АЦП подключен к шине GPIO. Он передает на одноплатник следующие данные:
Сигнал тактового генератора 500 кГц. В ПО ждем спад фронта этого сигнала на пине GPIO. По спаду фронта данные АЦП готовы для считывания
10 бит данных АЦП - каждый бит подключен к своей ножке GPIO
1 бит переполнения АЦП
Детектирование импульса программное. В непрерывном потоке данных на лету рассчитываем уровень шума на основе доработанного под наши задачи алгоритма EMA (экспоненциальное скользящее среднее)

Синим на графике выше обозначен сигнал, поступающий от АЦП, а зеленым - рассчитанный уровень порога. Здесь срабатывания нет, потому что сигнал имеет повторяющуюся помеху, а порог не успевает опуститься из-за нее.

Когда поступает импульс, динамический порог не успевает вырасти, происходит срабатывание детектора. В этот момент сохраняем сигнал и показываем его в админ панели.
Система синхронизации по времени
Для определения места удара молнии используется метод TDoA (Time Difference of Arrival). Этот метод требует точных координат места и времени приема сигнала каждым детектором в сети. Чтобы получить точное время приема и координаты детектора применяем навигационный модуль с сигналом PPS (Pulse Per Second).

После того как навигационный модуль захватил сигнал со спутников и рассчитал внутреннее время, на его выходе появляется сигнал PPS. Этот сигнал поступает на GPIO OrangePi One. Считывая этот сигнал мы получаем достаточную точность синхронизации между детекторами (погрешность всё равно велика, но это лучше, чем просто брать системное время)



WEB-консоль
WEB-консоль (она же админ-панель) предназначена для просмотра сигналов, которые принял детектор.

Что в ней можно делать:
просматривать принятые сигналы
применять к сигналу ФНЧ 35 кГц
видеть состояние OrangePi One (загрузка CPU, место на диске, состояние RAM)
обновлять ПО детектора
перезагружать детектор
сохранять понравившийся сигнал в формате JSON на свое устройство (например, чтобы поделиться с другими ловцами молний)
загружать сигнал в формате JSON от другого ловца молний в админ-панель (чтобы полюбоваться)


Детектор
Осталось собрать все воедино, для этого нужен корпус. Проще всего сделать корпус - напечатать его на 3D принтере. Первый блин корпус, как всегда, комом.

При разработке корпуса нами были допущены ошибки:
тонкие стенки
не все отверстия были предусмотрены
неудобная сборка
не предусмотрено место для БП


Однако все время что-то нам не нравилось. Решили обратиться к Владимиру (инженеру по моделированию и 3D печати). Он нам здорово помог. В итоге получился вот такой красавец:


Теперь корпус нам нравится. Что мы получили:
сборка превратилась в конструктор
БП внутри, нет лишних блоков снаружи
хорошее охлаждение стабилизатора
приятный внешний вид

Заключение
Таким получился наш путь от идеи "поймать радиосигнал молнии" в реальный, работающий девайс. Планы на будущее:
применить нейросети для классификации сигналов молния/не молния
добавить в WEB-консоль возможность прослушивания свистящих атмосфериков
попробовать применить магнитную ферритовую антенну
добавить в детектор управление внешними устройствами через реле (например, чтобы обесточить важный объект при близкой грозе)
-
написать сервер для:
отображения сети детекторов на карте
расчета координат молний (пеленгация методом TDoA)
рассылки уведомлений о грозе рядом
сбора статистики и данных для исследований
Но это уже в следующих тактах жизненного генератора.
Для желающих собрать такой детектор и присоединиться к приему молний прикладываем репозиторий: https://gitverse.ru/atribolt/raskat-detector В репозитории есть:
гербер-файлы для самостоятельного заказа платы модуля АЦП
проект “PCAD 2006” (схема, плата и библиотеки)
инструкция как установить ПО детекции и WEB-консоли на OrangePi One
Комментарии (23)

NutsUnderline
20.11.2025 09:34Это все настолько прекрасно насколько и ужасно. Высокоскоростной АЦП но на частоте дискретизации 500кГц 10 бит (я не ошибся?) который оцифровывается по заветам проца 8080, считывая gpio, даже без DMA. В то время когда в микроконтроллеры легко имеют 1-2 АЦП 12 бит на 1 или 5 МГц. Я точно правильно понял это материал?

RN3KK Автор
20.11.2025 09:34Микроконтроллеры неудобны когда речь заходит о хранениии данных, о ТСР стеке, о веб сервере. В одноплатнике все есть что нам нужно.

NutsUnderline
20.11.2025 09:34да я догадывался об этом, но есть же stm32f4 с ethernet
просто не могу слышать что одно ядро загружено на 100% все время, постараюсь это "развидеть" :)

RN3KK Автор
20.11.2025 09:34В чем тут проблема? Ничего не перегревается. Температура в норме. Система простаивает и ничего не делает кроме этого цикла.

NutsUnderline
20.11.2025 09:34В чем тут проблема?
да можно
и долларами камин топить, микроскопом гвозди забиватьв одноразовый вейп stm32 с экраном ставить:) Если цена сопоставима, речь про масштабируемость не идет, а работает нормально - почему бы и нет. Просто, несбалансированное решение, если че то допиливать это может аукнуться.
RN3KK Автор
20.11.2025 09:34Не нужно бояться цифры в 100%. Это показатель того что это ядро занято на 100% времени и система не может его использовать. Даже если применить STM, потребуется: добавить microsd для хранения сигналов, добавить построцессинг для отправки данных на сервер, не понятно как удаленно обновлять прошивку ( тут же обновление идет через наш репозиторий), нет полноценного стека TCP/IP из коробки. Ну и тп. Т.е. как ни крути STMу рядом для удобства пришлось бы ставить тот же самый одноплатник. От чего ушли, туда же и приходим.

d_nine
20.11.2025 09:34Ну вы же не гигабайтами данные храните + выгрузка на сервер. Обновляться можно так же по сети/UART/microsd. Одноплатник все же дорого для такого детектора. Причем одно ядро которого фуллтайм занято, я бы понял если бы детекции была мало ощутимой фоновой нагрузкой. Для массовости стоит упростить и удешевить решение.

RN3KK Автор
20.11.2025 09:34В stm32 тоже ядро занято, все время крутится цикл. Просто нам не показывают его загрузку нигде, "собака не видит, не лает". Тут же мы видим загрузку, все о чем нам это говорит: ОС, не используй это ядро, оно занято, у тебя есть еще 3 не нагруженных, помещай процессы в них. Не понимаем почему рекомендуя stm32 или иной микроконтроллер забываете, что там аналогичный цикл.
Мы открыты, покажите своим примером "как правильно". Будем опираться на Ваш опыт! Этого нам не хватает. Подсмотреть пока негде.

NutsUnderline
20.11.2025 09:34ядро занято, все время крутится цикл
именно что не лает, но и в дом не пускает - это у плохих програмистов :) так то никто не запрещает но как минимум для этого есть dma а проц занимается более сложным нежели байты перебрасывать. проблемка что на одноплатниках как правило на низкий уровень типа DMA особо и документации нету, но есть пример как решали на малинке (там тоже до регистров опустились).
При этом например любой SDR делает по сути тоже самое, только с манипуляцией ПЧ и на более высокой скорости (полосу хочется побольше), плюс IQ-магия. Тут обычно хотят большие мегагерцы. Однако для более узкой полосы есть даже пример на проце 6502 (вот там то ядро загружено! наверное), https://github.com/AndersBNielsen/PhaseLoom но и то автор опомнился и сделал АЦП на STM32F103 https://github.com/AndersBNielsen/PhaseLatchMini.
А для stm32 решения чуть ли не штатные, гуглом думаю несложно найти "ADC DMA STM32" - вот немного не то но почти https://habr.com/ru/companies/ruvds/articles/694640/ https://habr.com/ru/articles/543686/ https://habr.com/ru/articles/468393/ https://habr.com/ru/articles/588594/. более того - можно так не только STM но и другие контроллеры, включая отечественные
я ни в коем случае не предлагаю бежать переобуваться, но обозначить альтернативы наверное стоит

atribolt
20.11.2025 09:34именно что не лает, но и в дом не пускает - это у плохих програмистов :) так то никто не запрещает но как минимум для этого есть dma а проц занимается более сложным нежели байты перебрасывать
Вы так и не сказали, что плохого в том, что процессор работает. Ниже картинка нагрузки на одноплатник. Одноплатник не греется, ресурсов достаточно.

Загрузка одноплатника Дополнительно можем запускать стрим сигнала с ФНЧ и децимацией (все в одном ядре) с удаленного детектора к себе на ПК. И вот уже пара ядер в сотку. Но одноплатнику все еще норм. У него целых 2 ядра простаивает, температура не растет.

Стримминг сигнала с удаленного детектора, с одновременным отловом молний

tklim
20.11.2025 09:34Трансформатроный БП с линейным стабилизатором в 2025 ? монструозно. Хотя, реально все впихнуть внутрь "антенны", на базе микроконтроллера со встроенным ацп, ethernet и запитать через PoE.
Даже если очень хочется линукса - почти тоже самое, *PI-SBC + SPI-ADC + PoE.
Кстати, как чтение gpio реализовано? userspace или драйвер ядра ?
какое поличество семплов получается относительно периода PPS? стабильное значение или разброс ?
NutsUnderline
20.11.2025 09:34так написано же
С GPIO работаем напрямую, читая и записывая память ОЗУ, через /dev/mem

tklim
20.11.2025 09:34исходников нет, но судя по тому что есть - userspace. Неудивительно, что загрузка 1 ядра 100% и разброс 25мкс при синхонизации по времени.

atribolt
20.11.2025 09:34Трансформатроный БП с линейным стабилизатором в 2025 ? монструозно
Зато шумит меньше
Хотя, реально все впихнуть внутрь "антенны", на базе микроконтроллера со встроенным ацп, ethernet и запитать через PoE
Всё так, у нас не было такой цели
чтение gpio реализовано? userspace или драйвер ядра
userspace, лезем через /dev/mem. Пробовали писать драйвер ядра на прерываниях, получили в районе 100 кГц. Знаем, что можно быстрее, не хотелось с этим возиться, Если уж писать драйвер для такого, проще уходить на МК
какое поличество семплов получается относительно периода PPS? стабильное значение или разброс
Конечно разброс есть, так как нынче GPS поддавливают и на него сложно полагаться. А модуль свой PPS рассчитывает исходя из фиксации со спутниками и коррекцией времени по ним

Сеплы между PPS (ticks), длина импульса до спада сигнала (ticks down) 
Вывод работы модуля ядра pps-gpio 
tklim
20.11.2025 09:34Зато шумит меньше
У вас, судя по схеме, питание АЦП берется от от 3.3в gpio апельсина. Там, так-то тоже импульсный преобразователь. Ну и сама плата SBC тоже может шуметь во всех диапазонах.

RN3KK Автор
20.11.2025 09:34Не реально впихнуть все внутрь антенны.
антенна принимает сигналы до 90кГц
преобразователи питания (которые обязательно есть в POE) работают на частотах до 200кГц и частота можем меняться и быть не стабильной, т.е. мы антенной будем принимать свой преобразователь (более того, антенна слышит чужие РоЕ преобразователи находящиеся вдали от нее, например от видео камер, что будет если такое поставить прямо рядом с антенной - жуть)
добавляются требования к витой паре, потому что она начинает быть излучающей сигнал антенной, так как РоЕ преобразователь будет давать сигнал в нее и она будет его излучать, экранирование витой пары поможет, но насколько именно ослабит - нужно делать замеры
сама связь по Ethernet тоже дает поле вокруг витой пары, и его мы тоже примем антенной, тут частоты пошире, до мегагерц сигналы летят, потому является проблемой
Выводы очевидны: простыми способами разместить все на антенне довольно сложно.
Tirarex
AS3935 не смотрели? Готовый модуль с ним стоит 15$, под капотом определением расстояния до молнии и i2c/spi шина.
RN3KK Автор
Смотрели. Не понятно как фиксировать время для алгоритма TDoA. + хочется поэкспериментировать с антеннами.
RN3KK Автор
нет понимания каков алгоритм?