I. Cơ bản về ADC đối với NodeMCU và ESP32 DEVKIT
ADC – Analog to Digital Converter là một trong những ngoại vi quan trọng của vi điều khiển. Ngày nay đa số các cảm biến thông số môi trường như nhiệt độ, độ ẩm, độ sáng, tốc độ… đều trả về kết quả dưới dạng analog tuy nhiên vi điều khiển không thể xử lý được các dữ liệu ở dạng này vì vậy trong các dòng vi điều khiển thường có bộ chuyển đổi tương tự – số ADC.
Để hiểu về ADC chúng ta cần làm rõ 2 khái niệm chính là độ phân giải và thời gian lấy mẫu:
- Độ phân giải (resolution): chỉ số lượng bit dùng để biểu diễn giá trị dữ liệu sau quá trình chuyển đổi ở ngõ ra.
Hình vẽ trên biểu diễn quá trình xấp xỉ một tín hiệu liên tục (đường màu tím) thành các giá trị rời rạc (đường màu xanh), quá trình này được gọi là lượng tử hóa tín hiệu. Dễ dàng nhận ra rằng ở hình vẽ trên sử dụng 8 mức rời rạc khác nhau để lượng tử hóa tín hiệu màu tím và để biểu diễn được 8 mức này phải dùng 3 bit nhị phân, vì vậy ta nói bộ ADC có độ phân giải 3 bit. Từ đây cũng cho thấy một vấn đề quan trọng là nếu bộ ADC có độ phân giải càng thấp thì số mức để lượng tử hóa tín hiệu đầu vào càng ít dẫn đến tín hiệu đầu ra (tín hiệu sau khi lượng tử hóa) sẽ biến dạng càng nhiều so với tín hiệu đầu vào.
- Thời gian lấy mẫu và giữ mẫu (sampling time & hold time): dùng để chỉ khoảng thời gian giữa 2 lần lấy mẫu liên tiếp. Như ở hình trên, sau khi lấy mẫu các chấm đỏ chính là giá trị được đưa ra tại ngõ ra số. Dễ nhận thấy nếu thời gian giữa 2 lần lấy mẫu quá lớn thì sẽ làm cho quá trình chuyển đổi bị mất tín hiệu ở những khoảng thời gian không nằm tại thời điểm lấy mẫu. Thời gian lấy mẫu càng nhỏ sẽ làm làm cho việc tái tạo tín hiệu trở nên tin cậy hơn.
- Có một khái niệm khác các bạn cần hiểu là điện áp tham chiếu của bộ ADC (Vref). Điện áp tham chiếu là giá trị điện áp chuẩn để so sánh, thường là ngưỡng điện áp lớn nhất (Vref +) và ngưỡng điện áp nhỏ nhất (Vref -) mà bộ ADC chuyển đổi.
Ví dụ: bộ ADC có độ phân giải 10 bit và điện áp tham chiếu Vref + và Vref – là 5V và 0V. Khi đó giá trị số chuyển đổi sẽ nằm trong dải từ 0 đến 210-1 = 1023. Tức là:
Khi điện áp đầu vào là 0V -> giá trị số chuyển đổi là 0
5V -> giá trị số chuyển đổi là 1023
2.5V -> giá trị số chuyển đổi là: (2.5*1023)/5
Với việc Vref + bằng điện áp nguồn của vi điều khiển đã dẫn đến việc Vref + luôn bị thay đổi do sự không ổn định của điện áp nguồn. Vì vậy trên ESP32 và ESP8266 nhà phát hành đã thiết kế một điện áp tham chiếu khác là 1100mV ít chịu ảnh hưởng từ điện áp nguồn hơn.
Sự ảnh hưởng của nhiễu đối với giá trị analog: Khi tín hiệu analog của các cảm biến bị nhiễu tác động vào sẽ làm sai lệch đi giá trị điều này khiến cho việc chuyển đổi ADC trở nên không chính xác vì vậy cần phải có biện pháp để giảm sự ảnh hưởng của nhiễu đối với giá trị ADC. Ở phương diện phần cứng, để giảm nhiễu chúng ta có thể kết nối một tụ điện 0.1uF vào chân ADC input. Ở phương diện phần mềm có thể sử dụng phương pháp đa mẫu (lẫy mẫu liên tục trong một khoảng thời gian sau đó lấy giá trị trung bình của mẫu).
Hình minh họa cho thấy hiệu quả của việc giảm nhiễu bằng hai phương pháp trên:
II. Bộ ADC trong NodeMCU và ESP32 DEVKIT
NodeMCU: ESP8266 hỗ trợ 1 kênh ADC 10bit (chân A0 trên kit NodeMCU) với điện áp vào nằm trong dải từ 0 đến 1.1V (điện áp tham chiếu mặc định là 1.1V). Tuy nhiên bên trong kit NodeMCU đã thiết kế sẵn một cầu phân áp như hình vẽ sau:
Với cầu phân áp này ta có thể đưa điện áp vào tại chân A0 trên NodeMCU tối thiểu 0V và tối đa là 3.3V để không vượt quá ngưỡng giới hạn của bộ ADC trên ESP8266.
ESP32 DEVKIT: hỗ trợ 2 bộ ADC 12bit với tổng cộng 18 kênh.
- ADC1 gồm 8 kênh tại các chân từ GPIO32 đến GPIO39
- ADC2 gồm 10 kênh tại các chân GPIO0, 2, 4, 12 đến 15, 25 đến 27
Tuy nhiên khi sử dụng ADC trên ESP32 cần lưu ý như sau:
- Bộ ADC2 được dùng làm WiFi Driver vì vậy bộ ADC2 chỉ sử dụng được khi chức năng WiFi không được kích hoạt.
- Các chân GPIO0, 2, 15: không khuyến khích sử dụng vì các chân này dùng để cấu hình mode trong quá trình nạp code.
- Điện áp tham chiếu mặc định: Vref + = 3.3V
Hàm sử dụng trong lập trình chức năng đọcADC:
analogRead(ADC_pin);
- Chức năng: đọc giá trị analog tại ADC_pin
- Giá trị trả về: 0 -> 2n-1 với n là độ phân giải của bộ ADC
Ví dụ: Sử dụng NodeMCU đọc giá trị điện áp của biến trở, nếu điện áp lớn hơn hoặc bằng 2V thì sáng LED GPIO16, ngược lại tắt LED GPIO16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#define LED_PIN 16 #define ANALOG_PIN A0 void setup() { pinMode(LED_PIN, OUTPUT); } void loop() { int val = analogRead(ANALOG_PIN); float vol = (float)val * 1023.0 / 3.3; if(val >= 2) digitalWrite(LED_PIN, LOW); else digitalWrite(LED_PIN, HIGH); } |
Xem thêm: Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32
Nhóm TAPIT IoTs