Экспериментирую с ADC пришел вот к таким вводам. Простого объяснения на пальцах на русском не нашел, да и на английском как-то скудно. Прошу сообщество попинать и поправить если что-то неверно. Надеюсь новичкам это может пригодится.
Схема: esp32, потенциометр на GPIO36 (SENSOR VP).
По скетчу.
adc_range (нужен только для пересчета обратно в напряжение) и atten подбираются исходя из характеристик выходного сигнала устройства.
для устройств с выходом
0-1.1V -> adc_range =1.1f, atten = ADC_ATTEN_0db
0-1.5V -> adc_range =1.5f, atten = ADC_ATTEN_2_5db
0-2.2V -> adc_range =2.2f, atten = ADC_ATTEN_6db
0-3.3V -> adc_range =3.3f, atten = ADC_ATTEN_11db
Вот теперь "на пальцах" пример:
Пусть у нас есть устройство которое выдает диапазон напряжения от 0-3.3V (потенциометр). Но только мы об этом не знаем и поставили настройки от балды, например:
adc_range =1.1f, atten = ADC_ATTEN_0db
Запускаем, смотрим монитор порта. Видим цифры разделенные двоеточием. Слева - значение АЦП. справа пересчитаный вольтаж. Теперь покрутим потенциометр. Цифры меняются от 0 до 1.1V причем верхняя граница достигается задолго до того как потенциометр выйдет на максимум. Это говорит о том, что наша настройка неверна, мы попросту потеряли половину диапазона аналогового сигнала. Очевидно, что сделав правильную настройку adc_range =3,3f, atten = ADC_ATTEN_11db мы сможем измерить весь диапазон напряжениея приходящий с потенциометра. А что делать если у нас устройство выдает например от 0 - 5V? Тут, чтобы не спалить вход esp, необходимо подключаться через делитель напряжения который нужно расчитать. А если у нас устройство выдает 0-2V? Здесь мы можем выбрать настройку adc_range =2.2f, atten = ADC_ATTEN_6db и все будет нормально, только чуток пострадает точность, т.к. теперь уже невесь диапазон АЦП будет использован. Т.е. при 9 битах точности на максимальных 2V от устройства мы получим значение ~466, а не максимально возможное 511. Ну еще мы можем привести аналоговый сигнал к более низкому значению (от 0-1,5V) используя все тот же делитель и использовать настройку adc_range =1.5f, atten = ADC_ATTEN_2_5db, но что тут с точностью будет я не знаю. Битность задаваемая функцией adc1_config_width влияет на качество оцифровки сигнала. Чем выше битность тем точнее оцифровка (больше даиапазон АЦП). Что бы было понятнее: 0-3.3V при 12 битах будет масштабироваться на 4096 единиц АЦП, а при 9 битах, всего на 512. И если для нас критичны минимальные изменения аналогового сигнала, то и битность нужно выбирать соответствующую
Cкетч:
Схема: esp32, потенциометр на GPIO36 (SENSOR VP).
По скетчу.
adc_range (нужен только для пересчета обратно в напряжение) и atten подбираются исходя из характеристик выходного сигнала устройства.
для устройств с выходом
0-1.1V -> adc_range =1.1f, atten = ADC_ATTEN_0db
0-1.5V -> adc_range =1.5f, atten = ADC_ATTEN_2_5db
0-2.2V -> adc_range =2.2f, atten = ADC_ATTEN_6db
0-3.3V -> adc_range =3.3f, atten = ADC_ATTEN_11db
Вот теперь "на пальцах" пример:
Пусть у нас есть устройство которое выдает диапазон напряжения от 0-3.3V (потенциометр). Но только мы об этом не знаем и поставили настройки от балды, например:
adc_range =1.1f, atten = ADC_ATTEN_0db
Запускаем, смотрим монитор порта. Видим цифры разделенные двоеточием. Слева - значение АЦП. справа пересчитаный вольтаж. Теперь покрутим потенциометр. Цифры меняются от 0 до 1.1V причем верхняя граница достигается задолго до того как потенциометр выйдет на максимум. Это говорит о том, что наша настройка неверна, мы попросту потеряли половину диапазона аналогового сигнала. Очевидно, что сделав правильную настройку adc_range =3,3f, atten = ADC_ATTEN_11db мы сможем измерить весь диапазон напряжениея приходящий с потенциометра. А что делать если у нас устройство выдает например от 0 - 5V? Тут, чтобы не спалить вход esp, необходимо подключаться через делитель напряжения который нужно расчитать. А если у нас устройство выдает 0-2V? Здесь мы можем выбрать настройку adc_range =2.2f, atten = ADC_ATTEN_6db и все будет нормально, только чуток пострадает точность, т.к. теперь уже невесь диапазон АЦП будет использован. Т.е. при 9 битах точности на максимальных 2V от устройства мы получим значение ~466, а не максимально возможное 511. Ну еще мы можем привести аналоговый сигнал к более низкому значению (от 0-1,5V) используя все тот же делитель и использовать настройку adc_range =1.5f, atten = ADC_ATTEN_2_5db, но что тут с точностью будет я не знаю. Битность задаваемая функцией adc1_config_width влияет на качество оцифровки сигнала. Чем выше битность тем точнее оцифровка (больше даиапазон АЦП). Что бы было понятнее: 0-3.3V при 12 битах будет масштабироваться на 4096 единиц АЦП, а при 9 битах, всего на 512. И если для нас критичны минимальные изменения аналогового сигнала, то и битность нужно выбирать соответствующую
Cкетч:
Код:
#include <Arduino.h>
#include <driver/adc.h>
int range = 512;
float adc_range = 2.2f;
adc_atten_t atten = ADC_ATTEN_6db;
void setup() {
Serial.begin(115200);
Serial.println("Ready");
adc1_config_width(ADC_WIDTH_9Bit);
adc1_config_channel_atten(ADC1_CHANNEL_0, atten);
}
void loop() {
if (Serial.available() > 0)
{
int key = Serial.read();
switch (key)
{
case 48:
adc1_config_width(ADC_WIDTH_9Bit);
range = 512;
Serial.print("9Bit: ");
break;
case 49:
adc1_config_width(ADC_WIDTH_10Bit);
range = 1024;
Serial.print("10Bit: ");
break;
case 50:
adc1_config_width(ADC_WIDTH_11Bit);
range = 2048;
Serial.print("11Bit: ");
break;
case 51:
adc1_config_width(ADC_WIDTH_12Bit);
range = 4096;
Serial.print("12Bit: ");
break;
default:
range = 512;
break;
}
adc1_config_channel_atten(ADC1_CHANNEL_0, atten);
}
int in = adc1_get_raw(ADC1_CHANNEL_0);
float voltage = in * adc_range/range;
Serial.print(in, DEC);
Serial.print (": ");
Serial.println(voltage);
delay(1000);
}