Báo động nhiệt độ tăng bất thường cho bếp, kho, tủ điện
Theo dõi nhiệt độ liên tục bằng cảm biến DS18B20 chống nước; vượt ngưỡng cài đặt hoặc tăng quá nhanh là hú còi, nháy đèn đỏ và hiện cảnh báo trên web điện thoại. Xem được nhiệt độ hiện tại, mức cao nhất trong ngày và nhật ký lần báo gần nhất theo giờ Việt Nam.
✅ Đã kiểm thử
Xem chi tiết 22 phép đo
Đang báo động (còi hú, đèn đỏ sáng)
- Q1: dẫn 29.2mA, Vce=0.04V (bão hòa tốt).
- D1: dòng 5.9mA (cho phép 20.0mA).
- Chân GPIO18 cấp 2.4mA (an toàn ≤ 20.0mA).
- Chân GPIO25 cấp 5.9mA (an toàn ≤ 20.0mA).
- Tổng dòng đỉnh từ USB 289.1mA (đủ với cục sạc 5V 1A).
- Dòng qua còi: 29.2mA ✓
- Áp trên transistor khi dẫn (càng nhỏ càng tốt): 0.04V ✓
- Dòng chân GPIO18 mở transistor: 2.4mA ✓
- Dòng LED đỏ: 5.9mA ✓
- Áp trở kéo lên của cảm biến (phải là 3,3V): 3.30V ✓
- Tổng dòng từ cổng USB: 289.1mA ✓
Bình thường (đèn xanh sáng, còi im)
- D2: dòng 4.9mA (cho phép 20.0mA).
- Chân GPIO26 cấp 4.9mA (an toàn ≤ 20.0mA).
- Tổng dòng đỉnh từ USB 256.4mA (đủ với cục sạc 5V 1A).
- Còi phải im: 0.0mA ✓
- Dòng LED xanh: 4.9mA ✓
- LED đỏ phải tắt: 0.0mA ✓
Đang bấm nút tắt tiếng lúc báo động
- D1: dòng 5.9mA (cho phép 20.0mA).
- Chân GPIO25 cấp 5.9mA (an toàn ≤ 20.0mA).
- Tổng dòng đỉnh từ USB 257.4mA (đủ với cục sạc 5V 1A).
- Áp chân nút khi nhấn: 0.00V ✓
- Còi đã tắt nhưng đèn đỏ vẫn sáng: 0.0mA ✓
Nguyên lý hoạt động
DS18B20 là cảm biến nhiệt độ số đo từ −55 đến 125°C với sai số 0,5°C, trả kết quả qua một dây dữ liệu duy nhất. Dây đó phải có điện trở 4,7kΩ kéo lên nguồn thì cảm biến mới trả lời được — ở đây kéo lên 3,3V chứ không phải 5V, vì chân ESP32 chỉ chịu 3,3V. ESP32 đọc nhiệt độ mỗi giây và xét hai điều kiện: vượt ngưỡng tuyệt đối (mặc định 60°C) hoặc tăng nhanh hơn ngưỡng tốc độ (mặc định 6°C trong 1 phút) — kiểu tăng nhanh thường xuất hiện sớm hơn khi có đám cháy bắt đầu. Khi báo động, GPIO18 mở transistor S8050 cho còi 5V kêu ngắt quãng (còi ăn khoảng 30mA, chân ESP32 chỉ cấp khoảng 2,5mA qua điện trở 1kΩ) và GPIO25 nháy đèn đỏ; lúc yên bình thì GPIO26 giữ đèn xanh sáng. Nút ở GPIO27 tắt tiếng còi trong 5 phút mà vẫn giữ đèn đỏ. ESP32 phát WiFi riêng và chạy trang web tiếng Việt để xem nhiệt độ, đổi ngưỡng và nhập WiFi nhà cho đúng giờ.
Sơ đồ đấu dây
Mỗi màu là một dây. Chấm tròn là điểm hàn. Chạm vào tên dây trong bảng để làm nổi bật.
Đây là mô phỏng một chiều (DC) ở trạng thái tĩnh: dùng để kiểm tra mức áp, dòng và công suất. Hiệu ứng nhấp nháy, PWM hay giao tiếp số do code quyết định nên không chạy ở đây.
| # | Dây | Nối các điểm | Áp mô phỏng |
|---|---|---|---|
| 1 | đỏ 5V | U1 VIN ⟷ BZ1 + | — |
| 2 | cam 3V3 | U1 3V3 ⟷ U2 VDD · dây đỏ ⟷ R1 2 | — |
| 3 | đen GND | U1 GND ⟷ U2 GND · dây đen ⟷ Q1 E (phát) ⟷ D1 K · chân ngắn (−) ⟷ D2 K · chân ngắn (−) ⟷ SW1 2 | — |
| 4 | vàng DQ | U2 DQ · dây vàng ⟷ R1 1 ⟷ U1 GPIO4 (D4) | — |
| 5 | xanh lá BZ_DRV | U1 GPIO18 (D18) ⟷ R2 1 | — |
| 6 | xanh dương BZ_BASE | R2 2 ⟷ Q1 B (gốc) | — |
| 7 | tím BZ_NEG | BZ1 - ⟷ Q1 C (góp) | — |
| 8 | xanh ngọc RED_DRV | U1 GPIO25 (D25) ⟷ R3 1 | — |
| 9 | nâu RED_A | R3 2 ⟷ D1 A · chân dài (+) | — |
| 10 | hồng GRN_DRV | U1 GPIO26 (D26) ⟷ R4 1 | — |
| 11 | xám GRN_A | R4 2 ⟷ D2 A · chân dài (+) | — |
| 12 | xanh rêu BTN | SW1 1 ⟷ U1 GPIO27 (D27) | — |
Danh sách linh kiện
| Ký hiệu | Linh kiện | Giá tham khảo | |
|---|---|---|---|
| U1 | ESP32 DevKit V1 30 chân (ESP32-WROOM-32) | 110.000đ | Tìm mua |
| U2 | Cảm biến nhiệt độ DS18B20 dạng đầu dò chống nước, dây 1m | 25.000đ | Tìm mua |
| R1 | Điện trở 4,7kΩ 1/4W (vàng-tím-đỏ) (4.7k) | 200đ | Tìm mua |
| Q1 | Transistor S8050 (TO-92) | 500đ | Tìm mua |
| R2 | Điện trở 1kΩ 1/4W (nâu-đen-đỏ) | 200đ | Tìm mua |
| BZ1 | Còi chip chủ động 5V (loại to, kêu lớn) | 4.000đ | Tìm mua |
| D1 | LED đỏ 5mm (red) | 300đ | Tìm mua |
| R3 | Điện trở 220Ω 1/4W (đỏ-đỏ-nâu) | 200đ | Tìm mua |
| D2 | LED xanh lá 5mm (green) | 300đ | Tìm mua |
| R4 | Điện trở 220Ω 1/4W (đỏ-đỏ-nâu) | 200đ | Tìm mua |
| SW1 | Nút nhấn 4 chân 6×6mm | 1.500đ | Tìm mua |
| Tổng (chưa gồm board hàn, dây, thiếc) | 142.400đ |
Các bước làm
Code nạp cho mạch
Cài thư viện: OneWire, DallasTemperature (Arduino IDE → Library Manager). Chọn board DOIT ESP32 DEVKIT V1.
/*
Mạch Gọn — Báo động nhiệt độ tăng bất thường (ESP32 + DS18B20)
Board : ESP32 DevKit V1 ("DOIT ESP32 DEVKIT V1")
Thư viện: OneWire, DallasTemperature
Chân : GPIO4 <- DQ của DS18B20 (trở 4,7kΩ kéo lên 3V3)
GPIO18 -> 1kΩ -> B của S8050 (còi 5V ở cực C)
GPIO25 -> 220Ω -> LED đỏ ; GPIO26 -> 220Ω -> LED xanh
GPIO27 nút tắt tiếng, nối GND (INPUT_PULLUP)
Lần đầu: WiFi "MachGon-BaoNhiet" (mật khẩu machgon123) -> 192.168.4.1
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Preferences.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <time.h>
const uint8_t PIN_DS = 4, PIN_BUZ = 18, PIN_RED = 25, PIN_GRN = 26, PIN_NUT = 27;
const char* AP_SSID = "MachGon-BaoNhiet";
const char* HOSTNAME = "baonhiet";
const uint32_t DOC_MS = 1000; // nhịp đọc cảm biến
const uint32_t TAT_TIENG_MS = 5UL * 60UL * 1000UL; // tắt tiếng 5 phút
const uint8_t LOG_MAX = 20;
OneWire ow(PIN_DS);
DallasTemperature ds(&ow);
WebServer server(80);
Preferences cfg;
float nhiet = NAN, nhietMax = -999;
float nguongC = 60.0; // ngưỡng tuyệt đối
float nguongToc = 6.0; // °C tăng trong 60 giây thì coi là bất thường
bool baoDong = false, tatTieng = false, camBienOk = false;
uint32_t mocDoc = 0, mocTatTieng = 0, mocMau = 0;
float nhietMauTruoc = NAN;
uint8_t soLanLoi = 0;
struct LogItem { time_t t; uint32_t ms; float nhiet; bool toc; };
LogItem logs[LOG_MAX];
uint8_t logHead = 0, logCount = 0;
bool gioOk() { return time(nullptr) > 1700000000; }
void ghiLog(float t, bool theoToc) {
logs[logHead] = { gioOk() ? time(nullptr) : 0, millis(), t, theoToc };
logHead = (logHead + 1) % LOG_MAX;
if (logCount < LOG_MAX) logCount++;
}
String dinhDangLog(const LogItem& l) {
char b[48];
if (l.t) { struct tm tmv; localtime_r(&l.t, &tmv); strftime(b, sizeof b, "%d/%m %H:%M:%S", &tmv); }
else snprintf(b, sizeof b, "+%lus sau khi bật", (unsigned long)(l.ms / 1000));
return String(b);
}
const char PAGE[] PROGMEM = R"HTML(<!doctype html><html lang="vi"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1"><title>Báo nhiệt</title>
<style>
body{margin:0;font-family:system-ui,sans-serif;background:#0f172a;color:#e2e8f0}
header{padding:14px;background:#1e293b;font-weight:700}
.card{margin:14px;padding:14px;background:#1e293b;border-radius:14px}
.t{font-size:46px;font-weight:800;margin:4px 0}
.st{font-size:18px;margin-bottom:8px}.muted{color:#94a3b8;font-size:13px}
.alarm{color:#fca5a5}.ok{color:#86efac}
.btn{background:#334155;color:#e2e8f0;border:0;border-radius:10px;padding:12px 14px;margin-top:8px;width:100%;font-size:16px}
.mute{background:#dc2626;color:#fff;font-weight:700}
ul{list-style:none;padding:0;margin:0}li{padding:8px 0;border-bottom:1px solid #334155;font-size:14px}
input{width:100%;padding:9px;margin:4px 0 8px;border-radius:8px;border:1px solid #475569;background:#0b1220;color:#e2e8f0;box-sizing:border-box}
</style></head><body>
<header>🌡️ Báo động nhiệt độ</header>
<div class="card"><div class="st" id="st">…</div><div class="t" id="nh">--</div>
<p class="muted" id="info"></p>
<button class="btn mute" id="mute">🔕 Tắt tiếng 5 phút</button></div>
<div class="card"><b>Nhật ký báo động</b><ul id="log"></ul></div>
<div class="card"><b>Cài đặt</b>
<label class="muted">Ngưỡng nhiệt độ (°C)</label><input id="ng" type="number" min="30" max="110" step="1">
<label class="muted">Tăng nhanh bao nhiêu °C trong 1 phút thì báo</label><input id="toc" type="number" min="2" max="40" step="1">
<button class="btn" onclick="luu()">Lưu</button><hr style="border-color:#334155">
<label class="muted">WiFi nhà (để có giờ chính xác)</label><input id="ssid" placeholder="Tên WiFi"><input id="pass" type="password" placeholder="Mật khẩu">
<button class="btn" onclick="wifi()">Lưu WiFi & khởi động lại</button></div>
<script>
const $=s=>document.querySelector(s);let S={};
async function load(){const r=await fetch('/api/state');S=await r.json();
$('#nh').textContent=S.ok?S.nhiet.toFixed(1)+' °C':'--';
$('#nh').className='t '+(S.baoDong?'alarm':'ok');
$('#st').textContent=S.baoDong?'🚨 NHIỆT ĐỘ BẤT THƯỜNG':(S.ok?'✅ Bình thường':'⚠️ Không đọc được cảm biến');
$('#info').textContent='Cao nhất: '+(S.max>-900?S.max.toFixed(1)+'°C':'--')+' · '+(S.tatTieng?'đang tắt tiếng':'còi sẵn sàng')+' · '+(S.sta?'WiFi nhà '+S.ip+' — http://baonhiet.local':'chưa nối WiFi nhà');
$('#log').innerHTML=S.log.map(l=>`<li class="alarm">🚨 ${l.t} — ${l.nhiet.toFixed(1)}°C ${l.toc?'(tăng nhanh)':'(vượt ngưỡng)'}</li>`).join('')||'<li class="muted">Chưa có lần nào</li>';
if(document.activeElement.tagName!='INPUT'){$('#ng').value=S.nguong;$('#toc').value=S.toc}}
$('#mute').onclick=async()=>{await fetch('/api/mute',{method:'POST'});load()};
async function luu(){await fetch('/api/opt?ng='+$('#ng').value+'&toc='+$('#toc').value,{method:'POST'});load()}
async function wifi(){await fetch('/api/wifi',{method:'POST',body:new URLSearchParams({ssid:$('#ssid').value,pass:$('#pass').value})});alert('Đã lưu, mạch khởi động lại')}
load();setInterval(load,2000);
</script></body></html>)HTML";
void handleState() {
bool sta = WiFi.status() == WL_CONNECTED;
String j = "{\"ok\":" + String(camBienOk ? "true" : "false") +
",\"nhiet\":" + String(isnan(nhiet) ? 0 : nhiet, 2) +
",\"max\":" + String(nhietMax, 2) +
",\"baoDong\":" + (baoDong ? "true" : "false") +
",\"tatTieng\":" + (tatTieng ? "true" : "false") +
",\"nguong\":" + String(nguongC, 0) + ",\"toc\":" + String(nguongToc, 0) +
",\"sta\":" + (sta ? "true" : "false") +
",\"ip\":\"" + (sta ? WiFi.localIP().toString() : WiFi.softAPIP().toString()) + "\",\"log\":[";
for (uint8_t i = 0; i < logCount; i++) {
const LogItem& l = logs[(logHead + LOG_MAX - 1 - i) % LOG_MAX];
if (i) j += ',';
j += "{\"t\":\"" + dinhDangLog(l) + "\",\"nhiet\":" + String(l.nhiet, 2) + ",\"toc\":" + (l.toc ? "true" : "false") + "}";
}
j += "]}";
server.send(200, "application/json", j);
}
void setupWeb() {
server.on("/", []() { server.send_P(200, "text/html; charset=utf-8", PAGE); });
server.on("/api/state", HTTP_GET, handleState);
server.on("/api/mute", HTTP_POST, []() {
tatTieng = true; mocTatTieng = millis();
digitalWrite(PIN_BUZ, LOW);
server.send(200, "text/plain", "ok");
});
server.on("/api/opt", HTTP_POST, []() {
nguongC = constrain(server.arg("ng").toFloat(), 30, 110);
nguongToc = constrain(server.arg("toc").toFloat(), 2, 40);
cfg.putFloat("nguong", nguongC);
cfg.putFloat("toc", nguongToc);
server.send(200, "text/plain", "ok");
});
server.on("/api/wifi", HTTP_POST, []() {
cfg.putString("ssid", server.arg("ssid"));
cfg.putString("pass", server.arg("pass"));
server.send(200, "text/plain", "ok");
delay(500);
ESP.restart();
});
server.onNotFound([]() { server.sendHeader("Location", "/"); server.send(302); });
server.begin();
}
void setup() {
Serial.begin(115200);
pinMode(PIN_BUZ, OUTPUT); digitalWrite(PIN_BUZ, LOW);
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_GRN, OUTPUT);
pinMode(PIN_NUT, INPUT_PULLUP);
cfg.begin("cfg", false);
nguongC = cfg.getFloat("nguong", 60.0);
nguongToc = cfg.getFloat("toc", 6.0);
ds.begin();
ds.setResolution(11);
ds.setWaitForConversion(false);
ds.requestTemperatures();
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(AP_SSID, cfg.getString("appass", "machgon123").c_str());
String ssid = cfg.getString("ssid", "");
if (ssid.length()) {
WiFi.begin(ssid.c_str(), cfg.getString("pass", "").c_str());
uint32_t t = millis();
while (WiFi.status() != WL_CONNECTED && millis() - t < 15000) delay(250);
}
configTime(7 * 3600, 0, "pool.ntp.org", "time.google.com"); // giờ Việt Nam UTC+7
if (MDNS.begin(HOSTNAME)) MDNS.addService("http", "tcp", 80);
setupWeb();
Serial.printf("San sang. AP %s IP %s\n", AP_SSID, WiFi.softAPIP().toString().c_str());
}
void loop() {
server.handleClient();
uint32_t now = millis();
// 1. Đọc nhiệt độ
if (now - mocDoc >= DOC_MS) {
mocDoc = now;
float t = ds.getTempCByIndex(0);
ds.requestTemperatures();
if (t <= -100 || t >= 120) {
if (++soLanLoi >= 3) { camBienOk = false; nhiet = NAN; }
} else {
soLanLoi = 0;
camBienOk = true;
nhiet = t;
if (t > nhietMax) nhietMax = t;
}
// 2. Xét báo động: vượt ngưỡng hoặc tăng quá nhanh
bool vuotNguong = camBienOk && nhiet >= nguongC;
bool tangNhanh = false;
if (now - mocMau >= 60000) {
if (camBienOk && !isnan(nhietMauTruoc) && nhiet - nhietMauTruoc >= nguongToc) tangNhanh = true;
nhietMauTruoc = nhiet;
mocMau = now;
}
bool canBao = vuotNguong || tangNhanh;
if (canBao && !baoDong) {
ghiLog(nhiet, tangNhanh && !vuotNguong);
tatTieng = false;
Serial.printf("BAO DONG %.1fC (%s)\n", nhiet, tangNhanh ? "tang nhanh" : "vuot nguong");
}
if (!canBao && baoDong) Serial.println(F("Da ve binh thuong"));
baoDong = canBao;
Serial.printf("T=%.2fC max=%.2f bao=%d\n", nhiet, nhietMax, baoDong ? 1 : 0);
}
// 3. Nút tắt tiếng
if (digitalRead(PIN_NUT) == LOW && baoDong && !tatTieng) {
tatTieng = true;
mocTatTieng = now;
digitalWrite(PIN_BUZ, LOW);
Serial.println(F("Da tat tieng 5 phut"));
}
if (tatTieng && now - mocTatTieng >= TAT_TIENG_MS) tatTieng = false;
// 4. Còi và đèn
if (baoDong && !tatTieng) digitalWrite(PIN_BUZ, (now / 400) % 2);
else digitalWrite(PIN_BUZ, LOW);
digitalWrite(PIN_RED, baoDong ? ((now / 200) % 2) : LOW);
digitalWrite(PIN_GRN, (!baoDong && camBienOk) ? HIGH : ((now % 2000) < 60));
// 5. Nối lại WiFi nhà nếu rớt
static uint32_t mocKiemTra = 0;
if (now - mocKiemTra > 30000) {
mocKiemTra = now;
if (cfg.getString("ssid", "").length() && WiFi.status() != WL_CONNECTED) WiFi.reconnect();
}
delay(5);
}
🔌 Cắm thử trên breadboard
Cắm nháp trên board cắm trước cho chắc, chạy đúng rồi hãy làm mạch in. Sơ đồ này do máy tự xếp từ chính netlist ở trên và đã đối chiếu lại: hai chân cùng một cột (cùng nửa board) là thông nhau, không có net nào bị chập.
- Mỗi cột 5 lỗ trong cùng một nửa board thông nhau; hai nửa cách nhau bởi rãnh giữa.
- Hai đường kẻ dọc mép board là đường nguồn: hàng + (vạch đỏ) và hàng − (vạch xanh). Nhớ bắc dây nối đường nguồn trên với đường nguồn dưới nếu dùng cả hai nửa.
- Màu dây trên hình trùng với màu trong bảng nối dây ở mục Sơ đồ, cắm theo màu cho dễ dò.
🧲 Mạch in để ủi (PCB 1 mặt)
Bản mạch in một mặt đồng, tự xếp linh kiện và tự đi dây, đã kiểm quy tắc khoảng cách và đối chiếu đúng 100% với sơ đồ nguyên lý ở trên. In tỉ lệ 1:1 rồi ủi lên tấm đồng.
Hướng dẫn ủi – ăn mòn – khoan – hàn (đầy đủ)
Hướng dẫn làm mạch in bằng phương pháp ủi
Mạch: Báo động nhiệt độ tăng bất thường cho bếp, kho, tủ điện
Kích thước board: 68,6×66,0 mm · 54 lỗ khoan (mũi 0,8, 0,9 và 1 mm) · 22 đoạn mạch, tổng 519,4 mm · 0 cầu nhảy.
Quy tắc đã kiểm: đường mạch rộng 0,8mm (nguồn và GND 1mm), khe cách tối thiểu 0,5mm. Mạch in đã được máy đối chiếu đúng 100% với sơ đồ nguyên lý.
1. In đúng tỉ lệ 1:1
- In trang "MẶT ĐỒNG" bằng máy in LASER, đặt tỉ lệ 100%, KHÔNG chọn "Fit to page" hay "Scale to fit".
- Dùng thước trên bản in đo lại đoạn 100mm: phải đúng 100mm mới dùng được.
- In trên giấy in ảnh bóng, giấy decal bóc, hoặc giấy tạp chí láng. Mực càng dày càng tốt.
- Trang "MẶT ĐỒNG" đã được LẬT GƯƠNG sẵn: úp mặt có mực vào tấm đồng là đúng chiều.
2. Chuẩn bị tấm đồng
- Cắt phíp đồng (board đồng một mặt) lớn hơn kích thước mạch mỗi bề khoảng 5mm.
- Chà mặt đồng bằng giấy nhám mịn (P800–P1200) rồi rửa sạch, lau khô. Mặt đồng phải sáng, không vết dầu mỡ, không chạm tay vào.
3. Ủi mực sang đồng
- Úp mặt có mực vào tấm đồng, dùng băng keo giấy dán cố định một cạnh.
- Bàn ủi để mức nóng nhất (cotton/linen), KHÔNG dùng chế độ phun hơi nước.
- Ủi đè mạnh và đều 3–5 phút, tập trung từng vùng nhỏ, chú ý các góc và mép.
- Để nguội hẳn rồi ngâm cả tấm vào nước ấm 5–10 phút, bóc giấy thật nhẹ. Giấy decal thì bóc khi còn ấm.
- Soi kỹ: chỗ nào mực bị thiếu hoặc đứt đường thì tô lại bằng bút lông dầu (bút CD) rồi để khô.
4. Ăn mòn (etching)
- Pha dung dịch sắt(III) clorua FeCl3 theo hướng dẫn trên bao bì, hoặc dung dịch oxy già + muối ăn + a-xít; dùng hộp nhựa, KHÔNG dùng đồ kim loại.
- Nhiệt độ dung dịch khoảng 40–50°C thì ăn nhanh hơn. Lắc nhẹ hộp cho đều, thường 10–25 phút là xong.
- An toàn: đeo găng tay cao su và kính bảo hộ, làm ở nơi thoáng. Dung dịch ăn mòn làm hỏng quần áo, bồn rửa và gây bỏng rát da.
- Xong thì rửa board bằng nước sạch, lau khô, dùng xăng thơm hoặc axeton lau sạch lớp mực.
- Dung dịch đã dùng KHÔNG đổ xuống bồn rửa hay cống; đựng vào can kín và bỏ đúng nơi thu gom chất thải.
5. Khoan lỗ
- Đối chiếu trang "BẢN VẼ LỖ KHOAN" để biết lỗ nào dùng mũi nào.
- Dùng mũi khoan 0,8mm, 0,9mm và 1mm, khoan từ MẶT ĐỒNG vào để mũi tự định tâm giữa pad.
- Khoan tốc độ cao, đẩy nhẹ; mũi nhỏ rất dễ gãy. Khoan xong chà nhẹ bavia hai mặt.
6. Hàn linh kiện
- Linh kiện cắm ở MẶT KHÔNG CÓ ĐỒNG, hàn ở mặt đồng. Theo trang "MẶT LINH KIỆN" để đặt đúng vị trí và đúng chiều.
- Hàn linh kiện thấp trước (điện trở, đi-ốt), cao sau (tụ, hàng chân, board vi điều khiển).
- Chú ý chiều: LED chân dài là (+); đi-ốt có vạch trắng là K; tụ hoá có vạch là (−); transistor theo mặt chữ như nét vẽ đỏ.
- Trước khi cấp điện: đo thông mạch giữa chân nguồn và GND — KHÔNG được kêu (không được chập).
Lưu ý với board vi điều khiển
- Board nhái có thể khác thứ tự chân. Đối chiếu tên chân in cạnh từng lỗ trên trang "MẶT LINH KIỆN" với chữ in trên board thật TRƯỚC KHI ăn mòn. Nếu khác, đừng hàn mà báo lại để sửa bản vẽ.
Bản vẽ lỗ khoan
Đo kiểm bằng đồng hồ vạn năng
| Giữa 3V3 và GND | 3,2 – 3,4V |
| Giữa GPIO4 và GND lúc nghỉ | khoảng 3,3V (nhờ trở kéo lên) |
| Giữa C và E của S8050 khi còi im | khoảng 3V trở lên |
| Giữa C và E khi còi đang kêu | dưới 0,4V |
| Trang web | Nhiệt độ hiện tại chênh không quá 1°C so với nhiệt kế thường |
Sửa lỗi thường gặp
Nhiệt độ hiện −127°C
Thiếu hoặc hỏng điện trở kéo lên 4,7kΩ giữa dây dữ liệu và 3V3, hoặc dây vàng chưa vào GPIO4. Đo điện trở giữa GPIO4 và 3V3 phải khoảng 4,7kΩ.
Nhiệt độ hiện 85°C đứng yên
Đó là giá trị mặc định khi cảm biến chưa hoàn tất lần đo đầu: thường do nguồn yếu hoặc dây quá dài. Rút ngắn dây dưới 3m, dùng cục sạc 5V ≥1A.
Còi kêu dù không nóng
Ngưỡng tốc độ tăng đang quá nhạy khi mang cảm biến từ phòng lạnh ra. Tăng hằng số tốc độ trên trang Cài đặt hoặc chờ 2 phút cho ổn định.
Không thấy WiFi MachGon-BaoNhiet
ESP32 chưa chạy: xem Serial Monitor 115200. Nếu dùng cổng USB máy tính mà mạch khởi động lại liên tục thì đổi sang cục sạc 5V ≥1A.
Còi kêu nhỏ
Phải là còi chủ động 5V (cấp 5V trực tiếp là kêu ngay). Còi thụ động cần xung nên sẽ rất nhỏ hoặc im.
⚠️ An toàn
- Mạch này là thiết bị tham khảo, KHÔNG thay thế đầu báo cháy, báo khói đạt chuẩn phòng cháy chữa cháy. Nhà xưởng, kho hàng vẫn phải lắp thiết bị có chứng nhận.
- Không đặt mạch, dây hay cảm biến tiếp xúc trực tiếp với lửa, bếp đang nấu hay bề mặt trên 100°C — vỏ dây chỉ chịu được khoảng 85°C.
- Mạch chạy 5V USB, an toàn khi chạm; nên cắm vào cục sạc dự phòng để còn hoạt động khi mất điện.
- Không dùng mạch này để canh thiết bị bắt buộc phải có người trông coi.