Умеренно точный осциллограф на Arduino Uno R3

Я пытаюсь создать относительно точный осциллограф с помощью Arduino Uno R3 и провел небольшое исследование, чтобы найти наилучший способ сделать это. Прежде всего мне нужно измерить напряжение с довольно высокой частотой дискретизации, а затем я собираюсь передать свои данные через последовательный порт и построить данные с помощью Python или Matlab.

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

Я нашел на это веб-сайт содержит полезную информацию о том, как мне писать код, но у меня есть несколько вопросов:

  1. Я хочу, чтобы опорное напряжение составляло 1,1 В, чтобы, разделив его на 1023 части, я получил точность около 1 мВ. Как мне для этого отредактировать указанный код?

  2. Код в настройке void loop() мне бесполезен (я предпочитаю не сохранять измеренные данные на Arduino, а затем отправлять их на свой ПК из-за ограничений памяти ). После удаления данные будут по-прежнему отправляться на последовательный порт?

  3. Повлияет ли отправка данных через последовательный порт на частоту дискретизации/точность? Я имею в виду, как это влияет на мою точность?

PS: под умеренной точностью я подразумеваю следующее: я хочу точно измерить напряжение с точностью до 1 мВ для частот макс. 500 кГц (чуть меньше или больше не помешает).

, 👍2

Обсуждение

Это интересный вопрос, хотя бы для того, чтобы определить пределы «умеренной точности», установленные платформой Uno. Возможно, вам придется разбивать свое кодирование по частям, задавая все три вопроса одновременно, вы можете ограничить ответы, которые вы получите. Я думаю, что функция AnalogReference() может помочь с первым вопросом. https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/, @RowanP

@rowanp спасибо за помощь с аналогом. Я отредактирую вопрос для лучшего определения мягкости., @infinite

Когда аппаратное обеспечение выходит за пределы своих возможностей, я считаю, что нужно хорошо разбираться как в аппаратном, так и в программном обеспечении. Просто для начала учтите, что Python в 100 раз, если не более чем в 1000 раз, медленнее, чем, скажем, скомпилированный C. Я говорю это, хотя это звучит так, как будто вы используете Python не на Arduino. С другой стороны, хотя АЦП имеет 10 бит, это не обязательно означает, что вы можете получить 1024 шага разрешения для любого отдельного образца. Шум, вероятно, значительно уменьшит это., @st2000

@ st2000 Я понимаю, что Python намного медленнее, чем C. Так даст ли использование Matlab в качестве анализатора данных лучшие результаты? так как он основан на C или я должен просто проверить это?, @infinite

Вы не получите около 500 kS/s (килосэмплов в секунду) с Uno. Точность АЦП ухудшается по мере увеличения его тактовой частоты, и после частоты 1 МГц (что дает 76,9 тыс. отсчетов в секунду) он становится практически мусором. См. [Преобразование АЦП на Arduino] (https://www.gammon.com.au/adc) Ника Гэммона., @Edgar Bonet

@EdgarBonet после того, что вы сказали, я немного поискал критерий Найквиста и обнаружил, что если мы не хотим использовать частоту дискретизации выше 76,9 кС / с, самая высокая частота, которую мы можем измерить, составляет около 38 кГц. я прав?, @infinite

Я не думаю, что кто-то из нас хочет разочаровать тебя, @infinite. Может быть, лучше подумать об этом, думая, что вы можете не достичь своих целей. И если вы получаете удовольствие от этого, тем лучше. Кроме того, как только вы получите некоторый опыт работы с Uno R3, подумайте о том, чтобы улучшить свою игру с помощью более продвинутого / более быстрого процессора. Среда разработки Arudino была перенесена на множество различных процессоров/плат., @st2000

@ st2000 Думаю, ты прав! но до сих пор я многое узнал о сигналах и о том, как работает АЦП, и обо всем этом, поэтому для лучшего изучения я пытаюсь сделать этот проект как можно лучше., @infinite


1 ответ


Лучший ответ:

2

Я хочу, чтобы опорное напряжение было 1,1 В, чтобы, разделив его на 1023 детали у меня будут с точностью около 1мв.

У вас будет разрешение около 1 мВ. Точность будет значительно хуже, чем из-за несовершенства АЦП (ошибка смещения, ошибка усиления, нелинейность) и шум.

как я должен отредактировать указанный код, чтобы сделать это?

Ссылка настраивается битами REFS0 и REFS1 Регистр ADMUX. Внутреннее опорное напряжение 1,1 В выбирается установка обоих битов, как показано в таблице 24-3 техническое описание. Затем вы можете исправить исходный код следующим образом:

@@ -8,7 +8,7 @@
   ADCSRA = 0;             // очистить регистр ADCSRA
   ADCSRB = 0;             // очистить регистр ADCSRB
   ADMUX |= (0 & 0x07);    // устанавливаем контакт аналогового входа A0
-  ADMUX |= (1 << REFS0);  // устанавливаем опорное напряжение
+  ADMUX |= (1 << REFS0) | (1 << REFS1);  // устанавливаем опорное напряжение
   ADMUX |= (1 << ADLAR);  // выравнивание по левому краю значения АЦП по 8 битам из регистра ADCH
 
   // частота дискретизации [тактовая частота АЦП] / [предварительный делитель] / [тактовая частота преобразования]

код в настройке void loop() для меня бесполезен (я предпочитаю не сохранить измеренные данные на Arduino, а затем отправить на мой компьютер из-за ограничений памяти). после удаления данные останутся быть отправлены на последовательный порт?

В связанном коде loop() — единственная функция, отправляющая что-либо в последовательный порт. Если вы удалите его, ничего не будет отправлено. Ты мог Serial.write() в ISR, и в этом случае пустой loop() было бы хорошо.

Обратите внимание, что запись в Serial из ISR обычно обескураженный. Однако ваша ситуация (код осциллографа) является одной из очень мало случаев, когда это имеет смысл.

отправка данных через последовательный порт повлияет на мой образец скорость/точность?

Это, безусловно, может повлиять на частоту дискретизации. Serial.write() обычно неблокирующий, так как все, что он делает, это записывает данные в ОЗУ буфер. Однако если буфер заполнится, Serial.write() заблокирует ожидая, пока последовательный порт действительно отправит данные, и сделает достаточно место в буфере.

Это означает, что для того, чтобы осциллограф не пропускал выборки, вы должны убедиться, что последовательный порт может отправлять данные, по крайней мере, как быстро, как ADC получает его.

Пример расчета: если вы тактируете АЦП на частоте 1 МГц, вы получите выборка каждые 13 мкс. Вы можете следовать примеру, приведенному в коде вы связаны, и отбросить последние два бита, чтобы передавать только 8 бит выборки. Передача их в простом двоичном формате займет 10 «бит» пропускной способности последовательного порта (один стартовый бит, 8 бит данных и один стоповый бит). Тогда каждый бит должен занимать меньше 1,3 мкс, что соответствует скорости передачи данных 769 231 бит в секунду. второй. Вероятно, у вас не будет другого выбора, кроме как настроить последовательный порт на 1 Мбит/с.

Если вы хотите передать все 10 бит показаний АЦП, придется снизить частоту дискретизации в два раза.

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

,

Возможно, вы захотите использовать Teensy 3.x или Teensy 4.x вместо Arduino R3. У Teensy 4.1 частота процессора составляет 600 МГц, а у R3 — 16 МГц. Оба используют Arduino, и оба находятся в одном ценовом диапазоне., @user3765883