Делюсь опытом как работает ADC

unreg

New member
Экспериментирую с 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кетч:
Код:
#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);
}
 

nikolz

Well-known member
вот еще несколько советов новичкам:
прежде, чем ввязываться что-то делать на ESP, купите тестер за 5 долларов.
------------------------------
Определить диапазон напряжений от датчика можно так:
---------------------
1) прочитать документацию на датчик, там все указано, для грамотных;
------------------------
2) взять тестер и измерить напряжение на выходе датчика (потенциометра);
-----------------
 

unreg

New member
100%. Но тестер прокатит пожалуй только для потенциометра, а доки это действительно для грамотных коими новички не являются:)
 

nikolz

Well-known member
100%. Но тестер прокатит пожалуй только для потенциометра, а доки это действительно для грамотных коими новички не являются:)
чтобы в доке узнать какое напряжение надо лишь уметь складывать из буков слова.
 

unreg

New member
Хотел подредактировать топ, что это не способ подобрать нужные настройки и что читать доки обязательно, но тут нельзя редактировать к сожалению
 

nikolz

Well-known member
Хотел подредактировать топ, что это не способ подобрать нужные настройки и что читать доки обязательно, но тут нельзя редактировать к сожалению
раньше было можно, но модераторы борются с чем-то поэтому уже незя.
 

tema

New member
Спасибо за собранную разжеванную информацию, действительно, стандартный analogRead() не "взлетает" на esp32, по крайне мере у меня.
У меня вопрос следующего плана, я залил скрипт из поста и запустил, на входе у меня 1,63-1,65В (если верить тестеру за 5 баксов ;)), но и расчетно примерно такое напряжение и должно быть, но вот результаты немного отличаются:
511: 2.20
511: 2.20
511: 2.20
511: 2.20
496: 2.13
482: 2.07
463: 1.99
445: 1.91
422: 1.81
401: 1.72
392: 1.68
373: 1.60
366: 1.57
342: 1.47
336: 1.44
334: 1.44
316: 1.36
307: 1.32
303: 1.30
304: 1.31
296: 1.27
297: 1.28
303: 1.30
273: 1.17
301: 1.29
301: 1.29
304: 1.31
304: 1.31
314: 1.35
305: 1.31
318: 1.37
318: 1.37
324: 1.39
320: 1.37
338: 1.45
333: 1.43
331: 1.42
317: 1.36
341: 1.47
325: 1.40
328: 1.41
324: 1.39
319: 1.37
327: 1.41
332: 1.43
338: 1.45
328: 1.41
328: 1.41
330: 1.42
343: 1.47
341: 1.47
347: 1.49
355: 1.53
373: 1.60
383: 1.65
396: 1.70
402: 1.73
414: 1.78
422: 1.81
432: 1.86
424: 1.82
446: 1.92
455: 1.96
453: 1.95
456: 1.96
457: 1.96
463: 1.99
453: 1.95
449: 1.93
450: 1.93
438: 1.88
432: 1.86
426: 1.83
404: 1.74
391: 1.68
378: 1.62
366: 1.57
362: 1.56
349: 1.50
337: 1.45
337: 1.45
332: 1.43
317: 1.36
312: 1.34
305: 1.31
307: 1.32
306: 1.31
307: 1.32
304: 1.31
310: 1.33
308: 1.32
321: 1.38
344: 1.48
358: 1.54
369: 1.59
402: 1.73
415: 1.78
443: 1.90
467: 2.01
479: 2.06
511: 2.20
511: 2.20
511: 2.20
511: 2.20
511: 2.20
511: 2.20
511: 2.20
511: 2.20
и дело даже не в том что вместо 1,63 я вижу 2,2, а в том, что напряжение на входе не меняется, а результат меняется, может подскажите в чем дело, а то я уже совсем устал правду искать)
 

unreg

New member
@tema, а что в качестве источника сигнала и какой у него диапазон? схема с потенциометром? могу предположить, что источник не стабилен, у меня была похожая ситуация с подстроечным резистором
 

unreg

New member
@tema, а что в качестве источника сигнала и какой у него диапазон? схема с потенциометром? могу предположить, что источник не стабилен, у меня была похожая ситуация с подстроечным резистором
 

tema

New member
Источник "Активный однофазный трансформатор напряжения модуль AC датчик выходного напряжения для Arduino Mega" 64.32 руб. 10% СКИДКА|Активный однофазный трансформатор напряжения модуль AC датчик выходного напряжения для Arduino Mega-in Интегральные схемы from Электронные компоненты и принадлежности on Aliexpress.com | Alibaba Group
Так же пробовал SCT 013-030 (измеритель тока) - тоже показания плавают при стабильном (на мой взгляд) входном напряжении.
Я думал попробовать поставить конденсатор, микрофарад на 10, на вход, может помочь?
Еще сегодня попробую собрать делитель на резисторах, посмотреть, будет ли "плавать" результат.
 

nikolz

Well-known member
Источник "Активный однофазный трансформатор напряжения модуль AC датчик выходного напряжения для Arduino Mega" 64.32 руб. 10% СКИДКА|Активный однофазный трансформатор напряжения модуль AC датчик выходного напряжения для Arduino Mega-in Интегральные схемы from Электронные компоненты и принадлежности on Aliexpress.com | Alibaba Group
Так же пробовал SCT 013-030 (измеритель тока) - тоже показания плавают при стабильном (на мой взгляд) входном напряжении.
Я думал попробовать поставить конденсатор, микрофарад на 10, на вход, может помочь?
Еще сегодня попробую собрать делитель на резисторах, посмотреть, будет ли "плавать" результат.
у вас сигнал с этого модуля тоже плавает
если нет осциллографа то посмотрите тут
 

unreg

New member
Соберите схему с потенциометром, он и есть делитель. Думаю все встанет на свои места:)
 

tema

New member
чтобы ответить,надо схему
Да схема очень проста, это китайское чудо-вольтметр, подсоединен на D35 (ADC0_7) ну и запитан 3,3В, конденсатор не помог.
Да и вообще, что-то не ладится у меня с ESP32, никак не могу пару DHT11/DHT22 к нему подсоединить, иногда работает, но не могу понять закономерность, когда это случается
 
Сверху Снизу