Обновить

Комментарии 33

Хороший проект. Успехов!

🤍

А вы не рассматривали более классические реализации? События, которые будут доступны к обработке в Userspace через input-подсистему? АЦП, читаемый через industrial-input-output? В первом приближении сильно меньше велосипедов и проще сопровождать?

Нет, то, о чем вы говорите, я даже не рассматривал. Сначала я подумал, что речь про отправку команд по SPI через ioctl, но, кажется, это что-то совсем другое, я обязательно про это прочитаю. На первый взгляд, input-подсистема включает примерно те же вещи, что я пытался внедрять в свой модуль, например, на ранних этапах я пробовал скачивать буфер данных из ядра через "файл" в /proc.

Примерно так. input позволит прикинуться кнопкой на клавиатуре со специфическим кодом (типа F13 или Macro), по нажатию на которую можно будет запустить цикл чтения. А iio специально создана для работы с промышленными датчиками (ускорение, химия, давление, АЦП и им подобными). Правда если с input все просто - штатный драйвер gpio-keys, то с iio возможно придется написать драйвер для вашего АЦП. Не уверен что он есть в ядре. Но это не сложно - примеров с реализацией море.

Главный вопрос хватит ли времени реакции. Ибо у вас всё в ядре, а тут будет весьма часть в userspace. За то переносимость и независимость от конкретной микросхемы. Ну и штатный интерфейс - соответственно основной код в userspace.

Я бы сделал плавное ресемплирование с фиксированной частоты АЦП на нужную нам частоту отсчётов с помощью табличного интерполятора. Имея в распоряжении Raspberry Pi таблица может легко вмещать не 600 значений, как у АЦП в вашем варианте, а, скажем, 600 тысяч наборов коэффициентов. Т.е. плавность подстройки задержки и синхронизации частот может быть в 1000 раз лучше.
Принцим работы такой:

  • вычисляем требуемый сдвиг по времени для текущего отсчёта

  • выбираем соответствующий этому сдвигу набор коэффициентов из нашей таблицы

  • применяем КИХ фильтр с примерно 30-ю коэффициентами

  • получаем исключительно плавно перестроенную частоту отсчетов

Интересно, спасибо! Насколько я понял, не нужно настраивать регистр DRATE в АЦП: частота АЦП при включении 30 кГц и мы ее не трогаем. Перестроиться на любую частоту можно буквально одной командой (у меня так сделать нельзя, всё жестко прописано). Технически, можно даже определять точное время каждого импульса, GNSS-приемники дают такой функционал (раздел 14. Timemark). Я, получается, в своей работе пошел от обратного, я сначала настраиваю GNSS-приемник на импульсный сигнал определенной частоты, а уже он управляет преобразованием. Я так могу легко сопоставлять между собой записи с разных регистраторов, даже удаленных друг от друга, и они реально работают синхронно (не знаю, смогу ли опубликовать пост, как проверяю синхронность).

Да, частота отсчётов АЦП остаётся фиксированной, мы никак не меняем его режим работы. Имея точное время отсчёта АЦП от GNSS, можно прямо вычислять и брать нужный набор коэффициентов из таблицы.
Есть несколько нюансов как рассчитать такую большую таблицу. Основной из них - необходимо использовать интерполяцию исходного КИХ фильтра 30-го порядка в 600 тысяч раз с помошью ДПФ вместо вычисления "в лоб" КИХ фильтра порядка 30 * 600000 = 18 миллионов коэффициентов.

Для частоты 50 Гц нужно сделать 600 таких усреднений.

а нельзя сделать 100 усреднений, а дальше усреднять уже в драйвере?

600 усреднений делается внутри микросхемы, нужно просто дискретизацию увеличить, на частоте 500 SPS их будет уже 60. Я примерно о таком и пишу, что да, можно после строба SYNC получить несколько значений на более высокой частоте, и усреднить их уже программно. Но мне не нравится этот путь, поскольку АЦП и так должен выплюнуть готовое значение, которое не нуждается в постобработке. А я хотел бы в перспективе подключать к одному АЦП несколько разных датчиков, код тогда будет совсем перегруженным. Лучше, конечно, устранить первопричину помехи, а не пытаться под нее приспособиться.

