В моем приложении микроконтроллер Cortex M0 в настоящее время отбирает сигнал АЦП с частотой 10 кГц и отправляет результат через последовательный кабель USB на компьютер.
Теперь я хочу увеличить частоту дискретизации до более чем 100 кГц и добавить второй канал.
USB-последовательный канал ограничен 1-3 Мбит/с, поэтому физически невозможно вести потоковую передачу с такой скоростью при 12-битном значении АЦП и 2 байтах, необходимых для передачи каждого семпла. Для двух каналов АЦП с частотой дискретизации 100 кГц требуемая скорость передачи данных составляет примерно 4 Мбит/с:
Я знаю, что могу уместить 2 выборки АЦП в 3 байта, но я хочу несколько сжать данные АЦП.
Какие алгоритмы сжатия подходят для работы в микроконтроллере Cortex M0?
Существуют десятки алгоритмов сжатия, но я ищу то, что может работать на платформе с ограниченными ресурсами.
Это на самом деле аудио приложение? Не могли бы вы заменить все это выделенным аудиоинтерфейсом, который решит все эти проблемы за вас, или вам нужен точный уровень постоянного тока? Стерео 96kps вполне достижимо.
У вас не так много MIPS для работы, поэтому я собираюсь предложить следующую схему кодирования. Это технически переменный битрейт, так что лучше надеяться, что транзиенты редки. Он работает для сэмплов до 15 бит.
Реконструкция проста:
Есть несколько «простых» шагов, которые вы можете предпринять, чтобы уменьшить необходимую скорость передачи данных:
Вам действительно нужно разрешение 12 бит? Если вы можете пожертвовать 4 младшими битами (которые могут быть только шумом), вы уменьшите требуемую полосу пропускания на 33% и одновременно сэкономите несколько операций.
на какую величину сигнал «обычно» изменяется между двумя последовательными выборками. Например, если в 95% случаев разница только в 6 младших битах, вы можете отправить:
Наконец, одна интересная вещь, которую вы сказали в комментариях, заключается в том, что вам нужна такая высокая частота дискретизации, потому что вы хотите наблюдать переходные процессы.
Поэтому я вижу 2 решения, немного более сложных, но которые могут значительно снизить скорость передачи данных, необходимую для вашего конкретного приложения:
Если вам нужны только переходные процессы: почему бы не «запустить» их? Вы сохраняете все свои измерения в скользящем буфере (используя DMA, если можете). Затем вы используете некоторые программные вычисления для определения переходного процесса (например, разницы больше, чем X, между измерениями N и N-N0). Если вы обнаружите его, вы отправляете только значения, близкие к измерению N. Если ваши переходные процессы редки, ваша требуемая скорость передачи данных становится очень низкой. NB: в этой версии вы видите ТОЛЬКО переходные процессы, а не все остальное (может соответствовать вашим потребностям или нет, если нет, см. Решение 4)
Другое решение — не отправлять выборки с регулярными временными интервалами: вы по-прежнему производите выборку с частотой 100 кГц (хранится во внутреннем буфере с помощью DMA), но вы передаете только часть данных: когда данные быстро меняются, вы отправляете много данных, когда они меняется медленно, вы отправляете мало. Например :
Таким образом, в основном на принимающей стороне вы получаете значение в форме A[0:3].M[0:12], где A — количество пропущенных выборок (поэтому (A+1) sample_period — время, прошедшее с момента последней выборки ) , а M значение этого образца. Если ваш сигнал меняется достаточно медленно и переходные процессы редки, у вас будет среднее значение A между 14 и 15 (давайте будем консервативны и скажем 14), поэтому у вас есть средняя скорость передачи 2 канала 16 бит * 100000 Гц/15 = 213 кбит/с . s : это легко сделать на UART со скоростью 1 Мбит/с.
Это потребует значительных вычислительных затрат, поэтому вам нужно убедиться, что вы можете сделать все вовремя. Вам придется просмотреть все данные несколько раз, это порядка O (n). Потому что вы, очевидно, не можете сделать это, не просмотрев все данные хотя бы один раз, и с ними тоже нужно что-то делать. Возможно, вы можете сэкономить время на автоматизации процедуры отправки - вы можете регулярно запускать прерывания по таймеру, а затем запускать передачу данных с помощью DMA. Это высвободит часть вычислительной мощности. Если вам это нужно, может быть, вы можете справиться с этим проще и все же сделать это. (вы даже не опубликовали MCU и частоту, на которой он работает, на момент написания этого)
У вас может быть как статический, так и динамический словарь сжатия (что чем заменяет). Если он статичен, вы можете жестко закодировать его на принимающей стороне для распаковки. Если он динамический, для его генерации потребуется больше вычислений на стороне MCU, и вам также нужно будет передать его в виде данных на принимающую сторону (ПК), потому что ему необходимо его декодировать.
Во-первых, оцените, какие значения чаще всего возвращает ваш АЦП. Возможно, вы захотите сжать наиболее значимые биты. Вам придется искать некоторые конкретные алгоритмы, но я думаю, что нет способа сделать это, не отказываясь от некоторой пропускной способности, потому что то, что вы отправляете, должно быть различимо - вы отправляете фактические необработанные данные или сжатые данные или словарь? Например, вы можете жестко запрограммировать, чтобы каждые 16 байтов вы отправляли байт, который будет словарем для следующих 16 байтов (или больше, но тогда ваше сжатие может ухудшиться из-за того, насколько разнообразны данные). Это означает, что ваше сжатие должно быть достаточно хорошим, чтобы преодолеть эти накладные расходы и при этом увеличить общий объем передаваемых данных.
Но шаг номер 1 всегда оценивает, есть ли что-то в данных для сжатия. Если вы ожидаете, что все возможные значения будут полностью случайными все время, вы мало что можете сделать, тогда вы можете отказаться от некоторых измерений. Это просто ваше аппаратное ограничение. Вы можете получить так много только с ним.
Вам нужна полнополосная связь с ПК только в том случае, если вы планируете, что ARM будет просто тупым USB-АЦП и всеми умными вещами, происходящими на ПК. Если вы поместите обработку на ARM, вы сможете отправлять данные обратно на ПК медленнее.
Вы говорите, что ищете транзиентов. По сути, тогда мы говорим о дифференциации (поиске быстрой скорости изменений). Проделав это недавно с работой (дифференцируя позицию, чтобы дать скорость и ускорение, а затем запуская управление положением-скоростью-ускорением с обратной связью), я могу сказать вам, что сэмплирование зашумлено, и вам нужны значительные уровни фильтрации, когда вы смотрите по скорости изменения. Если вы этого не сделаете, то ложные срабатывания из-за шума убьют ваш дизайн. (Фильтры нижних частот Бесселя FTW из-за минимального перерегулирования и твердой групповой задержки в полосе пропускания; также посмотрите на преобразование MZTi для лучшего отклика, когда ваша постоянная времени фильтра приближается к Найквисту.)
Теперь у нас есть кое-что с более полезными данными для работы ПК. Но также у нас есть кое-что, что можно отправить обратно на ПК медленнее, потому что, если вы отфильтровали свои данные с помощью фильтра нижних частот, вам не нужно отправлять эти данные быстрее, чем удвоить вашу новую пропускную способность.
Илья
jwsc
mr_js
mr_js
Д утка
Илья
Антонио51
Винни
СтивШ