Bỏ qua, đến nội dung chính
Bài viếtFirmwareMới

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ẻ

LinkedInFacebookX
An ESP32-S3 development board, BME280 breakout, and sensor modules arranged beside a MacBook Pro on a practical electronics workbench

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

ESP32-S3 DevKitC-1 đặt cạnh cảm biến BME280, cảm biến PIR và cảm biến nhiệt độ độ ẩm dạng module.

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ạiDấu hiệu thường gặpCách đọc trên ESP32Điều cần kiểm tra
Digital đơnOUT, DO, DATAdigitalRead() hoặc thư viện theo timing riêngMức HIGH là 3,3 V hay 5 V; có cần pull-up không
AnalogAO, AOUTanalogRead() 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/RXI2C, 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:

  • SDA truyền dữ liệu.
  • SCL mang 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

Người dùng kiểm tra nhãn VCC, GND, SDA và SCL trên module BME280 cạnh MacBook Pro hiển thị tài liệu kỹ thuật.

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:

  1. Dòng chữ trên PCB và mã IC nếu nhìn được.
  2. Thứ tự VCC/VIN, GND, SDA/SDI, SCL/SCK.
  3. Breakout có regulator và level shifting hay chỉ là mạch 3,3 V.
  4. Đ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

ESP32-S3 DevKitC-1, module BME280 bốn chân và bốn dây Dupont female-to-female được đặt riêng trước khi đấu I2C.

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:

BME280ESP32-S3 / ESP32-C3Vai trò
VCC hoặc VIN3V3Cấp nguồn 3,3 V
GNDGNDMass chung
SDAGPIO4Dữ liệu I2C
SCLGPIO5Clock 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 Library
  • Adafruit 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ượngKiể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() failModule có thể là BMP280, nguồn không ổn định hoặc sai thư viện
Đọc lúc được lúc khôngDâ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ườngNhiệ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-FiLấ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ẻ

LinkedInFacebookX

Tiếp tục khám phá

Đọc tiếp

Bài viết liên quan

Xem thêm trong Bài viết

Nastrotek sử dụng cookie để phân tích truy cập và cá nhân hóa quảng cáo, giúp hiểu cách website được sử dụng. Bạn có thể chấp nhận hoặc từ chối các cookie không thiết yếu. Chính sách bảo mật