Но мне не нравится этот путь, поскольку АЦП и так должен выплюнуть готовое значение, которое не нуждается в постобработке.

Насколько я знаю это не очень правильный путь - руководствоваться тем что нравится/не нравится. Надо руководствоваться тем что работает/не работает и как работает и почему не работает.

Честно говоря из статьи мне не очень понятно как у вас система работает поэтому очень сложно что-то предложить. Как то сумбурно все начинаем с микросхемы АЦП, потом вдруг перепрыгиваем на драйвер SPI. Как связаны времена обращений по SPI с временами запуска АЦП если и написано - я не смог понять. Еще не понятно что вы имеете ввиду под тактированием АЦП - настройку моментов запуска преобразований или внутреннюю работу АЦП. То есть не то чтобы совсем не понятно - есть подозрение что там что-то напутано, потому что изложение местами выглядит как обрывки логики, а не полная логика.

Еще вроде вообще ничего не написано о моменте завершения АЦП и готовности данных очередного семпла, а это обычно ключевой параметр времени, по которому и строится вся логика синхронизации драйвера и устройства.

Как связаны времена обращений по SPI с временами запуска АЦП

Начать стоит с того, что при включении АЦП она работает на базовой частоте 30,000 SPS, нужно записать в регистры новую частоту, аналоговые входы для считывания, PGA.

Картинка номер 2, SYNC - это вход микросхемы, DRDY - выход. Пока DRDY в 1 - идет очередное преобразование, его результат извлекается после смены уровня на DRDY. Параметры SPI соединения нужно настроить заранее, отправляется команда RDATA (это всего 1 байт 0х01), после этого нужно подождать, пока АЦП по SPI вернёт 3 байта. На этом базисе основан код, который я предлагаю в статье.

SYNC - это вход микросхемы, DRDY - выход. Пока DRDY в 1 - идет очередное преобразование, его результат извлекается после смены уровня на DRDY.

вот так вот намного понятнее! Следующий шаг - надо понять как у вас формируются импульсы на SYNC. Там целых 2 параметра: частота импульсов и период отдельного импульса, как вы их задаете, как вы ими управляете? Далее надо понять сколько времени занимает чтение сэмпла по SPI и определиться с логикой контроля чтобы это время не превышало времени экспозиции очередного значения АЦП, соответственно надо понять как у вас определено время экспозиции и как это время накладывается на очередное преобразование...

Я подозреваю что у микросхемы АЦП есть и автоматический режим само запуска очередного АЦП после завершения предыдущего АЦП вы не пробовали такой режим включать-использовать если он конечно есть?

То что у вас в конце написано тоже довольно сумбурно выглядит как попытка самостоятельно вывести теорему Котельникова-Найквиста. Любая такая попытка может быть достаточно интересной, но, по моему, лучше просто прочитать и разобраться в уже существующей теории в этом направлении, я поэтому и особо вникать в конце не стал так как вы пытаетесь изобрести какую-то новую формулировку известной проблемы, придумать какую-то новую терминологию, а я предпочитаю классический вариант.

частота импульсов и период отдельного импульса, как вы их задаете, как вы ими управляете?

50 Гц частота SYNC и период импульса 1 мкс, это есть в статье. Вы точно читали текст?

чтобы это время не превышало времени экспозиции очередного значения АЦП

Эх, новое преобразование не идет, пока не извлечешь данные, об этом я тоже писал.

вы не пробовали такой режим включать-использовать

Попробовать можно.

То что у вас в конце написано тоже довольно сумбурно выглядит как попытка самостоятельно вывести теорему Котельникова-Найквиста

А чего вы не процитировали, как вы это обычно делаете, что я чего-то нового вывожу? Мне тоже любопытно посмотреть, где это у меня в тексте.

50 Гц частота SYNC и период импульса 1 мкс

числа я заметил в статье, вопрос откуда они у вас взялись и что с ними можно делать. А это:

