1. Giới Thiệu
ESP32 có 12 chân ADC (Analog-to-Digital Converter) mạnh mẽ, cho phép bạn đọc các tín hiệu điện áp từ cảm biến analog. Tuy nhiên, để đọc chính xác và tránh các lỗi thường gặp, bạn cần hiểu rõ về cách hoạt động và các tính năng của ESP32 ADC.
Trong bài viết này, chúng ta sẽ đi sâu vào:
- Cấu tạo và các chân ADC trên ESP32
- Độ phân giải 12-bit và dải điện áp
- Suy hao (Attenuation) và các mức điện áp
- Đo ADC hiệu quả: averaging, calibration
- So sánh với Analog Read trên Arduino Uno
2. Kiến Thức Cơ Bản Về ADC
ADC chuyển đổi tín hiệu điện áp analog (liên tục) thành giá trị số (rời rạc) mà vi điều khiển có thể xử lý.
- Độ phân giải: ESP32 có ADC 12-bit, nghĩa là nó có thể phân biệt 2<sup>12</sup> = 4096 mức. Nếu sử dụng dải tham chiếu 0-3.3V, mỗi bước nhỏ nhất tương ứng với khoảng 3.3V / 4096 ≈ 0.8 mV.
- Dải điện áp: Mặc định, ADC của ESP32 hoạt động trong dải 0-3.3V. Tuy nhiên, bạn có thể cấu hình mức suy hao để đọc điện áp cao hơn.
3. Các Chân ADC Trên ESP32
ESP32 có tổng cộng 18 kênh ADC, nhưng không phải tất cả đều có thể sử dụng được trên các board devKit phổ biến. Các chân được thiết kế cho ADC thường được đánh dấu là ADC1_CHx hoặc ADC2_CHx.
- ADC1: Có 8 kênh (GPIO 32-39). Các kênh này có thể sử dụng đồng thời với Wi-Fi.
- ADC2: Có 7 kênh (GPIO 0, 2, 4, 12-15). Các kênh này không thể sử dụng đồng thời với Wi-Fi. Khi Wi-Fi đang hoạt động, việc đọc ADC2 có thể gặp lỗi hoặc trả về giá trị sai. Nên ưu tiên dùng ADC1.
Các chân ADC phổ biến trên ESP32 DevKit V1:
- ADC1: GPIO 32 (ADC1_CH4), GPIO 33 (ADC1_CH5), GPIO 34 (ADC1_CH6), GPIO 35 (ADC1_CH7) (Lưu ý: GPIO 34, 35 chỉ có thể đọc)
- ADC2: GPIO 0 (ADC2_CH0), GPIO 2 (ADC2_CH2), GPIO 4 (ADC2_CH4), GPIO 12 (ADC2_CH5), GPIO 13 (ADC2_CH6), GPIO 14 (ADC2_CH7), GPIO 15 (ADC2_CH8)
4. Các Mức Suy Hao (Attenuation)
Để đọc điện áp ngoài dải 0-3.3V, bạn có thể cài đặt mức suy hao cho từng kênh ADC. Cài đặt này thay đổi điện áp đầu vào tối đa mà ADC có thể đo.
| Chân ADC | Tên kênh ADC1 | Tên kênh ADC2 | Điện áp tối đa (mV) | Suy hao (Attenuation) | Rung sai điện áp ADC (V) |
|---|---|---|---|---|---|
| GPIO 32 | ADC1_CH4 | – | 1100 | ADC_ATTEN_DB_11 | 0 – 1.1V |
| GPIO 33 | ADC1_CH5 | – | 1100 | ADC_ATTEN_DB_11 | 0 – 1.1V |
| GPIO 34 | ADC1_CH6 | – | 1100 | ADC_ATTEN_DB_11 | 0 – 1.1V |
| GPIO 35 | ADC1_CH7 | – | 1100 | ADC_ATTEN_DB_11 | 0 – 1.1V |
| GPIO 32-35 | ADC1_CH4-7 | – | 1500 | ADC_ATTEN_DB_6 | 0 – 1.5V |
| GPIO 32-35 | ADC1_CH4-7 | – | 2500 | ADC_ATTEN_DB_2.5 | 0 – 2.5V |
| GPIO 32-35 | ADC1_CH4-7 | – | 3300 | ADC_ATTEN_DB_0 | 0 – 3.3V |
| (Chân khác với ADC2) | – | ADC2_CHx | 1100-3300 tùy chân | ADC_ATTEN_DB_11/6/2.5/0 |
Lưu ý:
ADC_ATTEN_DB_0cho phép đo tối đa 3.3V.ADC_ATTEN_DB_11cho phép đo tối đa ~1.1V.ADC_ATTEN_DB_2.5cho phép đo tối đa ~2.5V.ADC_ATTEN_DB_6cho phép đo tối đa ~1.5V. (Có thể có sự sai khác nhỏ giữa các nguồn tài liệu, cần ghi nhớ tùy theo thư viện).
Để đọc điện áp đến 3.3V, bạn có thể chọn ADC_ATTEN_DB_0. Nếu cảm biến của bạn có điện áp ra trong khoảng 0-1.1V, bạn nên chọn ADC_ATTEN_DB_11 để có độ nhạy cao hơn.
5. Đo ADC Hiệu Quả
5.1. Cấu hình kênh và suy hao
Bạn cần khởi tạo ADC cho kênh và mức suy hao mong muốn, thường thực hiện trong hàm setup().
#include <Arduino.h>
// Chọn chân GPIO bạn muốn dùng (ví dụ: GPIO 34 cho ADC1_CH6)
#define ADC_PIN 34
void setup() {
Serial.begin(115200);
// Cấu hình ADC cho kênh 6 (GPIO 34) với mức suy hao 0dB (đo tới 3.3V)
// Có thể thay thế bằng các giá trị khác như ADC_ATTEN_DB_11, ADC_ATTEN_DB_6, ADC_ATTEN_DB_2_5
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_0);
// Đối với ADC2, bạn cần thêm cấu hình cụ thể hơn tùy theo thư viện Arduino ESP32
// và luôn kiểm tra xem Wi-Fi có đang chạy không.
Serial.println("ADC Setup Complete!");
}
void loop() {
// Đọc giá trị ADC
int adc_value = analogRead(ADC_PIN);
// Chuyển đổi giá trị ADC sang điện áp (ví dụ với 12-bit, 0-4095 là 0-3.3V)
float voltage = adc_value * (3.3 / 4095.0);
Serial.printf("Raw ADC: %d, Voltage: %.2f V\n", adc_value, voltage);
delay(1000);
}
5.2. Averaging (Trung bình cộng)
ADC có thể bị nhiễu. Để có kết quả ổn định hơn, hãy đọc nhiều lần và lấy trung bình cộng. Bạn có thể thực hiện điều này trong code, hoặc sử dụng các hàm thư viện hỗ trợ sẵn.
// Ví dụ: đọc 10 lần và lấy trung bình
float readSmoothedADC(int pin) {
long sum = 0;
for (int i = 0; i < 10; i++) {
sum += analogRead(pin);
delay(10); // Chờ một chút giữa các lần đọc
}
float avgValue = sum / 10.0;
// Chuyển đổi avgValue sang voltage
float voltage = avgValue * (3.3 / 4095.0);
return voltage;
}
5.3. Calibration (Hiệu chuẩn)
Sai lệch gốc của chip ADC (offset, gain error) có thể làm sai lệch kết quả. ESP32 có cơ chế hiệu chuẩn tích hợp. Tuy nhiên, đối với hầu hết các ứng dụng maker, việc sử dụng averaging thường là đủ. Nếu cần độ chính xác cao, bạn cần đọc tài liệu về API hiệu chuẩn của ESP-IDF.
6. So Sánh Với Arduino Uno ADC
| Tính năng | ESP32 (12-bit) | Arduino Uno (10-bit) |
|---|---|---|
| Độ phân giải | 4096 mức (0-3.3V) | 1024 mức (0-5V) |
| Dải điện áp gốc | 0-3.3V (có thể mở rộng với suy hao) | 0-5V |
| Tốc độ đọc (max) | ~2 Msps (Chế độ đơn giản, chưa bao gồm Wi-Fi) | ~10 Ksps |
| Số kênh | 18 (chia làm ADC1, ADC2) | 6 kênh analog (A0-A5) |
| Đồng thời với Wi-Fi | ADC1: Có <br> ADC2: Không | – |
| Suy hao (Attenuation) | Có thể cấu hình (0-3.3V) | Không có (tín hiệu > 5V cần chia áp) |
| Độ chính xác | Cao hơn nhờ độ phân giải cao hơn và cấu hình mạnh mẽ | Khá tốt cho các ứng dụng cơ bản |
Ưu điểm của ESP32 ADC:
- Độ phân giải cao hơn (12-bit vs 10-bit) cho phép đo điện áp với độ chi tiết cao hơn.
- Khả năng cấu hình suy hao giúp đo dải điện áp rộng hơn mà không cần mạch chia áp ngoài.
- ADC1 có thể hoạt động độc lập với Wi-Fi.
Nhược điểm:
- ADC2 bị ảnh hưởng bởi Wi-Fi, cần cẩn thận khi sử dụng.
- Việc đọc ADC có thể chậm hơn nếu Wi-Fi/Bluetooth đang hoạt động tần suất cao.
7. Kết Luận và Ứng Dụng
ESP32 cung cấp khả năng đọc analog mạnh mẽ và linh hoạt. Bằng cách chọn đúng kênh, cấu hình suy hao phù hợp và áp dụng kỹ thuật averaging, bạn có thể đọc chính xác các giá trị từ cảm biến như:
- Cảm biến nhiệt độ: LM35, TMP36
- Cảm biến độ ẩm: DHT22 (ngoài chân digital, nó cũng có thể đọc analog)
- Cảm biến ánh sáng: LDR (photoresistor), quang trở
- Cảm biến khoảng cách: HC-SR04 (chân Echo có thể dùng làm analog)
- Cảm biến điện áp/dòng điện: Với mạch chia áp hoặc sensor module phù hợp.
Luôn ưu tiên sử dụng ADC1 và kiểm tra cẩn thận mức điện áp đầu ra của cảm biến để chọn cấu hình suy hao phù hợp.


