Hướng dẫn đo điện áp 16 bit bằng module ADS1115 với ESP32

Hướng dẫn nối module ADC 16 bit ADS1115 với ESP32 DevKit V1 qua I2C, cài thư viện Adafruit ADS1X15, đọc 4 kênh ra vôn, đo vi sai và chọn gain an toàn.

ADS1115 là bộ chuyển đổi tương tự – số (ADC) 16 bit giao tiếp I2C, có 4 ngõ vào và bộ khuếch đại lập trình được (PGA). Bài viết hướng dẫn nối module ADS1115 với ESP32 DevKit V1, cài thư viện Adafruit ADS1X15, đọc 4 kênh ra vôn, đo vi sai và chọn gain an toàn bằng Arduino IDE.

1. Vì sao nên dùng ADC ngoài cho ESP32?

ESP32 có sẵn ADC 12 bit (giá trị 0–4095), nhưng có ba hạn chế khi cần đo chính xác:

  • Đo không đúng ở hai đầu dải: vùng dưới khoảng 0,15 V và vùng gần 3,3 V.
  • Điện áp tham chiếu khác nhau giữa các chip (thiết kế 1,1 V, thực tế 1,0–1,2 V), nên hai mạch có thể cho hai số đo khác nhau.
  • Các chân thuộc ADC2 (GPIO0, 2, 4, 12–15, 25–27) không đọc được analog khi bật Wi-Fi.

ADS1115 có độ phân giải 16 bit, điện áp tham chiếu riêng trong chip, 4 ngõ vào dùng chung hai dây I2C và không phụ thuộc Wi-Fi.

2. Tìm hiểu module ADS1115

Thông số cơ bản của module ADC 16 bit ADS1115
Thông số Giá trị
IC ADS1115
Độ phân giải 16 bit, kết quả là số có dấu từ −32768 đến 32767
Ngõ vào 4 kênh đơn A0–A3 (đo so với GND) hoặc 2 kênh vi sai
Thang đo (PGA) 6 mức, từ ±6,144 V đến ±0,256 V
Tốc độ lấy mẫu 8–860 mẫu/giây (mặc định 128)
Giao tiếp I2C, 4 địa chỉ 0x48–0x4B chọn bằng chân ADDR
Nguồn cấp 2,0–5,5 V (bài này dùng 3,3 V)
Điện áp ở ngõ vào analog Từ GND đến VDD, tuyệt đối không quá VDD + 0,3 V
Sơ đồ chân module ADC 16 bit ADS1115: VDD, GND, SCL, SDA, ADDR, ALRT, A0 đến A3 và bảng địa chỉ I2C
Các chân của module ADS1115 và địa chỉ I2C theo cách nối chân ADDR (hình vẽ minh họa).

Tùy lô hàng, màu mạch và thứ tự 10 chân có thể khác hình vẽ, vì vậy luôn nối dây theo tên chân in trên mạch. Nếu hàng chân chưa hàn, cần hàn trước khi dùng; cắm lỏng sẽ tiếp xúc chập chờn.

Chân ADDR chọn địa chỉ I2C: nối GND được 0x48, VDD được 0x49, SDA được 0x4A, SCL được 0x4B, nên một bus gắn được tối đa 4 module. Module thường có sẵn điện trở kéo ADDR xuống GND, vì vậy khi để hở địa chỉ là 0x48, cũng là địa chỉ dùng trong bài.

Thang đo và độ lớn 1 bit của ADS1115 theo từng mức gain
Hằng số trong thư viện Hệ số khuếch đại Thang đo 1 bit tương ứng
GAIN_TWOTHIRDS (mặc định của thư viện) 2/3 ±6,144 V 0,1875 mV
GAIN_ONE 1 ±4,096 V 0,125 mV
GAIN_TWO 2 ±2,048 V 0,0625 mV
GAIN_FOUR 4 ±1,024 V 0,03125 mV
GAIN_EIGHT 8 ±0,512 V 0,015625 mV
GAIN_SIXTEEN 16 ±0,256 V 0,0078125 mV

Độ lớn 1 bit bằng thang đo chia cho 32768. Khi đo kênh đơn, kết quả chỉ dùng nửa dương, từ 0 đến 32767. Thang đo không phải là điện áp được phép đưa vào các chân A0–A3 (xem mục 8).

3. Linh kiện cần chuẩn bị

  • ESP32 DevKit V1 30 chân (hoặc bản dùng chip CH340) và cáp USB có truyền dữ liệu.
  • Module ADC 16 bit ADS1115 đã hàn hàng chân.
  • Breadboard MB-102 và dây jumper.
  • Nguồn điện áp để thử: một biến trở 10 kΩ hoặc một viên pin 1,5 V. Phần đo vi sai ở mục 9 cần thêm hai điện trở 10 kΩ.
  • Máy tính đã cài Arduino IDE 2.x.

4. Sơ đồ nối ADS1115 với ESP32

Đấu nối module ADS1115 với ESP32 DevKit V1
ADS1115 ESP32 DevKit V1 Ghi chú
VDD 3V3 Cấp 3,3 V để bus I2C cùng mức logic với ESP32.
GND GND Mass chung.
SCL D22 / GPIO22 Xung clock I2C.
SDA D21 / GPIO21 Dữ liệu I2C.
ADDR Để hở hoặc nối GND Địa chỉ 0x48.
ALRT Không nối Không dùng trong bài.
A0 Điện áp cần đo 0–3,3 V so với GND.
Sơ đồ nối ESP32 DevKit V1 với module ADS1115 qua I2C, điện áp cần đo vào kênh A0
Sơ đồ nối ESP32 DevKit V1 với module ADS1115 (hình vẽ minh họa): VDD – 3V3, GND – GND, SCL – D22, SDA – D21; điện áp cần đo đưa vào A0.

Không cấp 5 V cho module khi dùng với ESP32: mức logic I2C của ADS1115 đi theo VDD (mức cao tối thiểu 0,7 × VDD = 3,5 V), không còn phù hợp với GPIO 3,3 V của ESP32.

Để thử nhanh, dùng biến trở 10 kΩ: hai chân ngoài nối 3V3 và GND, chân giữa nối A0. Khi đo nguồn khác như pin hoặc ngõ ra cảm biến, mass của nguồn đó phải nối chung với GND. Điện áp cao hơn 3,3 V phải qua cầu phân áp hai điện trở trước khi vào A0, rồi nhân lại hệ số phân áp trong chương trình.

5. Cài đặt Arduino IDE và thư viện

  1. Mở Tools > Board > Boards Manager, tìm esp32 và cài gói esp32 by Espressif Systems.
  2. Chọn Tools > Board > esp32 > DOIT ESP32 DEVKIT V1 và chọn đúng cổng COM.
  3. Mở Tools > Manage Libraries, tìm Adafruit ADS1X15 và bấm Install. Khi IDE hỏi cài thêm thư viện phụ thuộc, chọn Install All để cài kèm Adafruit BusIO.

Bài dùng gói esp32 phiên bản 3.3.10, thư viện Adafruit ADS1X15 2.5.0 và Adafruit BusIO 1.17.4.

6. Chương trình đọc 4 kênh và in điện áp

Chương trình đọc lần lượt A0–A3 mỗi giây, in giá trị thô (raw) và điện áp tính ra vôn:

/*
  PYWORLD.VN - ESP32 DevKit V1 + module ADC 16 bit ADS1115 (I2C)
  Đọc 4 kênh A0..A3 (so với GND) và in điện áp ra Serial Monitor
  VDD = 3V3, GND = GND, SDA = GPIO21, SCL = GPIO22
  Thư viện: Adafruit ADS1X15 (kèm Adafruit BusIO)
*/

#include <Wire.h>
#include <Adafruit_ADS1X15.h>

#define SDA_PIN   21
#define SCL_PIN   22
#define ADS_ADDR  0x48   // ADDR nối GND: 0x48, VDD: 0x49, SDA: 0x4A, SCL: 0x4B

Adafruit_ADS1115 ads;

void setup() {
  Serial.begin(115200);
  delay(500);

  // Khởi tạo I2C trên GPIO21 (SDA) và GPIO22 (SCL)
  Wire.begin(SDA_PIN, SCL_PIN);

  // Tìm ADS1115 trên bus I2C
  if (!ads.begin(ADS_ADDR)) {
    Serial.println("Khong tim thay ADS1115! Kiem tra day noi va dia chi I2C.");
    while (true) delay(1000);
  }

  // Thang đo ±4,096 V, 1 bit = 0,125 mV
  ads.setGain(GAIN_ONE);

  Serial.println("ADS1115 san sang. Thang do +/-4.096 V, 1 bit = 0.125 mV");
}

void loop() {
  for (uint8_t kenh = 0; kenh < 4; kenh++) {
    int16_t raw = ads.readADC_SingleEnded(kenh);   // Giá trị thô
    float volt = ads.computeVolts(raw);            // Đổi sang vôn theo gain đang chọn

    Serial.printf("A%u: raw = %6d   U = %.4f V\n", kenh, raw, volt);
  }
  Serial.println("----------------------------------");
  delay(1000);
}

Nạp chương trình rồi mở Serial Monitor ở tốc độ 115200 baud. Ví dụ khi A0 nối chân giữa biến trở, A1 nối 3V3, A2 và A3 nối GND:

Hình minh họa Serial Monitor in giá trị raw và điện áp 4 kênh của ADS1115 đọc bằng ESP32
Kết quả mong đợi trên Serial Monitor (hình minh họa, số liệu tính theo công thức của chương trình).

Kênh nối GND vẫn dao động vài đơn vị quanh 0, có lúc ra số âm nhỏ: đó là sai số offset và nhiễu bình thường của ADC. Kênh để hở cho số đo không xác định, nên nối kênh không dùng xuống GND.

7. Giải thích các lệnh chính

  • Adafruit_ADS1115 ads: khai báo đối tượng cho chip 16 bit.
  • Wire.begin(SDA_PIN, SCL_PIN): chọn GPIO21 làm SDA và GPIO22 làm SCL.
  • ads.begin(ADS_ADDR): tìm ADS1115 ở địa chỉ 0x48. Hàm trả về false khi không có thiết bị nào trả lời ở địa chỉ này.
  • ads.setGain(GAIN_ONE): chọn thang đo ±4,096 V. Nếu không gọi lệnh này, thư viện dùng GAIN_TWOTHIRDS (±6,144 V).
  • ads.readADC_SingleEnded(kenh): đo một lần kênh 0–3 so với GND và trả về số nguyên 16 bit có dấu. Hàm chờ đến khi đo xong; ở tốc độ mặc định 128 mẫu/giây, mỗi lần đọc mất khoảng 8 ms.
  • ads.computeVolts(raw): đổi giá trị thô sang vôn theo gain đang chọn, U = raw × thang đo / 32768. Với GAIN_ONE, raw = 13204 cho U = 13204 × 0,125 mV = 1,6505 V.

8. Chọn gain an toàn

Hình dưới so sánh thang đo của sáu mức gain với giới hạn 3,3 V của nguồn cấp:

Biểu đồ thang đo của ADS1115 theo từng mức gain và giới hạn điện áp vào khi VDD = 3,3 V
Thang đo của từng mức gain khi cấp nguồn 3,3 V (hình vẽ minh họa theo datasheet): phần thang đo vượt quá VDD không dùng được.
  • Gain không nâng giới hạn điện áp vào. Mỗi chân A0–A3 luôn phải nằm trong khoảng GND đến VDD; mức chịu đựng tuyệt đối là VDD + 0,3 V, tức 3,6 V khi cấp 3,3 V. Không đưa điện áp âm vào các chân này.
  • Chọn thang đo nhỏ nhất nhưng vẫn lớn hơn điện áp lớn nhất cần đo. Tín hiệu 0–3,3 V dùng GAIN_ONE; cảm biến 0–2 V dùng GAIN_TWO; tín hiệu dưới 1 V dùng GAIN_FOUR. Thang càng nhỏ, 1 bit càng mịn.
  • Vượt thang đo nhưng vẫn dưới VDD thì chip không hỏng: kết quả đứng yên ở 32767 hoặc −32768.
  • Khi cấp 3,3 V, hai thang ±6,144 V và ±4,096 V chỉ đo được tới 3,3 V (raw khoảng 26400 với GAIN_ONE).

9. Biến thể: đo vi sai giữa A0 và A1

Ở chế độ vi sai, ADS1115 đo hiệu điện áp giữa hai chân và cho kết quả có dấu: dương khi A0 cao hơn A1, âm khi thấp hơn. Cách đo này giảm nhiễu chung trên hai dây. Thư viện có các hàm readADC_Differential_0_1(), _0_3(), _1_3() và _2_3(); hai cặp A0–A1 và A2–A3 là 2 kênh vi sai độc lập.

Để thử, nối A1 vào điểm giữa hai điện trở 10 kΩ mắc nối tiếp từ 3V3 xuống GND (khoảng 1,65 V), nối A0 vào chân giữa biến trở. Hiệu điện áp thay đổi trong khoảng ±1,65 V nên chương trình chọn GAIN_TWO (±2,048 V):

/*
  PYWORLD.VN - ESP32 DevKit V1 + ADS1115: đo vi sai giữa A0 (+) và A1 (-)
  VDD = 3V3, GND = GND, SDA = GPIO21, SCL = GPIO22
  Thư viện: Adafruit ADS1X15 (kèm Adafruit BusIO)
*/

#include <Wire.h>
#include <Adafruit_ADS1X15.h>

#define SDA_PIN   21
#define SCL_PIN   22
#define ADS_ADDR  0x48

Adafruit_ADS1115 ads;

void setup() {
  Serial.begin(115200);
  delay(500);

  Wire.begin(SDA_PIN, SCL_PIN);

  if (!ads.begin(ADS_ADDR)) {
    Serial.println("Khong tim thay ADS1115! Kiem tra day noi va dia chi I2C.");
    while (true) delay(1000);
  }

  // Thang đo ±2,048 V, 1 bit = 0,0625 mV
  ads.setGain(GAIN_TWO);

  Serial.println("Do vi sai A0 - A1. Thang do +/-2.048 V, 1 bit = 0.0625 mV");
}

void loop() {
  int16_t raw = ads.readADC_Differential_0_1();   // U(A0) - U(A1), có dấu
  float volt = ads.computeVolts(raw);

  Serial.printf("A0 - A1: raw = %6d   U = %+.4f V\n", raw, volt);
  delay(500);
}

Ví dụ kết quả khi vặn biến trở qua hai phía của điểm giữa (số minh họa):

Do vi sai A0 - A1. Thang do +/-2.048 V, 1 bit = 0.0625 mV
A0 - A1: raw =  10560   U = +0.6600 V
A0 - A1: raw =  -8421   U = -0.5263 V

Đo vi sai không cho phép đưa điện áp âm vào module: từng chân A0, A1 vẫn phải nằm trong khoảng 0 đến VDD, chỉ hiệu của chúng mới có thể âm.

10. Xử lý lỗi thường gặp

  • Serial Monitor báo "Khong tim thay ADS1115!": kiểm tra 4 dây VDD, GND, SCL, SDA (dễ cắm nhầm SCL với SDA) và mối hàn hàng chân. Thử nối ADDR xuống GND; nếu ADDR nối sang chân khác, đổi ADS_ADDR theo bảng ở mục 2.
  • Số đo đứng yên ở 32767: tín hiệu vượt thang đo, cần chọn thang lớn hơn. Nếu đang dùng GAIN_ONE thì điện áp vào đã trên 4 V, vượt giới hạn VDD + 0,3 V: ngắt nguồn tín hiệu ngay.
  • Số đo nhảy nhiều: rút ngắn dây, kiểm tra mass chung, lấy trung bình nhiều lần đọc hoặc giảm tốc độ lấy mẫu bằng ads.setDataRate(RATE_ADS1115_8SPS) (mỗi lần đọc mất khoảng 125 ms).
  • Giá trị raw chỉ thay đổi theo từng nấc 16 đơn vị: chip trên module là ADS1015 12 bit. Điện áp tính ra vẫn đúng nhưng độ phân giải thấp hơn; khai báo Adafruit_ADS1015 ads cho đúng loại chip.
  • Số đo thấp hơn thực tế khi đo qua cầu phân áp điện trở lớn: trở kháng vào của ADS1115 chỉ cỡ vài MΩ và giảm khi tăng gain. Dùng điện trở phân áp từ vài kΩ đến vài chục kΩ.
  • Chương trình đứng im giữa chừng: dây I2C hoặc dây nguồn bị lỏng; hàm đọc chờ ADS1115 báo đo xong nên dừng tại đó. Cắm lại dây rồi nhấn nút EN.
  • Không nạp được chương trình hoặc Serial Monitor hiện ký tự lạ: dùng cáp USB có truyền dữ liệu, chọn đúng cổng COM, giữ nút BOOT khi IDE dừng ở dòng Connecting... và chọn đúng 115200 baud.

Xem thêm: HX711 với load cell và LCD 1602 bằng MicroPython, đo biến dạng bằng strain gauge và cầu Wheatstone và ESP32 điều khiển relay 4 kênh. Khi cần đọc tín hiệu rất nhỏ từ load cell, có thể dùng module ADC 24 bit HX711.


Tin tức liên quan

Hướng dẫn bắt đầu với Wemos D1 R2 (ESP8266) trên Arduino IDE
Hướng dẫn bắt đầu với Wemos D1 R2 (ESP8266) trên Arduino IDE

4 Lượt xem

Hướng dẫn dùng Wemos D1 R2 (ESP8266 khung Arduino UNO) với Arduino IDE 2.x: sơ đồ chân, cài driver CH340 và gói board ESP8266, nạp code nháy LED, kết nối WiFi và xử lý lỗi thường gặp.

Hướng dẫn dùng mạch tạo trễ NE555 có relay: đấu dây và chỉnh thời gian trễ
Hướng dẫn dùng mạch tạo trễ NE555 có relay: đấu dây và chỉnh thời gian trễ

3 Lượt xem

Hướng dẫn dùng mạch tạo trễ NE555 có relay bản 5 V và 12 V: nguyên lý tạo trễ, ý nghĩa các cọc VCC, GND, COM, CK, CB, cách chỉnh thời gian trễ, sơ đồ đấu dây và xử lý lỗi thường gặp.

Mạch hạ áp LM2596 và MP1584: cách chọn, chỉnh điện áp và cấp nguồn ESP32
Mạch hạ áp LM2596 và MP1584: cách chọn, chỉnh điện áp và cấp nguồn ESP32

5 Lượt xem

So sánh mạch hạ áp LM2596 và MP1584, cách chỉnh điện áp ra bằng đồng hồ vạn năng trước khi nối tải, cấp nguồn 5 V cho ESP32 DevKit V1 từ nguồn 12 V và xử lý lỗi thường gặp.

Hướng dẫn ESP32 làm web server điều khiển relay 4 kênh qua WiFi
Hướng dẫn ESP32 làm web server điều khiển relay 4 kênh qua WiFi

6 Lượt xem

Hướng dẫn dùng ESP32 DevKit V1 làm web server trong mạng WiFi nội bộ, mở trang trên điện thoại để bật, tắt module relay 4 kênh; có sơ đồ nối dây, code Arduino IDE và lưu ý an toàn.

Hướng dẫn dùng module thẻ nhớ Micro SD với ESP32
Hướng dẫn dùng module thẻ nhớ Micro SD với ESP32

6 Lượt xem

Hướng dẫn nối module thẻ nhớ Micro SD với ESP32 DevKit V1 qua SPI, định dạng thẻ FAT32, chạy code Arduino đọc ghi file, ghi dữ liệu định kỳ ra CSV và xử lý lỗi Card Mount Failed.

Hướng dẫn dùng màn hình OLED 1.3 inch SH1106 với ESP32
Hướng dẫn dùng màn hình OLED 1.3 inch SH1106 với ESP32

6 Lượt xem

Hướng dẫn nối màn hình OLED 1.3 inch SH1106 với ESP32 DevKit V1 qua I2C, cài thư viện Adafruit SH110X, chạy code hiển thị chữ và xử lý lỗi thường gặp.

Hướng dẫn bắt đầu MicroPython trên ESP32 Lite với Thonny
Hướng dẫn bắt đầu MicroPython trên ESP32 Lite với Thonny

5 Lượt xem

Hướng dẫn cài driver, cài Thonny và nạp firmware MicroPython cho mạch ESP32 Lite, dùng REPL, nháy LED, lưu main.py, đọc nút nhấn, quét I2C và xử lý lỗi thường gặp.

Hướng dẫn dùng màn hình LCD 2004 I2C với ESP32
Hướng dẫn dùng màn hình LCD 2004 I2C với ESP32

6 Lượt xem

Hướng dẫn nối màn hình LCD 2004 I2C (mạch PCF8574) với ESP32 DevKit V1, quét địa chỉ I2C, hiển thị 4 dòng chữ, tạo ký tự riêng, làm bộ đếm thời gian và đổi sang LCD 1602.


Bình luận
Đã thêm vào giỏ hàng