ESP32 Beginner Guide – P4: Kết nối cảm biến
Kết nối cảm biến với ESP32 qua digital, analog và I2C; thực hành đọc nhiệt độ, độ ẩm, áp suất từ BME280 và xử lý lỗi không tìm thấy thiết bị.
Chia sẻ

Ở P3: Pinout và GPIO, mình và bạn đã chọn chân an toàn, đấu LED và tránh đưa tín hiệu 5 V vào ESP32. P4 sẽ biến phần đó thành một ứng dụng có ích: đọc nhiệt độ, độ ẩm và áp suất từ cảm biến BME280 qua I2C.
Mục tiêu không phải cắm dây theo một tấm ảnh rồi hy vọng nó chạy. Sau bài này, bạn sẽ biết nhìn một module cảm biến, xác định giao tiếp, kiểm tra điện áp, tìm địa chỉ I2C và debug theo từng lớp.
Cảm biến và module cảm biến không hẳn là một

Trước khi cắm dây, hãy xác định cảm biến dùng tín hiệu digital, analog hay một bus như I2C.
BME280 là IC cảm biến rất nhỏ của Bosch. Thứ ta thường mua là breakout board: một PCB gắn BME280, tụ lọc, điện trở pull-up và đôi khi có regulator hoặc mạch chuyển mức. Vì vậy, hai sản phẩm cùng ghi “BME280” vẫn có thể khác số chân và điện áp cấp nguồn.
Trước khi nối, hãy tìm datasheet hoặc schematic của đúng breakout bạn đang cầm. Đừng mặc định chân VIN giống 3V3, hay module nhận nguồn 5 V thì tín hiệu trả về cũng an toàn cho GPIO 3,3 V.
Ba kiểu tín hiệu bạn gặp nhiều nhất
| Loại | Dấu hiệu thường gặp | Cách đọc trên ESP32 | Điều cần kiểm tra |
|---|---|---|---|
| Digital đơn | OUT, DO, DATA | digitalRead() hoặc thư viện theo timing riêng | Mức HIGH là 3,3 V hay 5 V; có cần pull-up không |
| Analog | AO, AOUT | analogRead() hoặc analogReadMilliVolts() | Chân phải có ADC; điện áp không vượt giới hạn GPIO |
| Bus số | SDA/SCL, MOSI/MISO/SCK/CS, TX/RX | I2C, SPI hoặc UART | Điện áp logic, chân bus, địa chỉ hoặc tốc độ |
Một chân DATA không đảm bảo có thể đọc bằng digitalRead(). DHT22 chẳng hạn truyền dữ liệu bằng timing riêng; module có comparator lại có thể chỉ trả về HIGH/LOW khi vượt ngưỡng. Tên linh kiện và datasheet mới quyết định code.
Với cảm biến analog, analogRead() trả về giá trị thô; analogReadMilliVolts() dùng hiệu chuẩn để trả về millivolt. Dải đo và attenuation khác giữa các họ ESP32, nên đừng biến số 0–4095 thành điện áp bằng một công thức copy từ board khác.
Vì sao mình chọn I2C và BME280
I2C chỉ cần hai đường tín hiệu:
SDAtruyền dữ liệu.SCLmang xung clock do ESP32 tạo khi làm controller.
Nhiều thiết bị có thể dùng chung hai dây nếu địa chỉ 7 bit không trùng nhau. SDA và SCL là đường open-drain nên cần điện trở kéo lên. Phần lớn breakout BME280 đã có pull-up, nhưng bạn vẫn phải biết chúng được kéo lên điện áp nào. Một breakout kéo SDA/SCL lên 5 V không được nối thẳng vào ESP32.
BME280 phù hợp cho bài đầu vì có một module cho ba đại lượng, có thư viện open-source ổn định và chỉ cần bus I2C. IC hỗ trợ địa chỉ 0x76 hoặc 0x77, tùy trạng thái chân SDO và cách breakout được thiết kế.
Kiểm tra đúng module trước khi cấp nguồn

Cùng tên BME280 nhưng breakout khác nhau có thể dùng regulator, pull-up và nhãn chân khác nhau.
Một số listing dùng ảnh BMP280 nhưng giao BMP280, hoặc in chân theo thứ tự khác. Trước khi cắm dây, mình kiểm tra:
- Dòng chữ trên PCB và mã IC nếu nhìn được.
- Thứ tự
VCC/VIN,GND,SDA/SDI,SCL/SCK. - Breakout có regulator và level shifting hay chỉ là mạch 3,3 V.
- Điện áp cấp và mức logic trong tài liệu của chính breakout đó.
Bài này giả định module BME280 I2C bốn chân hoạt động tốt ở 3,3 V. Nếu module của bạn có bảy chân VIN, 3Vo, GND, SCK, SDI, CS, SDO, hãy theo pinout của nhà sản xuất thay vì ép nó khớp với bảng dưới.
Đấu BME280 với ESP32

Rút USB trước khi nối 3V3, GND, SDA và SCL; màu dây chỉ để dễ theo dõi, không thay cho nhãn chân.
Rút USB trước khi đấu dây. Với ESP32-S3-DevKitC-1 hoặc ESP32-C3-DevKitM-1 trong series này:
| BME280 | ESP32-S3 / ESP32-C3 | Vai trò |
|---|---|---|
VCC hoặc VIN | 3V3 | Cấp nguồn 3,3 V |
GND | GND | Mass chung |
SDA | GPIO4 | Dữ liệu I2C |
SCL | GPIO5 | Clock I2C |
Với ESP32-DevKitC Classic WROOM, bạn có thể dùng GPIO21 cho SDA và GPIO22 cho SCL. Đây là lựa chọn rõ ràng cho các board cụ thể, không phải pinout chung của mọi kit ESP32. Nếu board có màn hình, camera hoặc cảm biến onboard, hãy kiểm tra xem GPIO4/5 đã bị dùng chưa.
Quét bus trước khi cài thư viện cảm biến
I2C scanner giúp tách lỗi dây khỏi lỗi thư viện. Nạp sketch sau và mở Serial Monitor ở 115200 baud:
#include <Wire.h>
constexpr uint8_t SDA_PIN = 4;
constexpr uint8_t SCL_PIN = 5;
void setup() {
Serial.begin(115200);
delay(500);
if (!Wire.begin(SDA_PIN, SCL_PIN)) {
Serial.println("I2C init failed");
return;
}
Serial.println("Scanning I2C bus...");
uint8_t found = 0;
for (uint8_t address = 1; address < 127; ++address) {
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
Serial.printf("Found device at 0x%02X\n", address);
++found;
}
}
Serial.printf("Scan complete: %u device(s)\n", found);
}
void loop() {}
Kết quả mong đợi là 0x76 hoặc 0x77. Nếu không thấy thiết bị, đừng đổi thư viện vội: tắt nguồn rồi kiểm tra VCC, GND, SDA/SCL có bị đảo, chân trong code và tiếp xúc với breadboard.
Đọc nhiệt độ, độ ẩm và áp suất
Trong Arduino IDE, mở Library Manager và cài:
Adafruit BME280 LibraryAdafruit Unified Sensor
Sau đó dùng đúng địa chỉ scanner vừa tìm thấy:
#include <Wire.h>
#include <Adafruit_BME280.h>
constexpr uint8_t SDA_PIN = 4;
constexpr uint8_t SCL_PIN = 5;
constexpr uint8_t BME280_ADDRESS = 0x77; // đổi thành 0x77 nếu scanner báo vậy
Adafruit_BME280 bme;
void setup() {
Serial.begin(115200);
delay(500);
if (!Wire.begin(SDA_PIN, SCL_PIN)) {
Serial.println("Cannot start I2C");
while (true) delay(1000);
}
if (!bme.begin(BME280_ADDRESS, &Wire)) {
Serial.println("BME280 not found. Check address and wiring.");
while (true) delay(1000);
}
}
void loop() {
Serial.printf("Temperature: %.2f C\n", bme.readTemperature());
Serial.printf("Humidity: %.2f %%\n", bme.readHumidity());
Serial.printf("Pressure: %.2f hPa\n\n", bme.readPressure() / 100.0F);
delay(2000);
}
Áp suất BME280 trả về từ thư viện theo Pa nên code chia cho 100.0F để hiển thị hPa. Nhiệt độ trên breakout cũng có thể hơi cao vì nhiệt từ regulator, ESP32 hoặc MacBook Pro; đừng coi một module đặt sát board là nhiệt kế phòng chuẩn.
Khi cảm biến không chạy
| Hiện tượng | Kiểm tra trước |
|---|---|
| Scanner báo 0 thiết bị | Nguồn 3,3 V, GND chung, SDA/SCL bị đảo, sai GPIO hoặc dây đứt |
Scanner thấy 0x77, code dùng 0x76 | Đổi BME280_ADDRESS theo kết quả scanner |
Thấy địa chỉ nhưng bme.begin() fail | Module có thể là BMP280, nguồn không ổn định hoặc sai thư viện |
| Đọc lúc được lúc không | Dây quá dài, tiếp xúc kém, pull-up không phù hợp hoặc bus quá nhanh |
| Nhiệt độ cao bất thường | Nhiệt tự sinh từ board, đặt sát nguồn nhiệt hoặc chưa chờ cảm biến ổn định |
| Analog nhiễu khi bật Wi-Fi | Lấy nhiều mẫu, kiểm tra nguồn/GND, vị trí ADC và giới hạn của đúng dòng ESP32 |
Debug theo thứ tự nguồn → GND → chân → địa chỉ → thư viện → dữ liệu. Đổi cùng lúc ba thứ thường chỉ làm ta mất dấu nguyên nhân.
Checklist trước khi sang P5
- Bạn biết cảm biến dùng digital, analog, I2C, SPI hay UART.
- Bạn đã kiểm tra điện áp nguồn và mức logic của đúng breakout.
- ESP32 và cảm biến có GND chung.
- SDA/SCL trong code khớp dây và không dựa mù quáng vào chân mặc định.
- I2C scanner tìm thấy địa chỉ trước khi chạy thư viện.
- Code có xử lý trường hợp khởi tạo cảm biến thất bại.
Ở P5, mình sẽ đưa dữ liệu cảm biến lên mạng Wi-Fi theo cách vẫn dễ debug: kết nối có timeout, log trạng thái rõ ràng và không biến loop() thành một vòng reconnect vô hạn.
Tham khảo
Chia sẻ
Tiếp tục khám phá
Đọc tiếp
Bài viết liên quan
ESP32 Beginner Guide – P3: Pinout và GPIO
Hiểu pinout ESP32, chọn GPIO đúng cho input và output, dùng pull-up, đấu LED với nút nhấn và tránh chân boot, flash, PSRAM hoặc tín hiệu 5 V.
ESP32 Beginner Guide – P2: Cài đặt và nạp code đầu tiên
Cài Arduino IDE, thêm Arduino-ESP32, chọn đúng board và Port, nạp sketch đầu tiên rồi xử lý lỗi Failed to connect trên ESP32, ESP32-C3 và ESP32-S3.
ESP32 IoT Project Roadmap: Lộ trình từ LED đến sản phẩm
Roadmap tương tác giúp bạn học ESP32 qua project: từ LED và nút nhấn, sensor kết nối cloud, TinyML tại edge đến OTA và bảo mật cho thiết bị thật.