Перейти к содержанию

АЦП: читаем потенциометр

Аналого-цифровой преобразователь превращает напряжение на входе в число от 0 до 1023. Чтобы получить правильное число, нужно выбрать опорное напряжение и канал, задать частоту АЦП и дождаться конца преобразования.

Обновлено Редакция GAW

AVR с нуляурок 7 из 825 мин

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

Цифровой вход знает только два уровня. Чтобы узнать, какое именно напряжение на выводе, нужен АЦП. В ATmega328P он 10-битный, последовательного приближения, с мультиплексором на шесть входов ADC0–ADC5 в корпусе DIP (у корпусов TQFP и VQFN есть ещё ADC6 и ADC7). На Uno входы ADC0–ADC5 — это выводы A0–A5.

Схема

Потенциометр 10 кОм включим между 5 В и землёй, а средний вывод — на A0 (PC0, ADC0). Выходное сопротивление такого делителя не больше 10 кОм / 4 = 2,5 кОм (в среднем положении; расчёт наш), а АЦП оптимизирован для источников до 10 кОм (раздел 24.6.1) — условие выполнено.

Опорное напряжение и канал: ADMUX

АЦП сравнивает входное напряжение с опорным. Его выбирают биты REFS1:0 регистра ADMUX (табл. 24-3), а канал — биты MUX3…0 (табл. 24-4):

REFS1:0Опорное
00внешнее, на выводе AREF
01AVCC, с конденсатором на выводе AREF
10зарезервировано
11внутреннее 1,1 В, с конденсатором на AREF

Для потенциометра от 5 В удобно опорное AVCC: ADMUX = _BV(REFS0), MUX3…0 = 0000 — канал ADC0. Бит ADLAR = 1 выравнивает результат влево, если хватает старших 8 бит; по умолчанию он 0.

Частота и запуск: ADCSRA

Для полного 10-битного разрешения частота АЦП должна быть от 50 до 200 кГц (раздел 24.4). Её получают из системной делителем, который выбирают биты ADPS2…0 (табл. 24-5): 2, 2, 4, 8, 16, 32, 64, 128. При 16 МГц подходит только 128 — получается 125 кГц.

Бит ADEN включает АЦП, запись единицы в ADSC запускает одиночное преобразование. ADSC остаётся единицей, пока преобразование идёт, и аппаратно сбрасывается по окончании (раздел 24.3). Обычное преобразование занимает 13 тактов АЦП, первое после включения — 25, потому что АЦП ещё инициализирует аналоговую часть. При 125 кГц это 104 и 200 мкс (расчёт наш).

Результат лежит в паре регистров ADCL и ADCH: сначала читают ADCL, потом ADCH (раздел 24.9.3). В avr-libc они объединены в 16-битный регистр ADC, и компилятор сам читает байты в правильном порядке. Результат связан с напряжением формулой из раздела 24.7:

ADC=VIN⋅1024VREF\text{ADC} = \frac{V_\text{IN} \cdot 1024}{V_\text{REF}}

Программа: яркость от потенциометра

Возьмём ШИМ из урока 6 и будем задавать яркость светодиода на выводе 6 потенциометром:

#include <avr/io.h>
#include <stdint.h>

static void adc_init(void)
{
    ADMUX = _BV(REFS0);                         /* AVCC reference, channel ADC0 */
    ADCSRA = _BV(ADEN)                          /* ADC on */
           | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); /* clk/128: 125 kHz at 16 MHz */
    DIDR0 = _BV(ADC0D);                         /* digital input buffer off on PC0 */
}

static uint16_t adc_read(uint8_t channel)
{
    ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);  /* keep REFS and ADLAR, set MUX */
    ADCSRA |= _BV(ADSC);                        /* start a single conversion */
    while (ADCSRA & _BV(ADSC)) {
        /* ADSC is cleared by hardware when the result is ready */
    }
    return ADC;                                 /* ADCL then ADCH, 0..1023 */
}

int main(void)
{
    DDRD |= _BV(DDD6);                          /* LED on OC0A (PD6, pin 6) */
    TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); /* fast PWM, non-inverting */
    TCCR0B = _BV(CS01) | _BV(CS00);             /* clk/64 */

    adc_init();

    for (;;) {
        uint16_t code = adc_read(0);
        OCR0A = (uint8_t)(code >> 2);           /* 10-bit code to 8-bit duty */
    }
}

Регистр DIDR0 отключает цифровой входной буфер вывода, когда он используется только как аналоговый вход (раздел 24.9.5): буфер на промежуточном напряжении лишь зря потребляет ток.

Чтобы получить милливольты, пересчитаем код по формуле с опорным 5000 мВ. Умножение в 32 битах, иначе 1023 · 5000 переполнит 16-битное число:

uint16_t mv = (uint16_t)(((uint32_t)code * 5000UL) / 1024UL);

Точность и опорное

Опорное AVCC — это питание платы, и все его колебания прямо переходят в результат: если USB даёт 4,8 В вместо 5 В, код будет примерно на 4 % больше (расчёт наш: 5 / 4,8 ≈ 1,042). Абсолютная погрешность самого АЦП по даташиту — типично 2 LSB при опорном 4 В и частоте 200 кГц (табл. 29-15). Если нужна стабильная шкала, используют внутреннее опорное 1,1 В и делитель на входе. После смены опорного первый результат может быть неточным, и его советуют отбросить (раздел 24.5.2). Подробнее о погрешностях — в ответе «Почему АЦП Arduino неточен» и в калькуляторе бюджета погрешности АЦП.

Безопасность

  • Напряжение на любом выводе, кроме RESET, — от −0,5 В до VCC + 0,5 В (раздел 29.1). Источник больше 5 В подают только через резистивный делитель.
  • Если на вывод AREF подано внешнее напряжение, нельзя выбирать опорное AVCC или 1,1 В: внутреннее опорное окажется замкнуто на внешний источник (раздел 24.5.2). На Uno при опорном AVCC на AREF ничего не подключают.

Задание

  1. АЦП с опорным AVCC = 5 В выдал код 300. Какое напряжение на входе?
  2. Потенциометр подключили к 3,3 В вместо 5 В, опорное оставили AVCC. Какой наибольший код получится, и сколько шагов шкалы потеряно?
Ответ и решение
  1. VIN = ADC · VREF / 1024 = 300 · 5 / 1024 ≈ 1,465 В.

  2. При 3,3 В на входе код = 3,3 · 1024 / 5 ≈ 675,8, то есть 675 (АЦП отбрасывает дробную часть). Используется около 676 кодов из 1024 — треть шкалы потеряна. Чтобы вернуть разрешение, опорное должно совпадать с питанием датчика: например, подать 3,3 В на AREF и выбрать REFS1:0 = 00.

Что дальше

В уроке 8 выведем результаты АЦП на компьютер через UART. Делитель ADPS, время преобразования и код по напряжению для любой частоты посчитает калькулятор АЦП AVR; все регистры АЦП с битами — на странице регистров АЦП ATmega328P. Как устроен АЦП последовательного приближения и чем он отличается от других, рассказывают статья «АЦП» и термины «АЦП последовательного приближения», «Опорное напряжение» и «Младший значащий разряд».

Частые вопросы

Почему код АЦП делят на 1024, а не на 1023?

Так записана формула в даташите: ADC = VIN · 1024 / VREF. Код 0x3FF (1023) соответствует не самому опорному напряжению, а опорному минус один шаг квантования. Деление на 1023 даёт ошибку меньше одного шага и часто встречается в примерах, но формулой производителя будет 1024.

Какую частоту АЦП выбрать при 16 МГц?

Для полного 10-битного разрешения частота АЦП должна быть 50–200 кГц. При 16 МГц подходит только делитель 128: 16 МГц / 128 = 125 кГц. Делитель 64 даёт 250 кГц — выше рекомендуемого, и точность падает.

Можно ли подать на вход АЦП больше 5 В?

Нет. Абсолютный максимум напряжения на выводе — VCC + 0,5 В, а всё, что выше опорного, АЦП всё равно покажет как код около 1023. Большее напряжение сначала уменьшают резистивным делителем до диапазона опорного.

Источники

  1. Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet (DS40002061B) — разд. 24.3: запуск преобразования битом ADSC, он сбрасывается по окончании; разд. 24.4: частота АЦП 50–200 кГц для полного разрешения, преобразование 13 тактов АЦП, первое — 25; разд. 24.5.2: опорное AVCC, 1,1 В или AREF, внешнее напряжение на AREF замыкается с внутренними опорными, первый результат после смены опорного отбросить; разд. 24.6.1: источник с выходным сопротивлением до 10 кОм; разд. 24.7: ADC = VIN · 1024 / VREF; табл. 24-3, 24-4, 24-5: REFS, MUX, ADPS; разд. 24.9.3: ADCL читается раньше ADCH; разд. 24.9.5: DIDR0; табл. 29-15: абсолютная погрешность типично 2 LSB (столбец Typ) при VREF 4 В и 200 кГц; разд. 29.1: напряжение на выводе от −0,5 В до VCC + 0,5 В
  2. AVR-LibC 2.3.2: заголовок iom328p.h (github.com/avrdudes/avr-libc) — 16-битный регистр ADC (он же ADCW) по адресу 0x78; биты REFS1, REFS0, ADLAR, MUX3…MUX0, ADEN, ADSC, ADATE, ADIF, ADIE, ADPS2…ADPS0, ADC0D

Нашли ошибку?