Далее надо понять сколько времени занимает чтение сэмпла по SPI и определиться с логикой контроля чтобы это время не превышало времени экспозиции очередного значения АЦП, соответственно надо понять как у вас определено время экспозиции и как это время накладывается на очередное преобразование...

вам видимо не о чем не говорит, ну и ладно.

Обратите внимание, что сигнал SYNC должен быть согласован с CLKIN. От этого вполне могут быть помехи или неправильная работа АЦП, что и дает вам выбросы.

Хм, у меня в документации только указано, что синхронизация случится на первом же такте CLKIN, после того, как SYNC перейдет из 0 в 1, т.е. как будто требование не такое жесткое. Но это интересный момент, можно его поисследовать.

с одной стороны, "это просто офигительно" - по уровню.

с другой стороны - если речь идет об солнечных батереях и 150-500м то малина с линуксами здесь лютый оверинжииниринг. Для этого есть esp32 и подобные микрухи, и радиоканал по ble lr и lora

с третей стороны - Минпромторг данному НИИ дозволил закупать импортные микросхемы? Импортозамещение наше все, даешь RepkaPi ;)

тут кстати еще одни товарищи недавно публиковали про свою распределенную сеть сенсоров https://habr.com/ru/articles/957828/

Минпромторг данному НИИ дозволил закупать импортные микросхемы?

Пока что да) Но скоро лавочку прикроют, действительно.

НИИ не в ведении минпромторга. Тем более что работы скорее всего по внебюджетному финансированию.

импортные микросхемы? Импортозамещение

В RepkaPi только плата своя, Allwinner ещё не импортозаместили. Но это-то ладно, можно на ВЕ48 систему сбора данных сваять. А вот 24-х битный АЦП сильно сомневаюсь что можно импортозаместить, а если и так, то цена будет кусачая.

Сигма дельта АЦП синхронизировать идея так себе, потому что это сброс цифрового фильтра и в результате измеренное напряжение - это некое среднее значение между t0 + N/Fs и t0 + (N+1)/Fs, где N в зависимости от фильтра около 3, 4, 5.

Хотя есть, например, ads1263 где это аккуратно внутрь всё спрятано и есть режим одиночного преобразования по дерганию за отдельную ногу START, и 1cycle settling фильтры.

Но имхо правильнее запустить АЦП в непрерывном режиме, а таймером в МК захватывать когда именно дергался DRDY и когда прилетал PPS, а потом сделать передискретизацию в нужные моменты времени

https://ru.dsplib.org/content/resampling_lagrange/resampling_lagrange.html

Благодарю за инфу! Мне тоже больше нравится такое решение, когда АЦП живет своей жизнью, а время каждого преобразования вычисляется внешними средствами, Я уже писал в комментариях, что GNSS может измерять время внешнего сигнала, таким сигналом как раз может быть флаг готовности DRDY. Конечно, чтобы потом сводить данные с разных регистраторов, придется лишний раз делать интерполяцию, но это уже не так страшно.

Какой лютый оверхед если юзать линух

Разрядность АЦП не менее 24 бит, чтобы за счет широкого динамического диапазона наблюдать едва заметные сигнальчики.

"не менее" - круто, 3 V делить на 16 777 216 - разрешение не менее 1/5 микровольта. Нет смысла хвататься за малинки и линуксы, если у вас нет готового аналогового модуля, который это может и вы можете его пусть не поверить, а хотя бы проверить на аналоговом стенде. Аналоговая и цифровая земля должны быть правильно разделены, должен быть экран для модуля, общий экран для модуля и датчика, потом земли, экраны, питание и spi интерфейс должны быть правильно соеденены. Spi должен заходить так, чтобы не вносить шум и т.д и т. п. Вся остальная цифра должна быть снаружи. Нельзя вот так просто взять и собрать устройство с разрешением 1/5 микровольта.

В работе, кстати, готовая плата используется, ссылка. Да, кстати, решение было довольно спонтанное и не самое обдуманное, гнаться за разрядностью не стоило. Шумы самого датчика (не считая помехи, описанной в статье) с лихвой перекрывают эти микровольты. Я лишь показываю, что АЦП может цифровать без дополнительной помехи, но почему-то этого не делает в режиме синхронизации от внешнего источника.

 ...гнаться за разрядностью не стоило. Шумы самого датчика (не считая помехи, описанной в статье) с лихвой перекрывают эти микровольты. Я лишь показываю, что АЦП может цифровать без дополнительной помехи, ...

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

