Hướng dẫn đo điện áp 16 bit bằng module ADS1115 với ESP32
- 1. Vì sao nên dùng ADC ngoài cho ESP32?
- 2. Tìm hiểu module ADS1115
- 3. Linh kiện cần chuẩn bị
- 4. Sơ đồ nối ADS1115 với ESP32
- 5. Cài đặt Arduino IDE và thư viện
- 6. Chương trình đọc 4 kênh và in điện áp
- 7. Giải thích các lệnh chính
- 8. Chọn gain an toàn
- 9. Biến thể: đo vi sai giữa A0 và A1
- 10. Xử lý lỗi thường gặp
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ố | 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 |
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.
| 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
| 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. |
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
- Mở Tools > Board > Boards Manager, tìm esp32 và cài gói esp32 by Espressif Systems.
- Chọn Tools > Board > esp32 > DOIT ESP32 DEVKIT V1 và chọn đúng cổng COM.
- 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:
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ềfalsekhi 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ùngGAIN_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ớiGAIN_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:
- 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ùngGAIN_TWO; tín hiệu dưới 1 V dùngGAIN_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_ADDRtheo 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_ONEthì đ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 adscho đú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.
Xem thêm