← До всіх проєктів
Сенсори Середній

Точний вольтметр на ADS1115: 16 біт замість «кривого» АЦП ESP32

Вбудований АЦП ESP32 має мертву зону біля нуля, стелю 3.1 В і нелінійність. Зовнішній 16-бітний ADS1115 по I2C міряє з кроком 0.125 мВ. Порівнюємо обидва на одному потенціометрі й міряємо напругу акумулятора 12 В через дільник.

Складність
Середній
Час
45 min
Категорія
Сенсори
Оновлено

Про проєкт

analogRead() на ESP32 зручний, але неточний: до ~0.1 В він показує нуль, вище ~3.1 В — максимум, а посередині помиляється на десятки мілівольт. Для індикатора заряду чи потенціометра цього досить, для вимірювального приладу — ні. ADS1115 — 16-бітний АЦП із програмованим підсилювачем і власним джерелом опорної напруги: 4 входи, I2C і похибка в частки відсотка. Порівнюємо його з вбудованим АЦП і робимо вольтметр для 12-вольтового акумулятора.

Що знадобиться

  • ESP32 DevKit
  • Модуль ADS1115 (фіолетова плата)
  • Потенціометр 10 кОм
  • Резистори 100 кОм і 22 кОм для дільника
  • Бібліотека Adafruit ADS1X15

Схема

ADS1115 Підключення
VDD / GND 3V3 / GND
SDA / SCL GPIO21 / GPIO22
ADDR GND → адреса 0x48
A0 повзунок потенціометра (він же на GPIO34 для порівняння)
A1 середня точка дільника 100 кОм / 22 кОм від «+12 В»

Потенціометр: крайні виводи на 3V3 і GND. Дільник: «+12 В» → 100 кОм → A1 → 22 кОм → GND, земля акумулятора з'єднана з GND ESP32.

Налаштування підсилювача (GAIN)

Діапазон вимірювань задає setGain():

GAIN Діапазон Крок (16 біт)
GAIN_TWOTHIRDS ±6.144 В 0.1875 мВ
GAIN_ONE ±4.096 В 0.125 мВ
GAIN_TWO (за замовч.) ±2.048 В 0.0625 мВ
GAIN_FOUR … GAIN_SIXTEEN ±1.024 … ±0.256 В до 0.0078 мВ

Важливо: діапазон ±6.144 В не означає, що на вхід можна подати 6 В. Напруга на будь-якому вході не може виходити за межі GND − 0.3 В … VDD + 0.3 В. При живленні 3.3 В це максимум 3.6 В. Усе більше — тільки через дільник. Симулятор попередить про перевищення.

Розрахунок дільника

U(вх) = U(бат) × R2 / (R1 + R2) = 14.4 × 22 / 122 ≈ 2.6 В навіть для акумулятора на зарядці (14.4 В) — із запасом у діапазоні ±4.096 В. У коді множимо назад на (100 + 22) / 22. Дільник на 122 кОм бере з акумулятора лише ~0.1 мА.

Код

// Вольтметр: ADS1115 (16 біт) проти вбудованого АЦП ESP32 + напруга акумулятора
#include <Adafruit_ADS1X15.h>

Adafruit_ADS1115 ads;
const float DIVIDER = (100.0 + 22.0) / 22.0;   // дільник 100 кОм / 22 кОм на A1

void setup() {
  Serial.begin(115200);
  ads.setGain(GAIN_ONE);   // ±4.096 В, крок 0.125 мВ
  if (!ads.begin(0x48)) {
    Serial.println("ADS1115 не знайдено");
    while (true) delay(1000);
  }
}

void loop() {
  float pot = ads.computeVolts(ads.readADC_SingleEnded(0));
  float naive = analogRead(34) * 3.3 / 4095.0;    // «наївний» перерахунок
  float mv = analogReadMilliVolts(34) / 1000.0;   // з заводською калібровкою
  float battery = ads.computeVolts(ads.readADC_SingleEnded(1)) * DIVIDER;
  Serial.printf("A0: ADS1115 %.4f В | analogRead %.3f В | analogReadMilliVolts %.3f В\n", pot, naive, mv);
  Serial.printf("Акумулятор: %.3f В\n", battery);
  delay(1000);
}

Що побачите

Покрутіть потенціометр до краю. Біля нуля ESP32 показує 0 В, коли ADS1115 ще бачить 0.05 В, а біля 3.3 В вбудований АЦП «впирається» в 3.1 В. analogReadMilliVolts() помітно краще за наївну формулу, але шум ±10–20 мВ залишається.

Корисно знати

  • Швидкість. За замовчуванням 128 вимірювань на секунду (~8 мс на одне). setDataRate(RATE_ADS1115_860SPS) — швидше, але шумніше.
  • Диференційний режим readADC_Differential_0_1() міряє різницю між A0 і A1, наприклад на шунті для вимірювання струму.
  • ADS1015 — 12-бітний брат із тією ж розпіновкою: у коді клас Adafruit_ADS1015. Переплутаєте класи — отримаєте результати, зсунуті в 16 разів.
  • Чотири ADS1115 на одній шині: ADDR до GND, VDD, SDA або SCL дає адреси 0x48–0x4B.