10-битный АЦП Arduino не точен?
Я считываю напряжение с помощью делителя напряжения:
| Arduino подключен как к USB, так и к адаптеру 9 В.
float r1 = 100000;
float r2 = 9980;
float adc, voltage, analog;
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
pinMode(A0, INPUT);
}
void loop() {
for (int i = 0; i < 256; ++i) {
analog += analogRead(A0);
}
analog = analog / 256;
adc = analog * 1.228 / 1023;
voltage = adc / (r2 / (r1 + r2));
Serial.print(analogRead(A0));
Serial.print(", ");
Serial.print(analog);
Serial.print(", ");
Serial.print(adc);
Serial.print(", ");
Serial.print(voltage);
Serial.println(" ");
delay(100);
}
Вот результат теста на точность:
Input | Arduino | Difference
1V 0.89V -110mV
2V 1.90V -100mV
3V 2.92V -80mV
4V 3.93V -70mV
5V 4.95V -50mV
6V 5.97V -30mV
7V 6.98V -20mV
8V 8.00 0
9V 9.01 +10mV
10V 10.02 +20mV
11V 11.04 +40mV
12V 12.06 +60mV
Входное напряжение измерено цифровым мультиметром и соответствует напряжению, например, 1 000 В.
Я не тестировал напряжения выше 12 В, но кажется, что разница будет увеличиваться на 20 мВ с каждым повышением на 1 В, это означает, что при 50 В показания напряжения будут отличаться на ~ 1 В!
Даже с 10-битным разрешением Arduino у меня должна была быть стабильная точность с некоторым процентом разницы (правильно?), но, как вы можете видеть, результат показывает, что показания совсем не стабильны!
Почему разность напряжений уменьшается/увеличивается при изменении напряжения на входе?
@ElectronSurf, 👍1
2 ответа
Лучший ответ:
Как заявил Маженко, ADC может в принципе иметь все виды ошибки. Однако, если вы посмотрите на свои данные, вы должны заметить, что ошибка практически линейна с напряжением. Это означает, что ошибка нелинейности довольно мала, и вы в основном видите смещение и получить ошибки. Это к счастью, потому что эти ошибки легко исправить. удалить, учитывая хорошие данные калибровки.
Таблица, которую вы написали в своем вопросе, оказалась очень хорошей. калибровочная таблица. Подгоняя к нему прямую, можно получить функцию калибровки, а затем исправить показания, просто добавив это к вашему коду:
voltage = 0.9848815 * voltage + 0.125354;
Или вы могли бы вместо этого вычислить коррекцию на уровне АЦП и заменить
adc = analog * 1.228 / 1023;
от
adc = (analog + offset) / scale;
где смещение
и масштаб
вычисляются на основе калибровки.
Правка: вот как я извлек калибровочные коэффициенты из данные.
Сначала я сохранил данные в текстовый файл Calibration.tsv и очистил его. чтобы удалить единицы и добавить маркер комментария (#) перед столбцом ярлыки:
#Input | Arduino | Difference
1 0.89 -110e-3
2 1.90 -100e-3
...
Затем я просмотрел данные с помощью gnuplot. Так как я хочу знать, как исправить показания, я нарисовал сумму, которую я должен добавить (минус столбец 3) по сравнению с показаниями Arduino (столбец 2):
plot 'calibration.tsv' using 2:(-$3)
На данный момент кажется, что это линейно с тем, что выглядит в основном
шум квантования. Я моделирую это как линию уравнения a*x+b
, и
сравнить строку с данными:
a = -1e-2
b = 0.12
plot 'calibration.tsv' using 2:(-$3), a*x+b
Линия сильно отличается от данных, но в первую очередь это разумно. приближение. Теперь я прошу gnuplot выполнить подбор по методу наименьших квадратов, затем взгляните еще раз:
fit a*x+b 'calibration.tsv' using 2:(-$3) via a, b
replot
Теперь подгонка выглядит неплохо. После завершения подгонки gnuplot отображается:
Final set of parameters Asymptotic Standard Error
======================= ==========================
a = -0.0151185 +/- 0.0002953 (1.953%)
b = 0.125354 +/- 0.002173 (1.734%)
так что теперь я знаю, что могу исправить данные с помощью:
voltage += -0.0151185 * volatage + 0.125354;
что эквивалентно тому, что я написал выше.
Да, вы правы в том, что АЦП Arduino не является точным. Если вы прочитали техническое описание (ATMega328P, раздел 28.9, Характеристики АЦП ) можно увидеть множество характеристик "ошибки" и "нелинейности".
Все это приводит к неточностям в ваших показаниях. Например, «ошибка смещения» на вашем VREF может достигать ± 4,4 мВ, а «ошибка усиления» такая же. Нелинейность может достигать 2 мВ и т. д.
АЦП Arduino не предназначен для обеспечения точности. Это должно быть простым и дешевым в реализации. (Это "АЦП последовательного приближения" - ключевое слово здесь - приближение...) Если вам нужна более высокая точность, то есть более подходящие микросхемы АЦП, обеспечивающие такую точность.
Я ожидал, что ошибка 100 мВ будет устойчивой, как 1,100 В, 2,100 В ... Потрачено столько времени на калибровку этого ...! помимо использования внешнего АЦП, вы думаете, что это хорошая идея переключиться на микроконтроллер PIC с 12-битным АЦП. я спрашиваю это, потому что PIC дешевле., @ElectronSurf
Я бы всегда советовал использовать PIC, а не ATMega, но тогда я фанат PIC, однако увеличение разрешения не означает повышение точности. Это все еще SAR с неотъемлемыми неточностями, которые он вам дает. Поскольку неточность выглядит довольно линейной, вы можете использовать калибровку и расчеты, чтобы устранить ее. У вас есть прямая линия, формула которой (если вы помните школьные уроки математики) y = mx + c
, @Majenko
Относительно «АЦП последовательного приближения»: любое измерение всегда является приближением. Ключевое слово здесь «последовательный»: это означает, что АЦП работает путем итеративного уточнения аппроксимации., @Edgar Bonet
@EdgarBonet А поскольку замеренное напряжение хранится в крошечном конденсаторе, и невозможно прочитать напряжение, не потребляя *некоторый* ток, каждое последующее сравнение будет влиять на напряжение на этом конденсаторе, делая его менее точным с каждым битом, который аппроксимируется. Таким образом, это последовательно ухудшающееся приближение. Это последовательное приближение, которое может быть только приблизительным., @Majenko
- Неточное считывание напряжения с аналогового вывода Arduino
- Постоянный выход тактовой частоты Arduino
- Расширение аналоговых входов для Arduino
- Как считывать напряжение с помощью ADS1115
- ESP8266: system_adc_read_fast() всегда возвращает 1024
- Делитель напряжения и входы NodeMCU
- Высокоскоростной внешний АЦП
- Измерение напряжения литий-ионного элемента, используемого для питания Arduino через повышающий модуль
Как рассчитать смещение и масштаб?, @ElectronSurf
@newbie, поместите данные в Excel/Calc, нарисуйте диаграмму с ожидаемыми значениями и функцией, а затем измените значения смещения и масштаба для функции, пока линии на диаграмме не совпадут., @Juraj
@Juraj Нравится [Это](https://1drv.ms/x/s!AgDusyVPFjOrglWeWee06WbLD3lx)?, @ElectronSurf
Код «напряжение = 0,9848815 * напряжение + 0,125354» почти откалибровал показания с устойчивой разницей ~ -60 мВ (хотя он не может измерять ниже 130 мВ), откуда вы взяли эти значения? не могли бы вы объяснить больше с включенной математикой?, @ElectronSurf
@newbie: я старожил, которому нравятся текстовые программы, а не Excel, Calc и тому подобное, поэтому я использовал gnuplot. Смотрите расширенный ответ., @Edgar Bonet
@EdgarBonet Ты гений, теперь мне нужно сесть и изучить твой ответ. Спасибо., @ElectronSurf
@newbie, столбец B должен иметь функцию в ячейках. и функция должна использовать две другие ячейки с коэффициентами, которые вы хотите настроить, @Juraj
@Juraj Я никогда раньше не пользовался Excel и понятия не имею, как сделать то, что ты хочешь, чтобы я сделал ..., @ElectronSurf
@newbie, пример https://github.com/jandrassy/Regulator/tree/master/util/Calc, @Juraj