基于STM32单片机的儿童误锁车内远程报警系统原理图PCB

该系统采用OLED屏幕显示数据,利用霍尔传感器检测车辆运行状态,压力传感器检测司机是否在位。当车辆停止且司机离位时,若温度或二氧化碳浓度超标,系统会启动蜂鸣器报警并发送短信给预设监护人。系统支持2个报警号码存储,压力、温度和二氧化碳阈值可调,并具备人体感应和风扇降温通风功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

功能介绍:
①:系统使用OLED屏幕显示数据。
②:系统通过霍尔传感器检测车辆运行状态,运行或者停止。
③:系统通过压力传感器检测司机是否在座位上,在位或者离位。压力传感器置于驾驶座下。
④:系统检测温度数据和二氧化碳数据,当车辆停止司机离位的情况下,温度或者二氧化碳浓度超标开启蜂鸣器报警,并发送报警短信给监护人。
⑤:系统设置2个接收报警信息的号码,号码支持按键调节,号码支持掉电保存。
⑥:系统压力,温度,二氧化碳阈值支持按键调节。
⑦:系统设计有人体感应模块,检测到有人滞留的情况下,温度或者二氧化碳浓度超标才会报警。
⑧:系统设计有风扇,当温度或者二氧化碳浓度超标开启风扇降温通风。

原理图:
在这里插入图片描述

在这里插入图片描述

PCB :
在这里插入图片描述

主程序:

#define __MAIN_C
#include "main.h"

enum MODE_DF dispMode;
volatile CreatByte Flag;
uint16_t tempBuf;
float temperature = 0;
volatile int temp_max = 30;
u32 sgp30_dat = 0;
u32 CO2_CONC = 0;
volatile int CO2_CONC_max = 800;
char dis0[16];
volatile unsigned char setIndex = 0;
unsigned char timeCnt = 30; //检测是否停止计时
unsigned char timeCnt2 = 10; //检测是否没有小孩计时
unsigned char timeCnt3 = 20; //检测司机是否离开计时
uint32_t initialWeight = 0; //单位g
uint32_t Weight = 0; //单位g
uint16_t weightMin = 1000; //单位g
char phone1[] = "\"11111111111\""; //可修改电话号码
char phone2[] = "\"22222222222\"";

int main(void)
{
    // 使用HSI,SYSCLK = 4M * RCC_PLLMul_x, x:[2,3,...16],最高是64MH
    HSI_SetSysClock(RCC_PLLMul_16); //使用内部8MHz晶振,并设置PLL输出为64MHz

    DelayMs(50);
    GPIO_Config();
    DelayMs(50);
    Key_GPIO_Config();
    DelayMs(50);
    
    EEPROM_Init();
    ReadData(); //读取EEPROM数据
    if (!KEY_UP) //初始化功能
    {
        DelayMs(5);
        if (!KEY_UP)
        {
            isNewFlag = 1;
        }
        //while(!KEY_SET);
    }
    DelayMs(50);
    if (isNewFlag != 0) //判断是否为新机
    {
        unsigned char i;
        isNewFlag = 0;
        temp_max = 30;
        CO2_CONC_max = 800;
        weightMin = 1000;
        phone1[0] = '\"';
        phone2[0] = '\"';
        for (i = 1; i <= 11; i++)
        {
            phone1[i] = '1';
            phone2[i] = '1';
        }
        phone1[12] = '\"';
        phone2[12] = '\"';
        SaveData();
    }


    OLED_I2C_GPIO_Init();
    OLED_Init();
    DelayMs(250);
    OLED_Display_Off();
    OLED_Clear();

    OLED_ShowString(4*8, 2, "Welcome!", FONT_1608);
    OLED_Display_On();

    SGP30_Init();   //初始化SGP30
    do{
        SGP30_Write(0x20,0x08);
        sgp30_dat = SGP30_Read();//读取SGP30的值
        CO2_CONC = (sgp30_dat & 0xffff0000) >> 16; //计算CO2的浓度值
    }while(CO2_CONC == 400); //等待初始化完成
    DelayMs(50);
    
    DS18B20_GPIO_Init();
    DelayMs(50);

    HX711_GPIO_Config();
    initialWeight = HX711_GetInitialWeight();
    
    GENERAL_TIM_Init();
    DelayMs(1000); //延时等待GSM稳定
    USART_Config();
    USART_Cmd(DEBUG_USARTx, DISABLE);
    printf("AT+CMGF=1\r\n"); //配置GSM
    USART_Cmd(DEBUG_USARTx, ENABLE);
    
    OLED_Clear();

    while (1) //主循环
    {
        if (readFlag == 1) //200ms刷新一次
        {
            readFlag = 0;
            if (dispMode == NORMAL)
            {
                DispNormal();

                /************************* 检测车辆移动 *************************/
                if (HS_IN == 0) //霍尔传感器检测到车辆移动
                {
                    timeCnt = 30; //200ms*30, 可根据需要加长时间
                    timeCnt2 = 10; //200ms*10
                    timeCnt3 = 20; //200ms*20 //时间更长一点,避免人刚离开时误触发
                    startFlag = 1;
                    driverFlag = 1;
                    alarmFlag = 0; //启动后,清空报警标志
                    BUZZER_OFF; //关闭蜂鸣器
                    FAN_OFF; //关闭风扇
                }
                else
                {
                    if (timeCnt == 0) //倒计时结束,认为车辆停止
                    {
                        startFlag = 0;
                    }
                    else
                    {
                        timeCnt--; //霍尔传感器没检测到车辆移动,开始倒计时
                    }
                }

                Weight = HX711_Read();
                if (Weight < initialWeight)
                {
                    Weight = 0;
                }
                else
                {
                    Weight = (Weight - initialWeight) * 10 / GAPVALUE;
                }
                
                if (Weight < weightMin) //重量小于阈值,表示司机离开
                {
                    driverFlag = 0;
                }
                else
                {
                    driverFlag = 1;
                    timeCnt3 = 20; // 时间更长一点,避免人刚离开时误触发
                }

                if (IR_IN == 1) //人体传感器没有检测到小孩
                {
                    if (timeCnt2 == 0) //倒计时结束,认为没有小孩
                    {
                        babyFlag = 0; //无小孩标志
                    }
                    else
                    {
                        timeCnt2--; //霍尔传感器没检测到小孩,开始倒计时
                    }
                }
                else
                {
                    timeCnt2 = 10; // 2s,200ms*10
                    babyFlag = 1;
                }

                /************************* 车辆停止后 *************************/
                if (startFlag == 0 && alarmFlag == 0) //车辆停止
                {
                    if (driverFlag == 0) //没有司机,有儿童滞留
                    {
                        if (timeCnt3 == 0)
                        {
                            if (babyFlag == 1)
                            {
                                if (temperature <= temp_max && CO2_CONC <= CO2_CONC_max) //处于阈值范围内
                                {
                                    BUZZER_OFF; //关闭蜂鸣器
                                    FAN_OFF; //关闭风扇
                                }
                                else
                                {
                                    alarmFlag = 1; //报警标志
                                    BUZZER_ON; //打开蜂鸣器
                                    FAN_ON; //打开风扇
                                    SendMessage(); //向目标手机发送短信
                                }
                            }                            
                        }
                        else
                        {
                            timeCnt3--; //开始倒计时,避免误触发
                        }
                    }
                }
            }
        }
        KeyProcess();
    }
}

void ReadData(void)
{
    uint16_t i;

    isNewFlag = EEPROM_ReadByte(0x00);
    temp_max = EEPROM_ReadByte(0x01);
    temp_max = (temp_max<<8) + EEPROM_ReadByte(0x02);
    CO2_CONC_max = EEPROM_ReadByte(0x03);
    CO2_CONC_max = (CO2_CONC_max<<8) + EEPROM_ReadByte(0x04);
    weightMin = EEPROM_ReadByte(0x05);
    weightMin = (weightMin<<8) + EEPROM_ReadByte(0x06);
    for (i = 0; i < 13; i++)
    {
        phone1[i] = EEPROM_ReadByte(0x07+i);
    }
    for (i = 0; i < 13; i++)
    {
        phone2[i] = EEPROM_ReadByte(0x20+i);
    }
}

void SaveData(void)
{
    uint16_t i;

    EEPROM_WriteByte(0x00, isNewFlag);
    EEPROM_WriteByte(0x01, (temp_max>>8));
    EEPROM_WriteByte(0x02, (temp_max&0x00FF));
    EEPROM_WriteByte(0x03, (CO2_CONC_max>>8));
    EEPROM_WriteByte(0x04, (CO2_CONC_max&0x00FF));
    EEPROM_WriteByte(0x05, (weightMin>>8));
    EEPROM_WriteByte(0x06, (weightMin&0x00FF));

    for (i = 0; i < 13; i++)
    {
        EEPROM_WriteByte(0x07+i, phone1[i]);
    }

    for (i = 0; i < 13; i++)
    {
        EEPROM_WriteByte(0x20+i, phone2[i]);
    }
}

