Arduino adc reading

Analog Read Serial

This example shows you how to read analog input from the physical world using a potentiometer. A potentiometer is a simple mechanical device that provides a varying amount of resistance when its shaft is turned. By passing voltage through a potentiometer and into an analog input on your board, it is possible to measure the amount of resistance produced by a potentiometer (or pot for short) as an analog value. In this example you will monitor the state of your potentiometer after establishing serial communication between your Arduino and your computer running the Arduino Software (IDE).

Hardware Required

10k ohm Potentiometer

Circuit

Connect the three wires from the potentiometer to your board. The first goes from one of the outer pins of the potentiometer to ground. The second goes from the other outer pin of the potentiometer to 5 volts. The third goes from the middle pin of the potentiometer to the analog pin A0.

By turning the shaft of the potentiometer, you change the amount of resistance on either side of the wiper, which is connected to the center pin of the potentiometer. This changes the voltage at the center pin. When the resistance between the center and the side connected to 5 volts is close to zero (and the resistance on the other side is close to 10k ohm), the voltage at the center pin nears 5 volts. When the resistances are reversed, the voltage at the center pin nears 0 volts, or ground. This voltage is the analog voltage that you’re reading as an input.

The Arduino boards have a circuit inside called an analog-to-digital converter or ADC that reads this changing voltage and converts it to a number between 0 and 1023. When the shaft is turned all the way in one direction, there are 0 volts going to the pin, and the input value is 0. When the shaft is turned all the way in the opposite direction, there are 5 volts going to the pin and the input value is 1023. In between, analogRead() returns a number between 0 and 1023 that is proportional to the amount of voltage being applied to the pin.

Schematic

In the sketch below, the only thing that you do in the setup function is to begin serial communications, at 9600 bits of data per second, between your board and your computer with the command:

Next, in the main loop of your code, you need to establish a variable to store the resistance value (which will be between 0 and 1023, perfect for an int datatype) coming in from your potentiometer:

int sensorValue = analogRead(A0);

Finally, you need to print this information to your serial monitor window. You can do this with the command Serial.println() in your last line of code:

Now, when you open your Serial Monitor in the Arduino Software (IDE) (by clicking the icon that looks like a lens, on the right, in the green top bar or using the keyboard shortcut Ctrl+Shift+M), you should see a steady stream of numbers ranging from 0-1023, correlating to the position of the pot. As you turn your potentiometer, these numbers will respond almost instantly.

See Also:

BareMinimum — The bare minimum of code needed to start an Arduino sketch.

Blink — Turn an LED on and off.

DigitalReadSerial — Read a switch, print the state out to the Arduino Serial Monitor.

Fade — Demonstrates the use of analog output to fade an LED.

Источник

Аналого-цифровые преобразования — АЦП

Не секрет, что все величины в физическом мире носят аналоговый характер. Для измерения этих величин, люди придумали множество различных приборов. Так, например, термометр позволяет узнать температуру вещества, барометр — давление газа, гигрометр — влажность воздуха. А с помощью весов можно измерить вес тела.

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

Чтобы автоматизировать процесс измерения аналоговых величин, и возложить эту задачу на электронные приборы, инженеры создали особое устройство, называемое аналого-цифровым преобразователем (АЦП). Это устройство позволяет превращать аналоговый сигнал в цифровой код, пригодный для использования в ЭВМ.

В робототехнике АЦП являются важной составляющей системы датчиков машины. Акселерометр, гироскоп (гиротахометр), барометр, магнитометр, и даже видеокамера — все эти приборы соединяются с центральным процессором с помощью АЦП.

Конструктивно, АЦП может находиться в одном корпусе с микропроцессором или микроконтроллером, как в случае Arduino Uno. В противном случае, как и все современные электронные устройства, АЦП может быть оформлен в виде отдельной микросхемы, например MCP3008:

Следует отметить, что существует и устройство с обратной функцией, называемое цифро-аналоговым преобразователем (ЦАП, DAC). Оно позволяет переводить цифровой сигнал в аналоговый. Например, во время проигрывания мелодии на мобильном телефоне происходит преобразование цифрового кода из MP3 файла в звук, который вы слышите у себя в наушниках.

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

Функции работы с АЦП

На этом уроке изучать работу АЦП мы будем с помощью платформы Arduino. В используемой нами модели Arduino Uno, наряду с обычными выводами общего назначения (к которым мы уже подключали светодиоды и кнопки) есть целых шесть аналоговых входов. В других версиях Arduino таких входов может быть и больше, например, у Arduino Mega их 16.

На карте Arduino Uno аналоговые входы имеют буквенно-цифровые обозначения A0, A1, …, A5 (снизу слева).

Во время работы всё с теми же кнопками, мы познакомились с функцией digitalRead, которая умеет считывать цифровой сигнал с определенного входа контроллера. У этой функции существует аналоговая версия analogRead, которая может делать то же самое, но только для аналогового сигнала.

результат = analogRead( номер_контакта );

после вызова этой функции, микроконтроллер измерит уровень аналогового сигнала на заданном контакте, и сохранит результат работы АЦП в переменную «результат». При этом результатом функции analogRead будет число от 0 до 1023.

Разрядность АЦП

Надо заметить, что число 1023 здесь появилось неспроста. Дело в том, что у каждого устройства АЦП есть такой важный параметр как разрядность. Чем больше значение этого параметра, тем точнее работает прибор. Предположим, что у нас есть АЦП с разрядностью 1. Подавая на вход любое напряжения от 0 до 2,5 Вольт, на выходе мы получим 0. Любое же напряжение от 2,5 до 5 вольт даст нам единицу. То есть 1-битный АЦП сможет распознать только два уровня напряжения. Графически это можно изобразить следующим образом:

АЦП с разрядностью 2 распознает уже четыре уровня напряжения:

  • от 0 до 1,25 — это 0;
  • от 1,25 до 2,5 — это 1;
  • от 2,5 до 3,75 — это 2;
  • наконец, от 3,75 до 5 — это 3.

На следующих двух картинках изображена работа АЦП с разрядностью 2 и 3 бит:

В Arduino Uno установлен 10-битный АЦП, и это значит, что любое напряжение на аналоговом входе в диапазоне от 0 до 5 вольт будет преобразовано в число с точностью 1/1024 вольта. На графике будет сложно изобразить столько ступенек. Имея такую точность, 10-битный АЦП может «почувствовать» изменение напряжение на входе величиной всего 5 милливольт.

Опорное напряжение

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

от 0 до опорного напряжения

Это изменение повлечет за собой изменение формулы расчет точности АЦП:

точность = опорное напряжение/1024

Опорное напряжение определяет границу диапазона, с которым будет работать АЦП.

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

Что если вы питаете микроконтроллер от другого источника? Допустим у вас есть четыре NiMh аккумулятора на 1.2 Вольта. В сумме они дадут 4.8 Вольта (пусть они немного разряжены, ведь в действительности их заряжают до 1.4 Вольта). Точность измерения будет равна 4.8/1024. Это следует учесть в нашей программе.

Наконец рассмотрим случай, когда мы питаем Arduino Uno одним напряжением, а в качестве опорного хотим установить совсем другое, например, 3.3 Вольта. Что делать? Для такого варианта на Arduino Uno есть специальный вывод Vref. Чтобы решить проблему, нам нужно подать на этот контакт напряжение 3.3 Вольта, и разрешить использование внешнего источника опорного напряжения функцией:

которую следует вызвать внутри функции setup нашей программы.

Также следует учитывать, что результат измерения значения напряжения не может превышать границы диапазона. Если мы выбираем в качестве опорного напряжения 3.3 Вольта, а поступающий сигнал будет с большим напряжением, то мы получим неправильное значение напряжения, поскольку АЦП «не знает» о наличии более высокого напряжения.

Программа

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

Теперь загружаем программу на Arduino, и переходим к измерениям.

Подключение

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

Теперь откроем окно COM-монитора в Arduino IDE, и посмотрим какие значение выдает нам АЦП:

Что означает число 314? Вспомним, что 10-битный АЦП разбивает диапазон от 0 до 5 вольт на 1024 части. Значит точность 10-битного АЦП — 5/1024. Зная точность, мы можем записать формулу для преобразования показаний АЦП к вольтам:

где V — измеренное напряжение на батарейке;
ADC — результат работы функции analogRead.

Подставим эту формулу в программу и снова попробуем измерить заряд батарейки!

Уже больше похоже на правду.

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

На нашем портале можно найти несколько уроков, выполнение которых зависит от понимания темы АЦП: датчик температуры, ёмкостный датчик, фоторезистор, потенциометр и аналоговый джойстик. А в совокупности с еще одной важной темой — ШИМ, применение АЦП позволит создать диммер светодиодной лампы и регулятор хода двигателя. Успехов!

Источник

analogReadResolution()

Description

analogReadResolution() is an extension of the Analog API for the Zero, Due, MKR family, Nano 33 (BLE and IoT) and Portenta.

Sets the size (in bits) of the value returned by analogRead() . It defaults to 10 bits (returns values between 0-1023) for backward compatibility with AVR based boards.

