Когда АЦП снимает показания?
Я экспериментирую с "двухвыводным измерителем емкости" и пытаюсь сделать его более точным. В настоящее время я заставил Arduino читать интервалы 62,5 нс, но это означает, что время чтения АЦП занимает большую часть интервала. В настоящее время я использую значение предварительного делителя 8 на АЦП. К сожалению, непрерывное чтение на самом деле не вариант, поэтому я ограничен временем чтения около 8 мкс вместо 6,5 мкс. Это не такая большая проблема, так как я знаю, что чтение займет около 8 мкс из экспериментов, однако я не знаю, когда в течение этого интервала 8 мкс происходит фактическое чтение.
Итак, вот мой вопрос: принимает ли adc среднее значение в течение этих 8 мкс, "блокирует" ли он биты в начале или когда именно происходит считывание?
Ссылка на измеритель емкости, особенно третий: http: //www.circuitbasics.com/how-to-make-an-arduino-capacitance-meter/#comment-363733)
@Beacon of Wierd, 👍0
Обсуждение1 ответ
АЦП представляет собой АЦП типа "Последовательное приближение". Это работает следующим образом:
- Снимок входного напряжения на небольшом конденсаторе
- Создание опорного напряжения
- Сравнение напряжения на конденсаторе с эталонным напряжением
- Уточнение эталонного напряжения
- Возвращайтесь к пункту 3, пока не добьетесь желаемой точности.
Там нужно много "времени":
- Конденсатор может точно сохранять напряжение только до тех пор, пока саморазряд (ток утечки) не вызовет падение напряжения (это определяет максимальное количество времени, которое может потребоваться для считывания показаний)
- Каждое уточнение опорного напряжения и его сравнение занимает один такт тактового сигнала АЦП. Также есть несколько «установочных» тактов часов. Это определяет минимальное количество тактов АЦП, необходимое для считывания (13)
- ЦАП и компаратору требуется определенное время для работы каждого тактового импульса, что ограничивает максимальную тактовую частоту, на которой может работать АЦП.
Итак, у вас есть "золотое пятно" скорости (например, "Зона Златовласки" Солнечной системы). Установите АЦП слишком медленно или попытайтесь получить от него слишком высокое разрешение, и вы потеряете точность из-за падения напряжения на конденсаторе. Установите его слишком быстро, и ЦАП не сможет угнаться за ним, и вы потеряете точность из-за неправильного напряжения сравнения.
Ну, это внутренности. Кроме того, у вас есть API Arduino. Это добавляет еще один уровень сложности. analogRead()
— это блокирующая операция. Это:
- Настраивает контакт ввода-вывода (при необходимости)
- Включает АЦП (при необходимости)
- Настраивает ADC MUX на правильный канал
- Начинает конверсию
- Некоторое время сидит, сложа руки.
- Читает результат конверсии.
- Возвращает его вам
И это происходит (кроме, может быть, 1 и 2) каждый раз, когда вы читаете показания. Это нормально для считывания показаний потенциометра, LDR и т. д. Но бесполезно, если вы хотите делать быстрые показания с привязкой ко времени.
Вместо этого вам нужно немного раздвинуть границы и отойти от Arduino API. Многое из того, что делает АЦП, выполняется без вмешательства ЦП. Ручная настройка АЦП для непрерывного чтения и запуска прерывания после завершения преобразования, а затем использование этого прерывания для захвата результата сравнения и запуска нового (или использование прерывания по таймеру для чтения предыдущего результата и запуска нового чтения ) даст вам гораздо больше контроля над АЦП и точно, когда что-то происходит.
Итак, теперь, чтобы ответить на ваш главный вопрос «когда в течение этого интервала 8 мкс происходит фактическое чтение» в контексте того, как работает АЦП:
В тот момент, когда конденсатор SAH отсоединяется от MUX, начинается последовательность сравнения.
Тем не менее, когда именно, это субъективно. Если вы используете API Arduino (analogRead()
), то он находится в какой-то момент рядом с началом вызова функции, но не в его начале.
Если вы настроите его вручную и запустите из прерывания таймера, он будет на втором (из 13) заднем фронте тактового сигнала ADC после того, как ADSC был установлен в ВЫСОКИЙ уровень.
Есть также режимы "Free Running" и "Auto Trigger", время которых такое же, как и для одиночной конверсии. Обратите внимание, что первое преобразование, выполняемое в любом режиме, налагает «вводную» последовательность тактовых импульсов, в которой инициализируются мультиплексор АЦП и ЦАП опорного напряжения.
Всю эту синхронизацию можно найти на рисунках 23-4 и 23-5 на странице 209 Техническое описание ATMega328P. На странице 210 есть удобная таблица, в которой указано, сколько циклов АЦП с начала преобразования происходит при выполнении выборки и удержания и сколько времени занимает преобразование в тактовых циклах.
Для лучшей пропускной способности вы хотите использовать режим "Free Running" и читать и сохранять результат ADC в прерывании, которое запускает ADC. Для наиболее точной и контролируемой синхронизации вы хотите использовать режим автоматического запуска с таймером для источника запуска и снова считывать результат в прерывании АЦП.
Вау, это был потрясающий ответ: D Чрезвычайно подробный: D Я не думаю, что свободный режим работы для меня будет работать, так как аналоговые выводы будут использоваться для вывода и аналогового чтения. Тем не менее, я столкнулся с режимом прерывания с низким уровнем шума, который работает очень хорошо. Тем не менее, я не могу измерить его скорость (поскольку все таймеры сбиваются), вы случайно не знаете, сколько времени требуется, чтобы Arduino заснул и запустил АЦП? :с, @Beacon of Wierd
- Шумный analogRead
- Расширенная настройка АЦП на Due (SAM3X8E) для повышения точности
- Ardunio Mega/ATmega2560: использование порта F или K как для аналоговых входов, так и для цифровых выходов.
- Определенные порты на Teensy 3.6 не считывают правильное битовое разрешение с помощью библиотеки ADC?
- Выход AnalogRead() колеблется, даже если контакт заземлен
- Как прочитать значение АЦП без общего заземления? (Возможно или нет!)
- Потенциометр отображает только аналоговое значение напряжения 1023 в proteus
- Печать результата функции AnalogRead() приводит к сбою Arduino
Синхронизация аналогового чтения() не имеет решающего значения в программе «2-контактный измеритель емкости». Только время между
pinMode(OUT_PIN, INPUT_PULLUP);
иpinMode(OUT_PIN, INPUT);
(переменнаяt
) должно быть известно с высокой точностью., @Edgar Bonet@EdgarBonet Почему именно время для pinMode (OUT_PIN, INPUT); важный момент, после этого мы считываем показания с АЦП, изменение режима вывода «задерживает» напряжение или что здесь происходит?, @Beacon of Wierd
Да. Режим вывода
INPUT_PULLUP
заряжает конденсатор через внутренний подтягивающий резистор. Режим «ВХОД» останавливает процесс и, как вы говорите, «запирает» заряд в конденсаторе. Время между двумя изменениями режима является временем зарядки, которое является релевантным временем для определения емкости., @Edgar Bonet@EdgarBonet Спасибо! Это знание значительно увеличило точность, которой я могу достичь. Я, вероятно, просто гоняюсь за машинами в этот момент, но вы случайно не знаете, когда напряжение «застревает». Я использую PORTC для включения и выключения подтягивающего резистора, и кажется, что это занимает всего 1 тактовый цикл, однако я не уверен, лучше ли измерять время до, после или между переключателями. В настоящее время я измеряю время после переключения., @Beacon of Wierd
Считайте время до или после переключения PORTC. Это не имеет значения, пока вы делаете это последовательно. Если вы взяли одно показание _до_ включения подтягивания, а другое _после_ его отключения (или наоборот), вы получите небольшую ошибку синхронизации. Для максимальной надежности делайте это с отключенными прерываниями, например,
cli(); ПОРТС |= _BV(PC2); время_начала = TCNT1; сэй();
, @Edgar Bonet@EdgarBonet Может ли отключение прерываний испортить обновление TCNT2? Я имею в виду, что это не прерывание, которое сбрасывает его на 0, когда оно переполняется в режиме CTC, верно?, @Beacon of Wierd
Нет, TCNT2 не использует прерывание для сброса., @Edgar Bonet