1. Vấn Đề: Tại Sao 3.3V Và 5V Không Thể Kết Nối Trực Tiếp?
ESP32 hoạt động ở 3.3V — tất cả các GPIO đều dùng mức logic 3.3V. Nhưng nhiều module và cảm biến phổ biến hoạt động ở 5V (HC-SR04, LCD 16×2, servo, relay module).
Kết nối trực tiếp giữa 2 mức logic có thể dẫn đến:
| Kịch bản | Hậu quả |
|---|---|
| 5V → GPIO ESP32 (module 5V gửi tín hiệu 5V vào GPIO 3.3V) | 🔥 Cháy GPIO ESP32! |
| GPIO ESP32 → module 5V (ESP32 3.3V gửi tín hiệu vào module 5V) | ⚠️ Module không nhận được tín hiệu HIGH (ngưỡng 5V là ~3.5V) |
| ESP32 3.3V → Arduino 5V | Arduino đọc HIGH ở >3.0V — thường OK nhưng không đảm bảo |
2. Mức Logic Là Gì?
Mỗi chip vi điều khiển có một điện áp hoạt động (VDD). Mức logic HIGH và LOW được định nghĩa dựa trên VDD:
| Thông số | ESP32 (3.3V) | Arduino Uno (5V) |
|---|---|---|
| VDD (điện áp hoạt động) | 3.3V | 5V |
| VIH (Input HIGH tối thiểu) | 2.475V (0.75 × VDD) | 3.5V (0.7 × VDD) |
| VIL (Input LOW tối đa) | 0.825V (0.25 × VDD) | 1.5V (0.3 × VDD) |
| VOH (Output HIGH tối thiểu) | 2.64V (0.8 × VDD) | 4.2V (0.84 × VDD) |
| VOL (Output LOW tối đa) | 0.66V (0.2 × VDD) | 0.9V (0.18 × VDD) |
| Dòng tối đa mỗi GPIO | 40mA (khuyến nghị <12mA) | 40mA (khuyến nghị <20mA) |
Giải thích:
- VIH: Nếu bạn đưa điện áp >= VIH vào chân INPUT, chip đọc là HIGH
- VIL: Nếu bạn đưa điện áp <= VIL vào chân INPUT, chip đọc là LOW
- VOH: Khi chip output HIGH, điện áp tối thiểu nó tạo ra
- VOL: Khi chip output LOW, điện áp tối đa nó tạo ra
Vấn đề với ESP32:
- VIH của ESP32 = 2.475V → ESP32 đọc 3.3V là HIGH, 0V là LOW. Nhưng không được đưa >3.3V vào GPIO!
- GPIO ESP32 KHÔNG 5V-tolerant (không chịu được 5V) — nếu đưa 5V vào, GPIO sẽ cháy
- Các module 5V output ra tín hiệu ~5V → CẦN hạ xuống 3.3V trước khi vào ESP32
3. Các Module 5V Phổ Biến Và Cách Kết Nối
3.1. Module ADC với board 5V
| Module/Board | Logic Level | Kết nối với ESP32 |
|---|---|---|
| Arduino Uno | 5V | ⚠️ Cần level shifter khi giao tiếp |
| HC-SR04 (siêu âm) | 5V | ⚠️ Echo pin output 5V → cần voltage divider |
| LCD 16×2 I2C | 5V | ✅ I2C bus có pull-up, ESP32 SDA/SCL 3.3V → module 5V đọc được |
| Servo SG90 | 5V | ✅ Signal từ ESP32 3.3V đủ cho servo, nhưng cấp nguồn 5V riêng |
| DHT22 | 3.3-5V | ✅ Dùng được với ESP32 trực tiếp (cả 3.3V và 5V) |
| HC-05 Bluetooth | 3.3V | ✅ Dùng trực tiếp (nhưng cần kiểm tra voltage regulator) |
| RFID RC522 | 3.3V | ✅ Dùng trực tiếp |
| MAX7219 LED Matrix | 5V | ⚠️ MOSI/SCLK 5V → cần level shifter hoặc voltage divider |
4. 5 Phương Pháp Kết Nối An Toàn
4.1. KHÔNG ĐƯỢC: Kết nối trực tiếp ❌
// ❌ SAI — HC-SR04 Echo (5V) vào GPIO ESP32 (3.3V)
const int echoPin = 5; // 5V signal → GPIO5 ESP32 → CHÁY GPIO!
4.2. Voltage Divider (2 điện trở) — Đơn giản nhất ✅
Đây là cách rẻ nhất và đơn giản nhất để hạ 5V xuống 3.3V.
Mạch:
Module 5V OUT ────[R1: 10kΩ]────┐
├──── ESP32 GPIO
[R2: 4.7kΩ]
│
GND
Tính toán:
V_out = V_in × R2 / (R1 + R2)
V_out = 5V × 4.7k / (10k + 4.7k) = 5 × 4.7 / 14.7 = 1.6V
Chờ — 1.6V < 2.475V (VIH của ESP32) → KHÔNG được! ESP32 sẽ đọc là LOW.
Công thức đúng:
Cần V_out > VIH (ESP32) = 2.475V, và càng gần 3.3V càng tốt.
Với R1 = 1kΩ, R2 = 2kΩ:
V_out = 5V × 2k / (1k + 2k) = 5 × 2/3 = 3.33V ✅ Gần 3.3V
Giá trị dễ mua:
| R1 | R2 | V_out (ngõ vào 5V) | Kết luận |
|---|---|---|---|
| 2.2kΩ | 3.3kΩ | 3.0V | ✅ Tốt |
| 1kΩ | 2kΩ | 3.33V | ✅ Tốt (gần 3.3V) |
| 10kΩ | 4.7kΩ | 1.6V | ❌ Quá thấp |
| 1kΩ | 1kΩ | 2.5V | ⚠️ Sát ngưỡng, không khuyến nghị |
Code hoàn chỉnh với voltage divider (HC-SR04):
// HC-SR04 với voltage divider cho Echo pin
#define TRIG_PIN GPIO_NUM_12
#define ECHO_PIN GPIO_NUM_14 // Echo qua voltage divider (R1=2.2k, R2=3.3k)
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void loop() {
// Gửi xung trigger
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Đọc Echo (đã hạ xuống ~3.0V qua voltage divider)
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
float distance = duration * 0.034 / 2;
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
delay(500);
}
4.3. Level Shifter Module (Nâng/Hạ Mức) — Khuyên dùng
Mua module 4-channel bi-directional level shifter (~10,000đ). Module này dùng MOSFET để chuyển đổi 2 chiều giữa 3.3V và 5V.
Sơ đồ chân:
LV (Low Voltage) ──── 3.3V (từ ESP32)
HV (High Voltage) ──── 5V (từ nguồn ngoài)
GND ──── GND chung
LV1, LV2... ──── 3.3V signal (ESP32 GPIO)
HV1, HV2... ──── 5V signal (module 5V)
Cách dùng với HC-SR04:
HC-SR04 VCC ──── 5V
HC-SR04 GND ──── GND
HC-SR04 Trig ──── HV1 (Level Shifter) ──── LV1 ──── ESP32 GPIO12 (OUTPUT)
HC-SR04 Echo ──── HV2 (Level Shifter) ──── LV2 ──── ESP32 GPIO14 (INPUT)
4.4. Serial Logic: Dùng 3.3V Arduino Board
Một số board tương thích Arduino hoạt động ở 3.3V:
- Arduino Due (3.3V)
- Teensy 3.x/4.x (3.3V)
- ESP8266 (3.3V)
- Raspberry Pi Pico (3.3V)
Nếu bạn kết nối ESP32 với các board này, không cần level shifter.
4.5. Dùng I2C: Tự Động Tương Thích
Nhiều module 5V giao tiếp qua I2C (LCD 1602 I2C, BMP280, MPU6050). Trên bus I2C, điện trở pull-up kéo lên 3.3V (hoặc 5V):
- ESP32 SDA/SCL = 3.3V
- Module 5V có pull-up 5V trên board → module tự đọc được tín hiệu 3.3V
- Module 5V gửi tín hiệu về → tín hiệu có thể lên 5V → cần kiểm tra — một số module I2C có điện trở pull-up yếu, tín hiệu chỉ lên ~3.3V
Cách an toàn: dùng module I2C 3.3V hoặc level shifter.
4.6. So sánh các phương pháp
| Phương pháp | Chi phí | Độ tin cậy | Chiều | Dễ làm |
|---|---|---|---|---|
| Voltage divider | ~200đ (2 điện trở) | ⚠️ Trung bình (sai số điện trở) | 5V→3.3V (1 chiều) | ✅ Rất dễ |
| Level shifter module | ~10,000đ | ✅ Cao | 2 chiều | ✅ Dễ |
| Dùng I2C | 0đ (nếu module có I2C) | ✅ Cao | 2 chiều | ✅ Dễ |
| Dùng board 3.3V | — | ✅ Rất cao | — | ✅ |
| Kết nối trực tiếp | 0đ | ❌ Rủi ro cháy GPIO | — | ❌ Không an toàn |
5. Trường Hợp Đặc Biệt: Open-Drain Output
Một số module (như cảm biến DHT22, DS18B20) dùng open-drain output — chúng chỉ kéo xuống GND (LOW) hoặc thả nổi (để điện trở pull-up kéo lên).
Ưu điểm: bạn có thể dùng pull-up 3.3V hoặc 5V tùy ý → tương thích với cả 2 mức logic.
// DHT22: dùng được với ESP32 trực tiếp (3.3V) hoặc 5V
// Data pin cần pull-up 10kΩ lên 3.3V (nếu dùng ESP32)
6. Bảng Tra Nhanh Kết Nối Các Module Với ESP32
| Module | Logic | Kết nối ESP32 | Phương pháp |
|---|---|---|---|
| DHT22 | 3.3-5V | ✅ Trực tiếp | Pull-up 10kΩ lên 3.3V |
| DS18B20 | 3.3-5V | ✅ Trực tiếp | Pull-up 4.7kΩ lên 3.3V |
| HC-SR04 | 5V | ⚠️ Echo→cần divider | Voltage divider (R1=2.2k, R2=3.3k) |
| LCD 16×2 I2C | 5V | ⚠️ Thường OK | Kiểm tra: module có pull-up 5V → thường vẫn đọc được 3.3V |
| OLED SSD1306 I2C | 3.3-5V | ✅ Trực tiếp | Nhiều module đã có 3.3V regulator |
| Servo SG90 | 5V | ✅ Signal OK | Signal 3.3V đủ cho servo, cấp nguồn 5V riêng |
| Relay module | 5V | ⚠️ Cần transistor | Dùng NPN transistor (2N2222) hoặc relay module opto |
| NeoPixel WS2812B | 5V | ⚠️ Signal 3.3V | Thường OK (một số LED cần level shifter nếu dây dài) |
| MAX7219 | 5V | ⚠️ Cần level shifter | MOSI/SCLK/CS 5V → cần divider hoặc level shifter |
| RFID RC522 | 3.3V | ✅ Trực tiếp | Tuyệt đối không cấp 5V vào VCC! |
| BMP280 (GY-BMP280) | 3.3V | ✅ Trực tiếp | Module 3.3V, dùng I2C |
| MPU6050 | 3.3V | ✅ Trực tiếp | Module 3.3V, dùng I2C |
| Ethernet ENC28J60 | 3.3V | ✅ Trực tiếp | Module 3.3V, dùng SPI |
| SD Card module | 5V | ⚠️ SPI 5V → level shifter | Cần level shifter cho SPI (hoặc dùng module 3.3V) |
| Arduino Uno | 5V | ⚠️ Level shifter | I2C: OK nếu pull-up 3.3V. UART/SPI: cần level shifter |
7. Mạch Level Shifter Tự Chế (MOSFET)
Bạn có thể tự làm level shifter 2 chiều với 1 con BSS138 (N-Channel MOSFET):
3.3V (ESP32) 5V (Module)
│ │
[10kΩ] [10kΩ]
│ │
ESP32 TX ───────┤ ├──── Module RX
│ ┌───┤
└─── Drain BSS138 ──┤ Gate
Source ─┬───
│
GND
Cách hoạt động:
- Khi ESP32 output LOW (0V): MOSFET OFF → Module RX kéo lên 5V qua R2
- Khi ESP32 output HIGH (3.3V): MOSFET ON → Module RX kéo xuống GND → LOW
- Chiều ngược lại: Module output LOW → MOSFET OFF → ESP32 đọc 3.3V qua R1
Mạch này có sẵn trên module level shifter 4 channel chỉ 10,000đ — khuyên dùng module thay vì tự hàn.
8. Lỗi Thường Gặp Và Debug
Dấu hiệu GPIO đã bị cháy
- GPIO luôn ở mức 0V hoặc 3.3V bất kể code nói gì — dấu hiệu chắc chắn đã cháy
- ESP32 không boot được — nếu nhiều GPIO bị cháy có thể ảnh hưởng boot
- GPIO bị nóng khi chạm — dòng rò quá lớn do cháy bên trong chip
- Cảm nhận mùi khét — dấu hiệu cuối cùng, chip đã hỏng hoàn toàn
Debug Checklist
- [ ] Kiểm tra datasheet: module này dùng 3.3V hay 5V?
- [ ] Đo VCC module: có đúng 5V hoặc 3.3V không?
- [ ] Đo điện áp tín hiệu từ module: có >3.3V không?
- [ ] Đã nối GND chung giữa ESP32 và module?
- [ ] Nếu dùng voltage divider, đã tính V_out đúng?
- [ ] Nếu dùng level shifter, đã cấp nguồn cho cả LV (3.3V) và HV (5V)?
- [ ] Dùng trực tiếp: module có thực sự 3.3V không?
9. Kết Luận
Kết nối thiết bị 3.3V và 5V là một trong những lỗi phổ biến nhất gây cháy GPIO trên ESP32. Hãy nhớ quy tắc vàng:
- KIỂM TRA DATASHEET trước khi kết nối — module chạy 3.3V hay 5V?
- KHÔNG đưa 5V vào GPIO ESP32 — dùng voltage divider hoặc level shifter
- GND chung là bắt buộc — cả 2 board phải cùng tham chiếu GND
- Dùng level shifter module — 10,000đ rẻ hơn mua ESP32 mới
- Nếu nghi ngờ, đo trước — dùng multimeter đo điện áp tín hiệu trước khi kết nối
- I2C thường tương thích — nhưng kiểm tra pull-up voltage trước
Bài tiếp theo: UART là gì? Debug và giao tiếp Serial với ESP32.
Tài liệu tham khảo
- Espressif ESP32 Datasheet — Section “GPIO Specifications”


