Amateur Radio Station R9AL

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

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

На плате Arduino UNO R3 аналоговые пины имеют названия: A0-A5 (14 - 19).

Аналоговые входы могут использоваться как цифровые выводы. Например, уже знакомая нам программа Blink, но со светодиодом подключенным к выводу A0:



Можно написать так:
void setup()
{
  pinMode(A0, OUTPUT);
}

void loop()
{
  digitalWrite(A0, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(A0, LOW);
  delay(1000); // Wait for 1000 millisecond(s)
}


Но можно и так:
void setup()
{
  pinMode(14, OUTPUT);
}

void loop()
{
  digitalWrite(14, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(14, LOW);
  delay(1000); // Wait for 1000 millisecond(s)
}

Функция analogRead()

      Рассмотрим работу аналоговых портов как в режиме аналогового входа, т.е. если мы запрограммируем аналоговый пин, например A0 как вход, то подавай на него некоторое напряжение - то сможем получить его цифровое значение. Считывание значение с аналогового входа занимает примерно 100 микросекунд (0.0001 сек), т.е. максимальная частота считывания приблизительно 10,000 раз в секунду.

Соберём следующую схему:



И напишем простую программу:
void setup() {
  Serial.begin (9600); 
  pinMode(14, INPUT); 
}

void loop() {
  int x;               // вводим переменную x, типа int
   x = analogRead(14); // переменной x присваиваем значение считанной с ввода A0 (14)
   Serial.print(x);    // выводим значение x в монитор порта
   Serial.println("");
   delay(1000);        // просто подождем секундочку :)
}
Запустив моделирование и устанавливая различные значения напряжения ан выходе источника питания мы будем видеть в мониторе порта различные значения:



Например, для 0В - 0, для 1В - 205, для 2В - 409, для 3В - 614, для 4В - 818, и, наконец, для 5В - 1023, это максимальное значение. Программа выдает нам значение, которое формируется на выходе АЦП из диапазона от 0 до 1023, т.е. мы модем измерять напряжение от 0 до 5 вольт, с шагом примерно 0.005 вольт. Это не очень удобно, изменим программу так, чтобы значение выводилось в вольтах. Для этого, найдем сколько приходится на один вольт (1023/5) и разделим считанное значение на это число:
void setup() {
  Serial.begin (9600); 
  pinMode(14, INPUT); 
}

void loop() {
  float x;                             // вводим переменную x, типа float (переменная с плавающей точкой)
  x = float (analogRead(14))/(1023/5); // делим считанное значение на (1023/5), и преобразуем в тип float

   Serial.print(x);                    // выводим измеренное напряжение в монитор порта
   Serial.println("V");                // выводим букву V, чтобы было понятно, что это напряжение
   delay(1000);                        // просто подождем секундочку :)
}
Попробуем теперь измерять напряжение на резисторном делителе напряжения:



Если собрать схему из двух резисторов номиналом 51к и 1к, первый резистор подключить к +5в а второй к общему проводу, то окажется, что падение напряжения на первом резисторе составит 0,1в. В данном случае, резистор сопротивлением 51 кОм называется подтягивающим резистором. А если нет возможности подключить подтягивающий резистор? Ведь очевидно если собрать вот такую схему:



то наш вольтметр будет показывать 0в, не зависимо от сопротивления резистора. Но есть выход! Если в нашу программу добавить всего одну строчку:
void setup() {
  Serial.begin (9600); 
  pinMode(14, INPUT); 
}

void loop() {
  float x;                             // вводим переменную x, типа float (переменная с плавающей точкой)
  digitalWrite(14, HIGH);              // !!!!!!!!
  x = float (analogRead(14))/(1023/5); // делим считанное значение на (1023/5), и преобразуем в тип float

   Serial.print(x);                    // выводим измеренное напряжение в монитор порта
   Serial.println("V");                // выводим букву V, чтобы было понятно, что это напряжение
   delay(1000);                        // просто подождем секундочку :)
}
то вольтметр опять начнет измерять!



Что же произошло? Все дело в том, что аналоговые выводы имеют подтягивающие резисторы работающие как и на цифровых выводах. Включение резисторов производится командой
  digitalWrite(14, HIGH);  
Разброс напряжений и шаг может быть изменен функцией analogReference()

Функция analogReference()

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



Возможное значение:

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







Copyright © R9AL 2021 Все права защищены

Рейтинг@Mail.ru