void DispNormal(void)
{
    TIM_ITConfig(GENERAL_TIM2, TIM_IT_Update, DISABLE);
    DS18B20_GetTemp(&tempBuf); //读取温度
    temperature = tempBuf * 0.0625;

    SGP30_Write(0x20,0x08);
    sgp30_dat = SGP30_Read();//读取SGP30的值
    CO2_CONC = (sgp30_dat & 0xffff0000) >> 16; //计算CO2的浓度值

    TIM_ITConfig(GENERAL_TIM2, TIM_IT_Update, ENABLE);

    sprintf(dis0, "Temp:%5.1f", temperature);
    OLED_ShowString(0, 0, dis0, FONT_1608);
    OLED_ShowWord(10*8, 0, 0); //显示摄氏度
    

    sprintf(dis0, "CO2:%5dppm", CO2_CONC);
    OLED_ShowString(0, 2, dis0, FONT_1608);

    if (startFlag == 1) //是否启动 
    {
        OLED_ShowString(0, 4, "CarStatus:Start", FONT_1608);
    }
    else
    {
        OLED_ShowString(0, 4, "CarStatus:Stop ", FONT_1608);
    }
    
    if (driverFlag == 1) //是否有司机
    {
        OLED_ShowString(0, 6, "Driver:Y", FONT_1608);
    }
    else
    {
        OLED_ShowString(0, 6, "Driver:N", FONT_1608);
    }

    if (babyFlag == 1) //是否有儿童
    {
        OLED_ShowString(9*8, 6, "Baby:Y", FONT_1608);
    }
    else
    {
        OLED_ShowString(9*8, 6, "Baby:N", FONT_1608);
    }
}

void DispSetThreshold(uint16_t setIndex)
{
    sprintf(dis0, "TempMax:%2d", temp_max);
    OLED_ShowString(8, 0, dis0, FONT_1608); //温度阈值
    
    sprintf(dis0, "CO2Max:%5d", CO2_CONC_max); //显示CO2浓度阈值
    OLED_ShowString(8, 2, dis0, FONT_1608);

    sprintf(dis0, "WeightMin:%4d", weightMin); //显示压力阈值
    OLED_ShowString(8, 4, dis0, FONT_1608);
    
    OLED_ShowString(8, 6, "Phone1  Phone2 ", FONT_1608); //设置电话号码
    
    if (setIndex == 1)
    {
        OLED_ShowChar(8*8, 6, ' ', FONT_1608);
        OLED_ShowChar(0, 0, '>', FONT_1608);
    }
    else if (setIndex == 2)
    {
        OLED_ShowChar(0, 0, ' ', FONT_1608);
        OLED_ShowChar(0, 2, '>', FONT_1608);
    }
    else if (setIndex == 3)
    {
        OLED_ShowChar(0, 2, ' ', FONT_1608);
        OLED_ShowChar(0, 4, '>', FONT_1608);
    }
    else if (setIndex == 4)
    {
        OLED_ShowChar(0, 4, ' ', FONT_1608);
        OLED_ShowChar(0, 6, '>', FONT_1608);
    }
    else if (setIndex == 5)
    {
        OLED_ShowChar(0, 6, ' ', FONT_1608);
        OLED_ShowChar(8*8, 6, '>', FONT_1608);
    }
}


void DispSetPhone1(uint16_t setIndex)
{
    OLED_ShowString(0, 0, "Phone1:", FONT_1608); //电话号码1
    
    OLED_ShowString(0, 2, phone1, FONT_1608); //电话号码1

    if (setIndex >= 1 && setIndex <= 11)
    {
        OLED_ShowChar((setIndex-1)*8, 4, ' ', FONT_1608);
        OLED_ShowChar(setIndex*8, 4, '^', FONT_1608);
    }
}

void DispSetPhone2(uint16_t setIndex)
{
    OLED_ShowString(0, 0, "Phone2:", FONT_1608); //电话号码2
    
    OLED_ShowString(0, 2, phone2, FONT_1608); //电话号码2

    if (setIndex >= 1 && setIndex <= 11)
    {
        OLED_ShowChar((setIndex-1)*8, 4, ' ', FONT_1608);
        OLED_ShowChar(setIndex*8, 4, '^', FONT_1608);
    }
}

void SendMessage(void)
{
    char temp1[30]="AT+CMGS=";
    char temp2[30]="AT+CMGS=";

    TIM_ITConfig(GENERAL_TIM2, TIM_IT_Update, DISABLE);
    USART_Cmd(DEBUG_USARTx, ENABLE);
    printf("AT+CMGF=1\r\n");
    DelayMs(1000);
    /************************* 向手机1发送短信 *************************/
    printf("AT+CSCS=\"GSM\"\r\n");
    DelayMs(1000);
    strcat(temp1,(char*)phone1); //字符串拼接函数(库函数)
    printf(temp1);
    printf("\r\n");
    DelayMs(1000);
    printf("Please be aware of your baby!\x1a"); //可以修改短信内容
    DelayMs(5000);

    /************************* 向手机2发送短信 *************************/
    printf("AT+CSCS=\"GSM\"\r\n");
    DelayMs(1000);
    strcat(temp2,(char*)phone2); //字符串拼接函数(库函数)
    printf(temp2);
    printf("\r\n");
    DelayMs(1000);
    printf("Please be aware of your baby!\x1a"); //可以修改短信内容
    DelayMs(3000);
    
    USART_Cmd(DEBUG_USARTx, DISABLE);
    TIM_ITConfig(GENERAL_TIM2, TIM_IT_Update, ENABLE);
}

/*********************************************END OF FILE**********************/

实物演示视频:
https://www.bilibili.com/video/BV16D4y1k7Rp/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值