• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

unreg

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

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

nikolz

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

unreg

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

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

unreg

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

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

tema

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