Нельзя вот так просто взять и собрать устройство с разрешением 1/5 микровольта.

боромир.jpg

С одной стороны как бы да, просто два разных куска меди не из одной катушки вполне могут дать до 1мкВ/С термоЭДС, и просто подключив как попало в эту китайскую плату свой датчик можно легко получить "погодную станцию" вместо измерения нужного мкВ напряжения.

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

Вот собственные шумы различных вольтметров измеренные с закороткой на входе:

https://raw.githubusercontent.com/pavel212/noise/main/integrators_v.png

ad7195 который при усреднении в пару минут (0.01SPS) вполне дотягивается до 1нВ шумов, запитан был при этом тупо от +5 USB от ПК к которому был подключен, схема платы AD7195EBZ на сайте AD есть.

а ADS1263 на этом же графике, с теми же 6нВ/rtHz шумами на максимальном усилении встроенного PGA, это точно такие же китайские модули от waveshare как у автора, и питание на них сделано действительно как попало, то есть вообще никак. На графике они правда были запитаны аккуратно, но ради интереса я их напрямую в USB тоже втыкал, AVDD == +5VUSB, без каких-либо дополнительных фильтров, и шумы только процентов на 40-50% подрастали от даташитных значений, а с дополнительным LDO, +5USB->4.9V AVDD становились обратно как по даташиту.

Последние лет пять занимаюсь внедрением регистрирующего оборудования на базе микрокомпьютера Raspberry Pi

За 5 лет на выходе прототип из готовых модулей?
Самое главное не огласили детали техзадание, что физически измеряется, какая точность нужна как по напряжению, так и по времени. И это выглядит как сами придумали проблемы и героически их решаете.

Судя по тому, что 50 выборок в секунду достаточно, аналоговая полоса сигнала до 10гц. Зачем здесь сверхточность синхронизации по GPS - непонятно.
Ну допустим, сигнал медленно меняющийся, 50sps на выходе. Вполне нормально запустить преобразователь в свободном режиме на 1000sps или как у вас 500. И потом раз в секунду делить полученный массив на 50 частей. И даже никакая сложная передискетизация, как выше предлагали, не нужна. Не страшно, если на один выходной семпл придется 20 отсчетов, полученных с АЦП или 19.

Помехи на столе: вы используете готовую "игрушечную" плату, в которой разрабочики не задумавались об аналоговой части особенно. Опорник с собсвенным шумом в 120uV, Питание напрямую от RPI... Ну и самое главное, частота 50гц "на столе" будет проникать со всех сторон. Про разводку и землю уже сказали выше.

То что у вас не получилось 20ms на измерение после синхронизации - выглядит вполне нормально для "первого" измерения (что указано как t18 = 2.18ms) + собственно длина строба Sync.

Ну и если уж так хочется чтоб все было жестко сихнронизировано - убрать кварц и использовать GPS-PPS->PLL (x7.68M). По идее u-blox модули и сами имют PLL и выдавать до 10Мгц на выходе, но там надо смотреть что с джиттером. Но подозреваю, для вашей задачи можно пренебречь. Но тут все равно начинаются проблемы если необходимо использовать больше 1 входа.

Ну и самое главное, RPI и и линукс тут явно избыточны. ESP32 за глаза, меньше размеры, заметно меньше потребление, не нужен внешний усб-вайфай свисток и можно все срокойно сделать на одной плате.

частота 50гц "на столе" будет проникать со всех сторон

Хорошо, а почему помеха проявляет себя даже в том случае, когда нет никаких 50 Гц? Когда питание от аккумулятора через DC-DC преобразователь. Я об этом не пишу напрямую, но я всё-таки добавил про "не зависит от источника питания".

По идее u-blox модули и сами имют PLL и выдавать до 10Мгц на выходе

Про эту фишку знаю. Там вся сложность в том, что, хорошо, u-blox теперь тактирует АЦП вместо кварца. А как отследить момент, когда он начал тактировать? У ублоксов момент переключения частот слегка отвратительно реализован. И ведь потом надо когда как-то считать эти тики 7.68М, чтобы не потерять привязку к моменту переключения частот (выраженному в чч:мм:сс), в полевых условиях, когда регистрация должна запускаться автоматически, это непросто. Так что, я считаю, что пошел по пути наименьшего сопротивления. И, повторюсь, синхронность отрабатывается на все деньги, и мне уже не важно, что ради этого пришлось пойти на сложности с GNSS и пр. Подробности я могу в личку написать.

Ну и самое главное, RPI и и линукс тут явно избыточны

Согласен. Единственное, имхо (повторюсь: опыта немного, могу ошибаться), работа с физическими носителями в ESP32/Ардуине - тихий ужас. А у меня часто бывает, что пропадает Wi-Fi, но малинка и в таком случае продолжает писать в файл на флэшку. Я спорить не буду, это "ошибка молодости", но у меня в обсерватории пять комплектов регистраторов на Raspberry работает, не вижу смысла начинать с чистого листа.

Ну допустим, сигнал медленно меняющийся, 50sps на выходе. Вполне нормально запустить преобразователь в свободном режиме на 1000sps или как у вас 500. И потом раз в секунду делить полученный массив на 50 частей.

Он что-то про геофизику писал, вероятно это массив сейсмодатчиков. Наверное стукают по земле тяжелой хреновиной и потом смотрят что приходит на сейсмодатчики, типа полезные материалы под землей ищут. А можнт не стукают, специфика текущего момента такая, что может хреновина сама едет и не совсем дружественно громыхает, - нужно посчитать ее координаты. Точность синхронизации и точность измерения начала фронта там нужна - чем точнее, тем лучше.


Только не делить полученный массив на 50 частей, раз уж, как предлагаете, преобразователь в свободном режиме, то считать "running average" ("rolling mean"). .

Первый вопрос: а какая точность по времени у выхода GNSS приёмника? В смысле какая максимальная гарантированная разница между таймингами прихода импульсов от этих конкретных моделей приёмников разнесенных на несколько сотен метров?

Просто если можно запустить АЦП в свободным режиме на высокой частоте, а по сигналу лишь выбирать какие группы импульсов усреднять, то это было бы проще и надёжнее. Но, конечно, если приемник может выдавать сигналы очень точно, то не прокатит.

Ну и в целом, я бы такой проект начинал с анализа предела точности, чтобы знать, что можно добиться на этом оборудовании, а что нельзя (либо чтобы выбирать, собственно, приемники, если их можно выбирать разные).

Хотя и в таком случае правильно было бы использовать свободный режим. Просто вычислить локально время между импульсами от приёмника, вычислить время от подачи сигнала запуска до первого измерения и, получив очередной импульс, выждать разницу первого и второго и самостоятельно выдать сигнал старта, чтобы получить результат аккурат к следующему импульсу. Можно периодически повторять калибровку, если устройство работает неделями и месяцами.

Дело в том, что у АЦП может отличаться точность в свободном и одиночном режиме, причём в случае сигма-дельта АЦП - свободный режим точнее. Кстати, и время между замерами может быть более круглое, чем время одиночного замера.

Наконец, конечно, там лучше подходит не малинка, а ESP32 и аналоги. Та же поддержка WiFi, но риалтайм из коробки без заморочек с модулями ядра. Плюс компактнее и меньше жрёт. По сложности программирования должно быть легко за счёт Arduino SDK, который осваивается прямо по ходу разработки, если уже есть знакомство с embedded.

А какие требования к синхронности? Просто данный ацп дельта-сигма и каждый раз делать синк это сбивает конвеер, возможно поэтому проблемы с малыми сигналами. Возможно первые три измерения вообще не валидны - это часто для сигма-дельта. Может имеет смысл работать на более высокой частоте постоянно, а по синхросигналу с gps выдергивать нужное измерение.

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

Дома несколько лет лежит распбери, кроме как поиграться, до сих пор не нашел реального применения - либо избыточно, либо недостаточно.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации