Community project

Cảnh Báo Trẻ Trong Xe

Photo of Cảnh Báo Trẻ Trong Xe
Generated with AI

Nguyễn Gia Vũ

Published November 4, 2026

This project builds a child-in-vehicle alert system that monitors air quality and temperature inside a parked car, sending SMS alerts and making calls to a guardian when dangerous conditions are detected. The system uses an Arduino Uno to read CO2 levels from a CCS811 sensor and temperature/humidity from a DHT11 sensor, then triggers visual and audio alarms (LEDs and a piezo buzzer) while communicating via an LTE modem to notify caregivers of emergencies.

This guide provides a complete parts list, wiring diagram showing connections between the Arduino, sensors, modem, and alert components, step-by-step assembly instructions, and fully commented firmware. Builders will learn how to integrate environmental sensors with cellular communication, implement multi-level alert thresholds based on CO2 concentration, and safely manage power distribution across multiple voltage domains.

Wiring diagram

Loading diagram…

Gather all the parts

QtyComponent
1

Adafruit CCS811 breakout 3566

Only regulated, level-shifted Adafruit version; eCO2 estimate, NOT true CO2.

1

DHT11 3-5V sensor (Adafruit 386)

DHT11 rated 3 to 5V power and I/O per https://learn.adafruit.com/dht ; use pullup 10k. Not the catalog DFR0067 3.3V record.

1

Banlinhkien FS-MCore-A7680C LANS

Photo-matched breakout; select 5-12V solder bridge. UART accepts 5V per vendor; default 115200.

1

24v Buck Converter

LM2596-based adjustable step-down buck converter module. Commonly used to regulate a higher battery rail, such as a 2S 18650 pack, down to 5V for Arduino logic. It is a regulator, not a charger or battery protection board.

1

Regulated isolated 12V 3A adapter

Regulated isolated 12V 3A adapter

1

DC 5.5mm jack center positive

DC 5.5mm jack center positive

1

LED 1

LED 1

1

330 ohm resistor

330 ohm resistor

1

LED 2

LED 2

1

330 ohm resistor

330 ohm resistor

1

10k ohm DHT pullup

10k ohm DHT pullup

1

5V active piezo buzzer <=20mA

5V active piezo buzzer <=20mA

1

2N3904 NPN transistor

2N3904 NPN transistor

1

1k ohm base resistor

1k ohm base resistor

1

100k ohm base pulldown

100k ohm base pulldown

1

1000uF 10V electrolytic capacitor

1000uF 10V electrolytic capacitor

Assemble it in 7 steps

1. Chuẩn bị mô hình thử nghiệm

Dùng nguồn bàn 12V 3A cách ly. Đây là mô hình eCO2, không dùng để bảo vệ trẻ em. CCS811 phải là bo Adafruit 3566 có ổn áp và chuyển mức, không thay bằng bo CCS811 bất kỳ.

  • Không nối trực tiếp vào ắc quy hoặc nguồn xe; mạch chưa có bảo vệ xung điện ô tô.
  • Không thử nghiệm bằng cách nhốt người hoặc tạo khí nguy hiểm.

2. Chỉnh nguồn trước khi nối thiết bị

Nối adapter qua jack DC (tâm dương) tới VIN+/VIN- của LM2596. Chưa nối tải, dùng đồng hồ chỉnh VOUT đúng 5.0V. Ngắt nguồn rồi mới nối tiếp.

  • Điện áp ra sai có thể phá hỏng toàn bộ mạch.

3. Cấp nguồn bo modem

Trên bo Banlinhkien trong ảnh, kiểm tra cầu hàn chọn 5-12V, KHÔNG chọn BAT. VOUT+ cấp VCC modem và đường 5V; VOUT- nối GND chung. Tụ 1000uF đặt sát VCC modem, chân âm về GND. Dùng dây nguồn ngắn và đủ lớn. Gắn anten LTE phù hợp vào đầu nối anten và lắp nano SIM khi tắt nguồn.

  • Đảo cực tụ có thể làm tụ nóng hoặc nổ.
  • Không cấp modem từ chân 5V Arduino; lấy trực tiếp từ bộ hạ áp.

4. Nối Arduino và đường truyền modem

Nguồn 5V đã chỉnh cấp vào chân 5V Uno, GND nối chung. TXD modem → D8 (Arduino nhận); RXD modem → D9 (Arduino gửi). Dùng tên in trên bo, không đoán theo vị trí hàng chân. Các chân modem khác để trống.

  • Khi cắm USB để Deploy, ngắt dây nguồn 5V từ LM2596 tới Uno; giữ GND chung và nguồn riêng cho modem. Không nối đồng thời hai nguồn 5V vào Uno.

5. Nối hai cảm biến

CCS811 VIN → 5V, GND và WAKE → GND, SDA → A4 (dữ liệu), SCL → A5 (xung nhịp). DHT11 VCC → 5V, GND → GND, DATA → D2; điện trở 10k nối DATA lên 5V. Kiểm tra chân theo nhãn của cảm biến, không suy từ màu dây.

  • CCS811 cần ổn định ít nhất 20 phút mỗi lần bật, chạy làm quen khoảng 48 giờ lần đầu; eCO2 không phải phép đo CO2 thực.
  • DHT11 có sai số lớn; ngưỡng 40 và 42 độ chỉ phục vụ mô phỏng.

6. Nối LED và còi

D4 → điện trở 330Ω → cực A LED1; D5 → điện trở 330Ω → cực A LED2. Hai cực K về GND. Còi piezo chủ động 5V tối đa 20mA: cực + về 5V, cực - tới C transistor 2N3904; E về GND; D6 qua điện trở 1k tới B. Điện trở 100k nối B về GND. Tra đúng B/C/E theo vỏ transistor bạn mua.

7. Kiểm tra trước khi vận hành

Kiểm tra nguồn 5V không sụt khi modem phát. SIM phải có SMS, thoại, tài khoản và VoLTE được nhà mạng hỗ trợ trên A7680C. Chỉ thử với số người giám hộ đồng ý nhận tin; không dùng số khẩn cấp.

  • Hai LED luân phiên và còi ngắn mỗi 5 giây báo lỗi cảm biến, không có nghĩa môi trường an toàn.
  • Cuộc gọi bị ngắt 20 giây tính từ lệnh quay số, không đảm bảo điện thoại đổ chuông đủ 20 giây. Không có microphone/loa thoại trong mạch này.

Review all connections

1. Connections between "supply" and "Arduino"

FunctionsupplyArduino
powerPLUS → DC 5.5mm jack center positive CENTEREXT
groundMINUS → DC 5.5mm jack center positive SLEEVEEXT

2. Connections between "jack" and "Arduino"

FunctionjackArduino
powerCENTER → 24v Buck Converter VIN+EXT
groundSLEEVE → 24v Buck Converter VIN-EXT

3. Connections between "buck" and "Arduino"

FunctionbuckArduino
groundVIN-GND
groundVOUT-GND
powerVOUT+5V

4. Connections between "modem" and "Arduino"

FunctionmodemArduino
powerVCC5V
groundGNDGND
uartTXDGPIO 8
uartRXDGPIO 9

5. Connections between "cap" and "Arduino"

FunctioncapArduino
powerPLUS5V
groundMINUSGND

6. Connections between "gas" and "Arduino"

FunctiongasArduino
powerVIN5V
groundGNDGND
i2cSDAGPIO 18
i2cSCLGPIO 19
groundWAKEGND

7. Connections between "dht" and "Arduino"

FunctiondhtArduino
powerVCC5V
groundGNDGND
dataDATAGPIO 2

8. Connections between "pull" and "Arduino"

FunctionpullArduino
power15V
data2 → DHT11 3-5V sensor (Adafruit 386) DATAEXT

9. Connections between "led1" and "Arduino"

Functionled1Arduino
digitalA → 330 ohm resistor 2EXT
groundKGND

10. Connections between "r1" and "Arduino"

Functionr1Arduino
data1GPIO 4

11. Connections between "led2" and "Arduino"

Functionled2Arduino
digitalA → 330 ohm resistor 2EXT
groundKGND

12. Connections between "r2" and "Arduino"

Functionr2Arduino
data1GPIO 5

13. Connections between "buzzer" and "Arduino"

FunctionbuzzerArduino
powerPLUS5V
groundMINUS → 2N3904 NPN transistor CEXT

14. Connections between "q" and "Arduino"

FunctionqArduino
groundEGND
digitalB → 1k ohm base resistor 2EXT

15. Connections between "rb" and "Arduino"

FunctionrbArduino
data1GPIO 6

16. Connections between "pd" and "Arduino"

FunctionpdArduino
data1 → 2N3904 NPN transistor BEXT
ground2GND

Deploy the firmware

// Wiring verified: modem software UART RX8 TX9; DHT D2; LED D4/D5; buzzer D6; I2C A4/A5.
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_CCS811.h>
#include <DHT.h>
#include <AltSoftSerial.h>
// Dien so nguoi giam ho theo dang +84...; de trong se KHONG goi/gui SMS.
const char PHONE[] = "+84396869634";
const uint16_t LEVEL1_PPM=1000, LEVEL2_PPM=2000, LEVEL3_PPM=5000;
const uint8_t LED1=4, LED2=5, BUZZ=6;
DHT dht(2,DHT11);
Adafruit_CCS811 gas;
AltSoftSerial modem; // Uno RX D8, TX D9
uint16_t eco2=0;
float temp=NAN;
bool gasOK=false, gasValid=false, tempValid=false;
uint32_t lastRead=0, lastGas=0, lastTemp=0, nextInit=15000;
uint32_t lastSMS=0,lastCall=0, started=0;
bool smsEver=false,callEver=false;
uint8_t level=0,initStep=0;
// Modem state: 0 init, 1 idle, 2 SMS prompt, 3 SMS result, 4 calling, 5 hangup
uint8_t state=0;
char response[140]; uint8_t used=0;
bool gotOK=false,gotError=false,prompt=false,sent=false;
void clearReply(){used=0;response[0]=0;gotOK=gotError=prompt=sent=false;}
void command(const __FlashStringHelper* s){clearReply();modem.println(s);started=millis();}
bool due(uint32_t now,uint32_t then,uint32_t interval){return (uint32_t)(now-then)>=interval;}
void receive(){
 while(modem.available()){
  char c=modem.read(); if(c=='>')prompt=true;
  if(c=='\n'){
   response[used]=0;
   if(strstr(response,"OK"))gotOK=true;
   if(strstr(response,"ERROR"))gotError=true;
   if(strstr(response,"+CMGS:"))sent=true;
   used=0;
  } else if(c!='\r' && used<sizeof(response)-1)response[used++]=c;
 }
}
void sample(uint32_t now){
 // DHT library takes a short synchronous reading; no delay-based alarm timing.
 if(!due(now,lastRead,2000))return;
 lastRead=now;
 float t=dht.readTemperature(), h=dht.readHumidity();
 if(!isnan(t)){temp=t;lastTemp=now;tempValid=true;}
 if(gasOK && gas.available() && gas.readData()==0){eco2=gas.geteCO2();lastGas=now;gasValid=true;}
 if(gasOK && !isnan(t) && !isnan(h))gas.setEnvironmentalData(h,t);
 Serial.print(F("eCO2="));Serial.print(eco2);Serial.print(F(" T="));Serial.println(temp);
}
void alarms(uint32_t now){
 bool gv=gasValid&&!due(now,lastGas,10000),tv=tempValid&&!due(now,lastTemp,10000);
 level=0;
 if(gv&&eco2>=LEVEL1_PPM)level=1;
 if((gv&&eco2>=LEVEL2_PPM)||(tv&&temp>40))level=2;
 if((gv&&eco2>=LEVEL3_PPM)||(tv&&temp>=42))level=3;
 bool fault=now>30000&&(!gv||!tv);
 digitalWrite(LED1,level>=1 || (fault&&now%1000<500));
 digitalWrite(LED2,level>=2 || (fault&&now%1000>=500));
 bool sound=level==3 || (level==2&&now%300<150) || (level==1&&now%1000<200);
 if(fault && !level)sound=now%5000<100;
 digitalWrite(BUZZ,sound);
}
void startCall(uint32_t now){
 clearReply(); modem.print(F("ATD"));modem.print(PHONE);modem.println(';');
 lastCall=now;callEver=true;started=now;state=4;
}
void network(uint32_t now){
 receive();
 if(state==0){
  if((int32_t)(now-nextInit)<0)return;
  if(initStep==0){modem.end();modem.begin(115200);command(F("AT"));initStep=1;return;}
  if(initStep==2){modem.end();modem.begin(9600);command(F("ATE0"));initStep=3;return;}
  if(gotError||due(now,started,3000)){initStep=0;nextInit=now+3000;return;}
  if(!gotOK)return;
  switch(initStep){
   case 1:command(F("AT+IPR=9600"));initStep=2;nextInit=now+300;return;
   case 2:modem.end();modem.begin(9600);command(F("ATE0"));initStep=3;return;
   case 3:command(F("AT+CMGF=1"));initStep=4;return;
   default:state=1;Serial.println(F("Modem ready"));return;
  }
 }
 if(state==4){if(due(now,started,20000)){command(F("ATH"));state=5;}return;}
 if(state==5){if(gotOK||gotError||due(now,started,3000))state=1;return;}
 if(state==2){
  if(prompt){
   clearReply();modem.print(F("MO HINH eCO2 - MUC "));modem.print(level);
   modem.print(F(" eCO2="));modem.print(eco2);modem.print(F("ppm T="));
   if(tempValid)modem.print(temp,1);else modem.print(F("LOI"));
   modem.print(F("C. KIEM TRA NGAY!"));modem.write(26);started=now;state=3;
  }else if(gotError||due(now,started,5000)) {modem.write(27);state=1;}
  return;
 }
 if(state==3){
  if(gotOK||gotError||due(now,started,30000)){
   Serial.println(sent?F("SMS accepted"):F("SMS failed/unknown"));state=1;
  }return;
 }
 if(!PHONE[0] || !level)return;
 // At level 3, place call first so a slow SMS cannot postpone the SOS call.
 if(level==3&&(!callEver||due(now,lastCall,60000))){startCall(now);return;}
 if(!smsEver||due(now,lastSMS,60000)){
  lastSMS=now;smsEver=true;clearReply();
  modem.print(F("AT+CMGS=\""));modem.print(PHONE);modem.println('"');started=now;state=2;
 }
}
void setup(){
 pinMode(LED1,OUTPUT);pinMode(LED2,OUTPUT);pinMode(BUZZ,OUTPUT);
 Serial.begin(9600);Wire.begin();Wire.setWireTimeout(25000,true);dht.begin();
 gasOK=gas.begin(0x5A);modem.begin(115200);
 Serial.println(F("DEMO ONLY: eCO2 is NOT measured CO2. Set PHONE in source."));
}
void loop(){uint32_t now=millis();network(now);sample(now);alarms(now);}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace, diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik