Arduino аналого цифровые преобразования ацп. Аналого-цифровые преобразования — АЦП. Актуальна для измерения крайне малого напряжения

Продолжим знакомство с платформой Arduino и в данной статье рассмотрим аналоговые входы.

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

На плате Arduino UNO их 6 (A0-A5). У других плат количество может отличаться, смотрите в спецификации.

Благодаря встроенному АЦП (аналого-цифровой преобразователь), данные входы могут считывать напряжение подаваемое на них. Микроконтроллеры Atmega 328, используемые в Arduino UNO, содержат шестиканальный АЦП, разрешение которого составляет 10 бит. Это позволяет на выходе получать значения от 0 до 1023 (всего 1024 градации).

// Производим чтение с аналогового входа A0 analogRead (0);

Данная функция возвращает значение от 0 до 1023 пропорционально напряжению на аналоговом входе

Пример на практике

В качестве первого примера работы с аналоговыми входами подключим потенциометр.

Для нашей задачи отлично подойдут однообортные потенциометры изображенные на картинке. Не смотря на столь значительные внешние отличия, они мало чем отличаются. Для примера можно использовать любой из них. Большим потенциометром с крутилкой конечно удобнее пользоваться, но он обладает толстыми ножками которые быстро расшатывают контакты макетной платы. В случае, если под рукой имеется отвертка, то, при работе с макетной платой, лучше воспользоваться квадратным потенциометром.

Для эксперимента нам понадобятся:

Перевод значения аналогового сигнала в вольты

Для перевода получившегося значения в вольты достаточно вычислить шаг и умножить его на получаемое значение.

Для вычисления шага поделим опорное напряжение на 1024 градации

5В / 1024 = 0.0049 Вольт

Т.е. При получаемом аналоговом значении в 500, на порт контроллера приходит (500 * 0.0049) 2.45В.

пример программного кода:

