Từ breadboard đến thiết bị dùng thật: đưa ESP32 vào hộp, khoan lỗ jack Type-C, GX16, jack DC
Đưa dự án ESP32 từ breadboard vào hộp: cấp nguồn USB 5 V hoặc adapter 12 V qua LM2596, bố trí linh kiện, khoan lỗ jack Type-C, jack DC, GX16 và chương trình hộp relay có nút nhấn.
Mạch ESP32 chạy ngon trên breadboard chưa phải là thiết bị dùng được hằng ngày: dây cắm lỏng, nguồn lấy từ máy tính, không có chỗ cắm tải, không có nút bấm. Bài này đi qua các bước biến một dự án ESP32 thành thiết bị đặt trong hộp: chọn cách cấp nguồn 5 V hoặc 12 V, bố trí linh kiện, khoan lỗ cho jack Type-C, jack DC và đầu nối GX16, nối dây, và một chương trình mẫu cho hộp điều khiển relay có nút nhấn, đèn báo, nhớ trạng thái khi mất điện và cảnh báo khi nguồn yếu.
1. Chọn cách cấp nguồn

- Cách A, nguồn USB 5 V qua jack Type-C tròn gắn hộp nối vào chân VIN của ESP32. Hợp với thiết bị nhỏ chỉ có cảm biến, màn hình. Jack Type-C loại 2 chân không đưa chân CC ra ngoài; có loại đã có sẵn điện trở bên trong, có loại không. Thử bằng cáp Type-C sang Type-C trước: không lên 5 V thì dùng cáp USB-A sang Type-C, hoặc chọn jack có điện trở 5,1 kΩ ở chân CC (xem bài jack Type-C cái và điện trở 5,1 kΩ ở CC1, CC2).
- Cách B, adapter 12 V qua jack DC gắn hộp, rồi mạch hạ áp LM2596 chỉnh ra 5 V cho ESP32 và module relay. Hợp với thiết bị có relay, tải, dây dài. Cách chỉnh LM2596 ra đúng 5 V có trong bài LM2596 là gì, cách chỉnh áp.
- Đế ra chân ESP32 30 chân có sẵn jack DC nhận 6,5–16 V và IC ổn áp, dùng được thay cho mạch hạ áp khi không có relay, tải lớn (xem bài đế ra chân ESP32 30 chân).
2. Bố trí linh kiện trong hộp

- Chia vùng: nguồn vào (jack DC, mạch hạ áp) ở một góc; ESP32 ở giữa; relay sát cửa ra tải để dây tải ngắn và không chạy ngang qua ESP32.
- Cố định mạch bằng cột đồng M3 và ốc; cắm ESP32 lên đế ra chân để thay mạch không cần hàn. Không dán keo nóng lên IC hạ áp, cuộn cảm vì chúng nóng khi chạy tải lớn.
- Đi dây: bó dây tín hiệu riêng, dây tải và dây 220 V riêng; dây vào ra đầu nối để dư một đoạn và có chỗ giữ để kéo dây không giật vào mối hàn.
- Anten Wi-Fi: hộp nhựa không chặn sóng. Hộp kim loại chặn sóng Wi-Fi, khi đó dùng ESP32 bản anten rời và đưa anten ra ngoài hộp.
- Thiết bị nhỏ chỉ có ESP32 và vài cảm biến thì dùng luôn hộp mica cho ESP32 DevKit 30 chân (65 × 45 × 25 mm).
3. Khoan lỗ mặt hộp

- Đo đường kính thân ren của từng jack bằng thước kẹp; lỗ khoan lớn hơn khoảng 0,3–0,5 mm. Đầu nối GX16 khoan lỗ 16 mm (chi tiết trong bài đầu nối GX16 là gì).
- Dán băng keo giấy lên mặt hộp, vẽ tâm lỗ, chấm dấu bằng mũi nhọn để mũi khoan không trượt.
- Khoan mồi 3 mm, mở rộng bằng mũi khoan bước; nhựa mềm thì khoan tốc độ chậm để lỗ không chảy nhựa.
- Gọt ba via, thử lắp. Jack có tai chống xoay thì khoét thêm rãnh nhỏ.
- Chừa khoảng cách giữa các lỗ đủ để vặn đai ốc và cầm đầu cắm khi rút.
Kiểm tra cực tính jack DC trước khi hàn: phần lớn adapter có tâm dương; cách đo có trong bài jack DC 5.5×2.1 và 5.5×2.5, cực tính. Đeo kính bảo hộ khi khoan.
4. Nối dây và chương trình mẫu: hộp relay có nút nhấn

| Linh kiện | Nối với ESP32 | Ghi chú |
|---|---|---|
| LM2596, ngõ ra 5 V | VIN, GND | Chỉnh đúng 5 V trước khi nối ESP32 |
| Module relay: VCC, GND, IN | 5 V, GND, D27 | Module kích mức thấp |
| Nút nhấn trên mặt hộp | D33 và GND | Dùng điện trở kéo lên bên trong |
| LED trên mặt hộp | D25 qua điện trở 330 Ω | Cực âm LED về GND |
| Cầu phân áp 100 kΩ / 22 kΩ | Điểm giữa vào D35 | 12 V chia còn khoảng 2,2 V |
// PYWORLD.VN - Hộp điều khiển dùng thật: nút nhấn trên mặt hộp bật tắt relay, LED báo trạng thái
// PYWORLD.VN - Nhớ trạng thái relay vào bộ nhớ flash (Preferences), mất điện có lại vẫn đúng trạng thái cũ
// PYWORLD.VN - Đo điện áp nguồn 12 V qua cầu phân áp 100 kΩ / 22 kΩ vào GPIO35, nháy LED cảnh báo khi nguồn yếu
#include <Preferences.h>
#include "esp_system.h"
const int RELAY_PIN = 27;
const bool RELAY_KICH_MUC_THAP = true; // module relay kích mức thấp: IN = LOW là relay đóng
const int NUT_PIN = 33; // nút nhấn nối GPIO33 với GND, dùng điện trở kéo lên bên trong
const int LED_PIN = 25; // LED trên mặt hộp, nối qua điện trở 330 Ω xuống GND
const int CHAN_DO_NGUON = 35; // điểm giữa cầu phân áp từ nguồn 12 V
const uint32_t CAU_TREN_KOHM = 100; // điện trở từ nguồn 12 V xuống điểm giữa
const uint32_t CAU_DUOI_KOHM = 22; // điện trở từ điểm giữa xuống GND
const uint32_t NGUON_YEU_MV = 10500; // dưới 10,5 V coi là nguồn yếu
const uint32_t CHONG_DOI_MS = 30; // thời gian chống dội phím
const uint32_t CHU_KY_IN_MS = 5000;
Preferences boNho;
bool relayDangBat = false;
uint32_t soLanBam = 0;
void datRelay(bool bat) {
relayDangBat = bat;
digitalWrite(RELAY_PIN, (bat == RELAY_KICH_MUC_THAP) ? LOW : HIGH);
}
// Điện áp nguồn (mV) = điện áp chân đo x (100 + 22) / 22; lấy trung bình 16 lần đo
uint32_t doNguonMv() {
uint32_t tong = 0;
for (int i = 0; i < 16; i++) {
tong += analogReadMilliVolts(CHAN_DO_NGUON);
}
return tong / 16 * (CAU_TREN_KOHM + CAU_DUOI_KOHM) / CAU_DUOI_KOHM;
}
const char *lyDoKhoiDong() {
switch (esp_reset_reason()) {
case ESP_RST_POWERON: return "cap nguon";
case ESP_RST_BROWNOUT: return "SUT AP";
case ESP_RST_SW: return "khoi dong lai bang lenh";
case ESP_RST_PANIC: return "LOI CHUONG TRINH";
default: return "khac";
}
}
void setup() {
// Giữ relay nhả trong lúc khởi động: ghi mức "tắt" khi chân còn là ngõ vào rồi mới chuyển thành ngõ ra
pinMode(RELAY_PIN, INPUT);
digitalWrite(RELAY_PIN, RELAY_KICH_MUC_THAP ? HIGH : LOW);
pinMode(RELAY_PIN, OUTPUT);
pinMode(NUT_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
delay(300);
boNho.begin("hop_relay", false);
bool trangThaiCu = boNho.getBool("relay", false);
datRelay(trangThaiCu);
digitalWrite(LED_PIN, trangThaiCu ? HIGH : LOW);
Serial.println();
Serial.printf("Khoi dong: %s\n", lyDoKhoiDong());
Serial.printf("Khoi phuc relay: %s\n", trangThaiCu ? "BAT" : "TAT");
}
void loop() {
// Nút nhấn: đọc mức, chống dội, chỉ xử lý lúc vừa nhấn xuống
static int mucTruoc = HIGH;
static uint32_t lucDoi = 0;
static int mucOnDinh = HIGH;
int muc = digitalRead(NUT_PIN);
if (muc != mucTruoc) {
lucDoi = millis();
mucTruoc = muc;
}
if (millis() - lucDoi > CHONG_DOI_MS && muc != mucOnDinh) {
mucOnDinh = muc;
if (mucOnDinh == LOW) {
datRelay(!relayDangBat);
boNho.putBool("relay", relayDangBat); // chỉ ghi khi trạng thái đổi để đỡ mòn flash
soLanBam++;
Serial.printf("Nhan nut: relay %s\n", relayDangBat ? "BAT" : "TAT");
}
}
// LED: sáng khi relay bật; nháy nhanh khi nguồn yếu
static uint32_t lanDoNguon = 0;
static uint32_t nguonMv = 12000;
if (millis() - lanDoNguon >= 500) {
lanDoNguon = millis();
nguonMv = doNguonMv();
}
bool nguonYeu = nguonMv < NGUON_YEU_MV;
if (nguonYeu) {
digitalWrite(LED_PIN, (millis() / 150) % 2);
} else {
digitalWrite(LED_PIN, relayDangBat ? HIGH : LOW);
}
static uint32_t lanIn = 0;
if (millis() - lanIn >= CHU_KY_IN_MS) {
lanIn = millis();
Serial.printf("Nguon %u mV%s | relay %s | so lan nhan %u\n", (unsigned)nguonMv, nguonYeu ? " (YEU)" : "",
relayDangBat ? "BAT" : "TAT", (unsigned)soLanBam);
}
}
Các điểm chính của chương trình:
- Nhớ trạng thái: thư viện Preferences có sẵn trong gói esp32 lưu trạng thái relay vào vùng nvs của bộ nhớ flash. Mất điện có lại, relay về đúng trạng thái cũ. Chương trình chỉ ghi khi trạng thái đổi để đỡ mòn flash.
- Relay không đóng thoáng qua lúc cấp nguồn: chân điều khiển được ghi mức "tắt" khi còn là ngõ vào rồi mới chuyển thành ngõ ra.
- Chống dội phím: chỉ nhận lần nhấn khi mức của nút đứng yên hơn 30 ms.
- Đo nguồn 12 V:
analogReadMilliVolts()đọc điện áp chân D35, nhân với (100 + 22) / 22. Điện trở sai số 5 % thì số đo lệch vài phần trăm: đo nguồn bằng đồng hồ vạn năng, so với số in ra và chỉnh hằng sốCAU_DUOI_KOHMnếu cần. Dưới 10,5 V thì LED nháy nhanh báo nguồn yếu.

5. Trước khi đóng hộp
- Cấp 12 V, đo ngõ ra LM2596 bằng đồng hồ vạn năng, chỉnh đúng 5 V khi chưa nối ESP32.
- Nối ESP32, nạp chương trình, thử nút, relay, LED khi hộp còn mở.
- Thử relay đóng cắt tải thật vài chục lần; ESP32 khởi động lại hay treo thì xem lại cách đi dây và nguồn (bài relay làm ESP32 bị reset cùng đợt bài này giải thích chi tiết).
- Lắc nhẹ hộp, kéo nhẹ từng dây ra vào để chắc không có mối hàn lỏng.
- Dán nhãn cạnh từng cổng: "12 V DC", "Tải", "USB 5 V". Đóng hộp xong muốn nạp chương trình mới thì nạp qua Wi-Fi theo bài nạp chương trình cho ESP32 qua Wi-Fi (OTA).
Thiết bị đóng cắt điện 220 V phải có cầu chì, dây đủ tiết diện và phải cắt điện khi lắp; cách nối relay an toàn có trong bài ESP32 điều khiển module relay an toàn.
6. Xem thêm
- Jack USB Type-C: phân biệt loại 2, 4, 5, 6 dây và các kiểu lắp.
- Đầu nối GX16: loại chân, dòng, lỗ khoan, cách hàn.
- Bài cấp nguồn cho ESP32 đúng cách cùng đợt bài này.
Cần tư vấn chọn linh kiện để đóng hộp thiết bị, liên hệ PYWORLD qua số 0915703319.
Xem thêm