The Zero, Due, MKR family and Nano 33 (BLE and IoT) boards have 12-bit ADC capabilities that can be accessed by changing the resolution to 12. This will return values from analogRead() between 0 and 4095.
The Portenta H7 has a 16 bit ADC, which will allow values between 0 and 65535.

Syntax

Parameters

bits : determines the resolution (in bits) of the value returned by the analogRead() function. You can set this between 1 and 32. You can set resolutions higher than the supported 12 or 16 bits, but values returned by analogRead() will suffer approximation. See the note below for details.

Returns

Example Code

The code shows how to use ADC with different resolutions.

Notes and Warnings

If you set the analogReadResolution() value to a value higher than your board’s capabilities, the Arduino will only report back at its highest resolution, padding the extra bits with zeros.

For example: using the Due with analogReadResolution(16) will give you an approximated 16-bit number with the first 12 bits containing the real ADC reading and the last 4 bits padded with zeros.

If you set the analogReadResolution() value to a value lower than your board’s capabilities, the extra least significant bits read from the ADC will be discarded.

Using a 16 bit resolution (or any resolution higher than actual hardware capabilities) allows you to write sketches that automatically handle devices with a higher resolution ADC when these become available on future boards without changing a line of code.

Источник

Аналоговые пины

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

В уроке про возможности микроконтроллера мы обсуждали аналоговые входы, т.е. входы, подключенные к АЦП – аналогово-цифровому преобразователю (ADC). Взглянем на распиновку популярных плат (Arduino Nano и Wemos Mini):

Пины, на которых выведен ADC, могут измерять аналоговый сигнал. На плате Nano это пины, маркированные буквой А (A0A7), а у esp8266 такой пин всего один – A0.

Чтение сигнала

“Аналоговые” пины могут принимать напряжение от 0V (GND) до опорного напряжения и преобразовывать его в цифровое значение, просто в какие-то условные единицы. АЦП на AVR и esp8266 имеет разрядность в 10 бит, т.е. мы получаем измеренное напряжение в виде числа от 0 до 1023 .

Функция, которая оцифровывает напряжение, называется analogRead(pin) . Она принимает в качестве аргумента номер аналогового пина и возвращает оцифрованное напряжение. Сам пин должен быть сконфигурирован как INPUT (вход). Нумерация:

  • Arduino Nano:
    • Просто номером А-пина: A0 – 0
    • Как на плате: A0 – A0
    • Порядковым номером GPIO: А0 – 14 , A1 – 15 .. А7 – 21
  • Wemos Mini
    • Просто номером А-пина: A0 – 0
    • Как на плате: A0 – A0

Пример, опрашивающий пин А0:

Хранить полученное значение разумно в переменной типа int , потому что значение варьируется от 0 до 1023.

10k) – можно, но всё равно не рекомендуется этого допускать.

Потенциометры

Аналоговые пины очень часто используются при работе с потенциометрами (переменный резистор). При помощи полученного значения можно влиять на ход работы программы, менять какие-то настройки и тому подобное. У потенциометра всегда три ноги: две крайние и одна центральная. Всё вместе это представляет собой делитель напряжения, который и позволяет менять напряжение в диапазоне 0-VCC: К Arduino потенциометр подключается следующим образом: средний вывод на любой A-пин, крайние – на GND и питание. От порядка подключения GND и питания зависит направление изменения значения. Что касается сопротивления, то читай заметку по делителям напряжения ниже в этом уроке. Чаще всего для МК ставят потенциометры с сопротивлением 10 кОм, но диапазон в принципе очень широк: от 1 кОм до 100 кОм. Чем больше, тем более шумным будет приходить сигнал, а если брать меньше – пойдут потери тока в нагрев потенциометра, а это никому не нужно.

Опорное напряжение (для AVR Arduino)

Опорное напряжение играет главную роль в измерении аналогового сигнала, потому что именно от него зависит максимальное измеряемое напряжение и вообще возможность и точность перевода полученного значения 0-1023 в Вольты. Изучим функцию analogReference(mode) , где mode:

  • DEFAULT : опорное напряжение равно напряжению питания МК. Активно по умолчанию
  • INTERNAL : встроенный источник опорного на 1.1V (для ATmega168 или ATmega328P) и 2.56V (на ATmega8)
  • INTERNAL1V1 : встроенный источник опорного на 1.1V (только для Arduino Mega)
  • INTERNAL2V56 : встроенный источник опорного на 2.56V (только для Arduino Mega)
  • EXTERNAL : опорным будет считаться напряжение, поданное на пин AREF

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

В режиме DEFAULT мы можем оцифровать напряжение от 0 до напряжения питания VCC. Если напряжение питания 4.5 Вольта, и мы подаём 4.5 Вольт – получим оцифрованное значение 1023. Если подаём 5 Вольт – опять же получим 1023, т.к. выше опорного. Это правило работает и дальше, главное не превышать 5.5 Вольт. Как измерять более высокое напряжение, читайте ниже.

Что касается точности: при питании от 5V и режиме DEFAULT мы получим точность измерения напряжения (5 / 1024)

4.9 милливольт. Поставив INTERNAL мы можем измерять напряжение от 0V до 1.1V с точностью (1.1 / 1024)

0.98 милливольт. Весьма неплохо, особенно если баловаться с делителем напряжения.

Что касается внешнего источника опорного напряжения: нельзя подавать напряжение меньше 0V (отрицательное) или выше 5.5V в качестве внешнего опорного в пин AREF. Также при подключении внешнего опорного напряжения нужно вызвать analogReference(EXTERNAL) до первого вызова функции analogRead() (начиная с запуска программы), иначе можно повредить микроконтроллер!

Чтобы “на лету” переключаться между внутренними и внешним опорными, можно подключить его на AREF через резистор на

5 кОм. Вход AREF имеет собственное сопротивление в 32 кОм, поэтому реальное опорное будет вычисляться по формуле REF = V * 32 / (R + 32), где R – сопротивление резистора (кОм), через которое подключено опорное напряжение V (Вольт). Например для 2.5V получим 2.5 * 32 / (32 + 5) =

2.2V реальное опорное.

Измерение напряжения

0-5 Вольт

Простой пример, как измерить напряжение на аналоговом пине и перевести его в Вольты. Плата питается от 5V.

Таким образом переменная voltage получает значение в Вольтах, от 0 до 5. Чуть позже мы поговорим о более точных измерениях при помощи некоторых хаков. Почему мы делим на 1024, а не на 1023 , ведь максимальное значение измерения с АЦП составляет 1023? Ответ можно найти в даташите:
АЦП при преобразовании отнимает один бит, т.е. 5.0 Вольт он в принципе может измерить только как 4.995, что и получится по формуле выше: 1023 * 5 / 1024 == 4.995.. . Таким образом делить нужно на 1024.

Сильно больше 5 Вольт

Для измерения постоянного напряжения больше 5 Вольт нужно использовать делитель напряжения на резисторах (Википедия). Схема подключения, при которой плата питается от 12V в пин Vin и может измерять напряжение источника (например, аккумулятора):
Код для перевода значения с analogRead() в Вольты с учётом делителя напряжения:

Как выбрать/рассчитать делитель напряжения?

  • Согласно даташиту на ATmega, сумма R1 + R2 не рекомендуется больше 10 кОм для достижения наибольшей точности измерения. В то же время через делитель на 10 кОм будет течь ощутимый ток, что критично для автономных устройств (читай ниже). Если девайс работает от сети или от аккумулятора, но МК не используется в режиме сна – ставим делитель 10 кОм и не задумываемся. Также рекомендуется поставить конденсатор между GND и аналоговым пином для уменьшения помех.
  • Если девайс работает от аккумулятора и микроконтроллер “спит”: пусть аккумулятор 12V, тогда через 10 кОм делитель пойдёт ток 1.2 мА. Сам микроконтроллер в режиме сна потребляет

1 мкА, что в тысячу раз меньше! На самом деле можно взять делитель с гораздо бОльшим суммарным сопротивлением (но не больше 20 МОм, внутреннего сопротивления самого АЦП), но обязательно поставить конденсатор на

0.1 мкФ между аналоговым пином и GND (вот здесь проводили эксперимент). Таким образом например при при R1+R2 = 10 МОм (не забыть про конденсатор) ток через делитель будет 1.2 мкА, что уже гораздо лучше!
Коэффициент делителя (не тот, который в Википедии) равен (R1 + R2) / R2 . Коэффициент должен быть таким, чтобы при делении на него измеряемого напряжения не получилось больше напряжения питания МК. У меня в примере (10 + 4.7) / 4.7

3.13 . Я хочу измерять литиевый аккумулятор с максимальным напряжением 12.8 Вольт. 12.8 / 3.13

4 Вольта – отлично. Например для измерения 36 Вольт я бы взял делитель с плечами 100к и 10к.

  • Можно воспользоваться онлайн-калькулятором.
  • Сильно меньше 5 Вольт

    Для более точных измерений маленького напряжения можно подключить пин AREF к источнику низкого опорного напряжения (об этом было выше), чтобы “сузить” диапазон работы АЦП. Источник может быть как внешний, так и внутренний, например изменив опорное на внутреннее 1.1V ( analogReference(INTERNAL) ) можно измерять напряжение от 0 до 1.1 Вольта с точностью 1.1/1024

    Видео

    Источник