float Step = 5.0F / 1024; void setup () { Serial .begin (9600); // Задаем скорость работы монитор порта } void loop () { int analogValue = analogRead (0); // Задаем переменную analogValue для считывания показаний float voltageValue = analogValue * Step; // Переводим в вольты (показание * шаг) Serial .println (voltageValue); // Выводим значение в вольтах в порт delay (500); // Ждем пол секунды }

Более точная работа аналогового входа

Для того чтобы добиться более точных показаний с аналогового входа можно использовать 2 варианта:

. Функция analogReference()​

Задает опорное напряжение относительно которого происходят аналоговые измерения.

analogReference (type);

Возможные настройки (type ):

DEFAULT : установлено по умолчанию. при данной конфигурации опорное напряжение автоматически принимается за напряжение питания платы Arduino. 5В (на платформах с напряжением питания 5 В) или за 3.3 В (на платформах с напряжением питания 3.3В)

На платформах Arduino "из коробки" вывод AREF не задействован. В этом случае при настройке DEFAULT к выводу подключается внутреннее напряжение AVCC . Соединение является низко-импедансным и любое напряжение подведенное к выводу в этот момент может повредить микросхему ATmega .

INTERNAL : встроенное опорное напряжение 1.1В на микроконтроллерах ATmega168 и ATmega328, и 2.56 В на ATmega8.

Это может пригодиться для более точного измерения напряжения лежащего в пределах ниже 1.1В либо 2.56В . Болле точная работа достигается за счет меньшего шага 5/1024 против 1.1/1024. Значения соответствующее или превышающее 1.1В (2.56В) будут конвертироваться АЦП в 1023.

EXTERNAL : внешний источник опорного напряжения, подключенный к выводу AREF.

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

. Ручная установка опорного напряжения

Актуальна для измерения крайне малого напряжения

Искажения при работе с аналоговыми входами появляются по причине того, что по дефолту за опорное напряжение принимается 5В, в то время как стабилизаторы напряжения на плате Arduino могут немного отклоняться от эталонного значения и выдавать к примеру 4.85В. 4.85 / 1024 = 0.0047 (при эталонном шаге в 0.0049)

В случае, если под рукой имеется точный мультиметр, то можно попросту замерить питающее напряжение и вбить его в расчет, который рассматривался выше.

float Step = 4.85F / 1024; // Вычисляем шаг Uопорн / на градацию

Использование аналоговых входов в качестве цифровых выводов

Аналоговые входы могут использоваться как цифровые порты входов/выходов рассмотренные в предыдущем уроке

Для этого, для UNO, в коде их нужно записывать как цифровые с 14 по 19. К примеру, для A0

// Инициализируем аналоговый pin 0 как выход pinMode (14, OUTPUT ); // Инициализируем аналоговый pin 0 как вход pinMode (14, INPUT );

Описание портов, работающих как аналоговые входы, платформы Arduino (Atmega8, Atmega168, Atmega328, или Atmega1280)

Аналого-цифровой преобразователь

Микроконтроллеры Atmega, используемые в Arduino, содержат шестиканальный аналого-цифровой преобразователь (АЦП). Разрешение преобразователя составляет 10 бит, что позволяет на выходе получать значения от 0 до 1023. Основным применением аналоговых входов большинства платформ Arduino является чтение аналоговых датчиком, но в тоже время они имеют функциональность вводов/выводов широкого применения (GPIO) (то же, что и цифровые порты ввода/вывода 0 - 13).

Таким образом, при необходимости применения дополнительных портов ввода/вывода имеется возможность сконфигурировать неиспользуемые аналоговые входы.

Цоколевка

Выводы Arduino, соответствующие аналоговым входам, имеют номера от 14 до 19. Это относится только к выводам Arduino, а не к физическим номерам выводов микроконтроллера Atmega. Аналоговые входы могут использоваться как цифровые выводы портов ввода/вывода. Например, код программы для установки вывода 0 аналогового входа на порт вывода со значением HIGH:

pinMode(14, OUTPUT);
digitalWrite(14, HIGH);

Подтягивающие резисторы

Выводы аналоговые входов имеют подтягивающие резисторы работающие как на цифровых выводах. Включение резисторов производится командой

digitalWrite(14, HIGH); // включить резистор на выводе аналогового входа 0

пока вывод работает как порт ввода.

Подключение резистора повлияет на величину сообщаемую функцией analogRead() при использовании некоторых датчиков. Большинство пользователей использует подтягивающий резистор при применении вывода аналогового входа в его цифровом режиме.

Подробности и предостережения

Для вывода, работавшего ранее как цифровой порт вывода, команда analogRead будет работать некорректно. В этом случае рекомендуется сконфигурировать его как аналоговый вход. Аналогично, если вывод работал как цифровой порт вывода со значением HIGH, то обратная установка на ввод подключит подтягивающий резистор.

Руководство на микроконтроллер Atmega не рекомендует производить быстрое переключение между аналоговыми входами для их чтения. Это может вызвать наложение сигналов и внести искажения в аналоговую систему. Однако после работы аналогового входа в цифровом режиме может потребоваться настроить паузу между чтением функцией analogRead() других входов.

На этом занятии рассмотрим, аналоговые порты Arduino A0-A5. Разберем принцип работы аналоговых портов, что к ним можно подключать. Соберем с помощью макетной платы схему светильника с управляемой яркостью, чтобы с помощью потенциометра (переменного резистора) можно было изменять яркость свечения светодиода. Рассмотрим директиву #define и analogRead в языке Ардуино IDE.

Устройство и принцип работы потенциометра

Переменный резистор (потенциометр) поворотом ручки изменяет сопротивление в электрической цепи от нуля до номинального сопротивления в 10 кОм. Потенциометр сделан состоит из токопроводящей поверхности — плоского постоянного резистора с двумя контактами и скользящего по поверхности токосъемника. Потенциометр предназначен для регулировки напряжения в электрической цепи.

Переменный резистор имеет прочную токопроводящую поверхность, поскольку положение настройки потенциометра изменяется постоянно. Переменный резистор служит для регулярного применения, например, для изменения уровня громкости.

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

Аналоговые входы на Ардуино

Микроконтроллер Atmega в Arduino , содержит шестиканальный аналого-цифровой преобразователь (АЦП). Разрешение преобразователя составляет 10 бит, что позволяет получать значения от 0 до 1023. Основным применением аналоговых входов Ардуино (A0 — A5 в Arduino UNO) является снятие значений с аналоговых датчиков. Рассмотрим применение аналогового входа для снятия показаний с потенциометра.


Небольшая цена деления шкалы позволяет с большой точностью получать значения практически любой физической величины. Чтобы считать показания на аналоговом входе следует использовать функцию analogRead . Аналоговые порты, как цифровые Ардуино можно сделать с помощью команды digitalRead — используется для считывания данных с кнопки и digitalWrite — можно подключить светодиод.

Светильник с управляемой яркостью

На этом занятии мы соберем электрическую схему светильника с управляемой яркостью. С помощью потенциометра мы сможем изменять яркость светодиода, подключенного к пину 9. Потенциометр подключается крайними ножками к портам 5V и GND, со средней ножки снимается значение напряжения на аналоговый вход A0.

Для занятия нам понадобятся следующие детали:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • макетная плата;
  • потенциометр;
  • 1 светодиод и резистор 220 Ом;
  • провода «папа-папа».

Соберите электрическую цепь, как на рисунке. Средняя ножка переменного резистора подключается к аналоговому порту A0, чтобы снимать показания напряжения. Какую из крайних ножек подключить к портам 5V и GND значения не имеет, изменится лишь направление вращения ручки потенциометра для увеличения яркости светодиода. После сборки схемы, подключите Arduino к компьютеру и загрузите следующий скетч.

Скетч для Ардуино и потенциометра

// Присваиваем имя для пина со светодиодом (англ. «led») #define LED_PIN 9 // Присваиваем имя для пина с потенциометром (англ. «potentiometer») #define POT_PIN A0 void setup () { // пин со светодиодом будет выходом (англ. «output») pinMode (LED_PIN, OUTPUT ); // пин с потенциометром будет входом (англ. «input») pinMode (POT_PIN, INPUT ); // Запускаем монитор последовательного порта // снимите комментарий // Serial.begin(9600); } void loop () { // заявляем, что будем использовать 2 переменные - rotation и brightness // хранить в переменных будем только целые числа (англ. «integer») int rotation, brightness; // rotation равна значениям с потенциометра в интервале от 0 до 1023 rotation = analogRead (POT_PIN); // переменная brightness будет равна rotation делённое на 4 // brightness может быть только целым числом, дробная часть будет отброшена // в итоге переменная brightness будет находится в пределах от 0 до 255 brightness = rotation / 4; // выдаём напряжение, рассчитанное по формуле brightness = rotation / 4 analogWrite (LED_PIN, brightness); // Выдаем значение rotation на монитор последовательного порта // снимите комментарий // Serial.println(rotation); // снимите комментарий // delay(1000); }

Пояснения к коду:

Очень полезный модуль в составе микроконтроллера — аналого-цифровой преобразователь. Он позволяет микроконтроллеру измерять произвольное напряжение.
В мы описывали, как можно считать логическое состояние входа, то есть "0" или "1". Аналого-цифровой преобразователь считывает величину напряжения на выводах A0-A5. Это дает возможность считать данные с датчика освещенности, измерить напряжение питания и т.д.

Подготовка к работе

На нашем для освоения работы с АЦП есть три переменных резистора. Для их подключения к выводам A0-A2 установите перемычке так, как показано на рисунке:

К выводу A0 подключен подстроечный резистор, расположенный в левом верхнем углу платы и у него есть удобная ручка. Два других меньше и подключены к выводам A1, A2.

Первый пример

Для начала попробуем просто считать напряжение на выводе микроконтроллера A0 и отправить его в COM-порт.
Делается это при помощи функции analogRead() . Этой функции нужно передать номер вывода, напряжение на котором должно быть измерено и она вернет текущее значение.
Загрузите на плату следующий пример:

int val; void setup() { Serial. begin(9600 ) ; } void loop() { val = analogRead(A0) ; Serial. println(val) ; delay(1000 ) ; }

В микроконтроллере Atmega8A, который используется на нашей плате , есть модуль АЦП с разрешением 10 бит и возможностью мультиплексирования шести входов. Эти входы пронумерованы A0-A6 (или 14-19).
Измерение производится относительно напряжения питания. Ни в коем случае нельзя подавать на вход отрицательное напряжение или напряжение, превышающее питание! Мы подключили ко входу переменный резистор и наше входное напряжение точно не выйдет за рамки питания.
Теперь разберемся с тем, что нам будет присылать плата. Раз разрешение 10 бит — в десятичном виде значение будет меняться от 0 до 1023. Измерение производится относительно 5-ти вольт, поэтому изменение показаний на 1 соответствует фактическому напряжению 5/1023=4.9мВ. То есть средствами встроенного АЦП микроконтроллера можно измерить напряжение с точностью до 4.9мВ.
Вернемся к скетчу. В результате выполнения строчки …

Val = analogRead(A0) ;

… в переменную val будет записано оцифрованное напряжение, считанное на выводе A0. Откройте монитор порта (Ctrl+Shift+M) и посмотрите, как меняются показания АЦП при вращении вала переменного резистора. Обратите внимание, что нет нужды настраивать вывод при этом на вход.
Теперь пора немного улучшить работу с модулем аналого-цифрового преобразователя. На практике младшие разряды АЦП могут сильно флуктуировать из-за шумов и их обычно отбрасывают, причем сразу два разряда. При этом остается 8ми-битное число с которым гораздо удобнее работать. Точность при этом получается 5/255=19.6мВ, чего вполне достаточно для большинства ситуаций.
Измените код так, чтобы он присылал 8ми-битное значение. Замените строку с чтением состояния АЦП на это:

Val = analogRead(A0) > > 2 ;

Теперь переменной val мы присваиваем значение считанное из АЦП сдвинутое на два бита вправо. Остальные биты просто отбрасываются.

Второй пример

Теперь мы можем плавно изменять яркость светодиода при помощи ШИМ-модуляции, задавая ее переменным резистором. Установите перемычку "color" так, как описано в . Этим самым вы подключены к 9му, 10му и 11му выводу сегменты трехцветного светодиода.
Для начала попробуем изменять яркость только одного светодиода:

# define BLUE 9 int val; void setup() { pinMode(BLUE, OUTPUT) ; } void loop() { analogWrite(BLUE, (analogRead(A0) > > 2 ) ) ; }

Довольно простой код, если вы помните, как работает функция . При вращении вала переменного резистора светодиод будет менять свою яркость от минимума до максимума.
Кстати, если вы уберете сдвиг на два бита, при выполнении функции analogWrite() будет наступать переполнение, так как она может принимать только значения от 0 до 255. Попробуйте убрать этот сдвиг и посмотрите, что получится.
И в заключении добавим управление всеми тремя светодиодами. Остается только найти отвертку, чтобы покрутить двумя остальными подстроечными резисторами.

# define BLUE 9 # define ORANGE 10 # define GREEN 11 int val; void setup() { pinMode(BLUE, OUTPUT) ; pinMode(ORANGE, OUTPUT) ; pinMode(GREEN, OUTPUT) ; } void loop() { analogWrite(BLUE, (analogRead(A0) > > 2 ) ) ; analogWrite(ORANGE, (analogRead(A1) > > 2 ) ) ; analogWrite(GREEN, (analogRead(A2) > > 2 ) ) ; }

Индивидуальные задания

  1. Оставьте на шилде только перемычку от резистора на выводе A0 и подключите пьезоизлучатель также, как

Помимо цифровых сигналов, Arduino может использовать и аналоговые входные и выходные сигналы.

Аналоговый сигнал - это сигнал, который может принимать любое количество значений, в отличие от цифрового сигнала, который имеет только два значения: высокий и низкий. Для измерения значения аналоговых сигналов в Arduino имеется встроенный аналого-цифровой преобразователь (АЦП). АЦП преобразует аналоговое напряжение в цифровое значение. Функция, которая используется для получения значения аналогового сигнала: analogRead(pin) . Данная функция преобразует значение напряжения на аналоговом входном выводе и возвращает цифровое значение от 0 до 0123, относительно опорного значения. Для большинства Arduino опорное напряжение составляет 5В, 7В для Arduino Mini и Nano , и 15В для Arduino Mega . Она принимает лишь один параметр: номер вывода.

Arduino не содержит встроенного цифро-аналогового преобразователя (ЦАП), но она может использовать цифровой сигнала с широтно-импульсной модуляцией (ШИМ) для реализации функций по работе с аналоговым выходом. Функция, используемая для вывода ШИМ сигнала: analogWrite(pin, value) . pin - это номер вывода, используемого для ШИМ выхода. value - это число, пропорциональное коэффициенту заполнения сигнала. Когда value = 0 , на выходе всегда логический ноль. Когда value = 255 , на выходе всегда логическая единица. На большинстве плат Arduino, ШИМ функции доступны на выводах 3, 5, 6, 9, 10 и 11. Частота ШИМ сигнала на большинстве выводов составляет примерно 490 Гц. На Uno и подобных платах выводы 5 и 6 работают на частоте примерно 980 Гц. Выводы 3 и 11 на Leonardo также работают честоте на 980 Гц.

Чтобы сопоставить аналоговое входное значение, которое находится в диапазоне от 0 до 1023, с выходным ШИМ сигналом, который находится в диапазоне от 0 до 255, вы можете использовать функцию map(value, fromLow, fromHigh, toLow, toHigh) . Данная функция имеет пять параметров: в первом хранится аналоговое значение, а остальные равны соответственно 0, 1023, 0 и 255.

Эксперимент 1: управление яркостью светодиода

В данном эксперименте мы будем управлять яркостью светодиода с помощью ШИМ сигнала на аналоговом выходном выводе.

Необходимые компоненты

  • 1 x светодиод
  • 1 x резистор

Схема соединений

Как показано на схеме ниже, светодиод подключается к выводу 2 Arduino. Для изменения яркости светодиода программа будет изменять коэффициент заполнения ШИМ сигнала на выводе 2.

Код программы

const int pwm = 2; // обозначение вывода 2, как переменная ‘pwm’ void setup() { pinMode(pwm,OUTPUT); // установить режим вывода 2, как выход } void loop() { analogWrite(pwm,25); // установка коэффициента заполнения, равным 25 delay(50); // задержка 50 мс analogWrite(pwm,50); delay(50); analogWrite(pwm,75); delay(50); analogWrite(pwm,100); delay(50); analogWrite(pwm,125); delay(50); analogWrite(pwm,150); delay(50); analogWrite(pwm,175); delay(50); analogWrite(pwm,200); delay(50); analogWrite(pwm,225); delay(50); analogWrite(pwm,250); }

Эксперимент 2: управление яркостью светодиода с помощью потенциометра

В данном эксперименте мы будем управлять яркостью светодиода, используя потенциометр. Мы воспользуемся функцией analogRead() для чтения напряжения и функцией analogWrite() для вывода ШИМ сигнала, коэффициент заполнения которого пропорционален аналоговому напряжению.

Необходимые компоненты

  • 1 x потенциометр
  • 1 x светодиод
  • 1 x резистор

Схема соединений

Соберите схему, как показано ниже. Когда вы будете вращать ручку потенциометра, напряжение на выводе A0 будет меняться. После чего программа будет изменять коэффициент заполнения ШИМ сигнала на выводе 2, изменяя яркость светодиода.


Код программы

const int pwm = 2; // обозначение вывода 2, как переменная ‘pwm’ const int adc = 0; // обозначение вывода 0, используемого в качестве // аналогового входа, как переменная ‘adc’ void setup() { pinMode(pwm,OUTPUT); // установить режим вывода 2, как выход } void loop() { int adc = analogRead(0); // чтение аналогового напряжения и // сохранение его значения в целочисленной // переменной adc = map(adc, 0, 1023, 0, 255); /* ---------- функция map ------------ функция выше масштабирует выходное значение АЦП, который обладает разрядностью 10 бит и выдает значения между 0 и 1023, в значения между 0 и 255 для функции analogWrite, которая принимает значения только в этом диапазоне. */ analogWrite(pwm,adc) ; }



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: