
近年来国内乘用车数量达到一个非常高的数量,但是报纸上时有儿童被忘在车内的情况,后果严重者影响儿童生命健康。本项目旨在利用部署在车内的多个超声波传感器来判断车内人员活动情况,并且结合四个车门的状态来甄别儿童单独在车内的情况。如果出现这种状态达到3min,启动报警功能。本项目提供的报警包括
1)通过MQTT服务通知驾驶员手机,其中wifi功能由现有的ESP模块来提供;
2)检测到后座上儿童活动后,触发报警,通过MQTT客户端通知家长
3)检测到后座上儿童活动后,发送给别的报警单元
项目实现:为了检测遗留车内儿童活动,本项目使用超声波传感器。在车内没有儿童活动的时候,超声波传感器的数据维持不变,但是有儿童来回活动,遮挡住超声波传感器的时候,数据摆幅非常大,以此来作为一个判断依据。在实现上,采用了一颗乐鑫公司的ESP32S3单片机来专门用于采集超声波传感器数据。
本次项目采用的传感器型号是:HC-SR04,其基本工作原理如下:
  
ESP32S3采集超声波数据和声音传感器的数据,开发环境使用Arduino,利用FreeRTOS创建了两个单独的线程来分别处理传感器数据和MQTT。
xTaskCreatePinnedToCore( TaskMqtt , "TaskMqtt" // A name just for humans , 10240 // This stack size can be checked & adjusted by reading the Stack Highwater , NULL , 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. , NULL , 1); xTaskCreatePinnedToCore( TaskSensor , "TaskSensor" // A name just for humans , 1024 // This stack size can be checked & adjusted by reading the Stack Highwater , NULL , 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. , NULL , 1);
 
在检测逻辑上,主要判断依据是座椅上没有人的时候,超声波传感器数据变动不会超过5cm。当前传感器固定位置距离橱窗的距离是57cm,当有物体进入检测范围后,测量距离会变化。
if(fabs((int)distance -  57) >= 5){
    display.println(F("HASCHILD"));
    digitalWrite(WarningPin, HIGH);
    digitalWrite(WarningPinExt, HIGH);
    childDetectFlag = 1;
    Serial.println("Child Detected");
  }else{
    display.println(F("NO CHILD"));
    digitalWrite(WarningPin, LOW);
    digitalWrite(WarningPinExt, LOW);
    Serial.println("No Child Found");
 }实物照片:
手机MQTT客户端使用的是MQTT DashBoard。


附完整源代码:
/**************************************************************************
 This is to detect any child alone in the car.
 Mainly to use ultrasonic sensors to detect the child and
 then report via MQTT to the parent.
 **************************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <WiFi.h>
#include "secrets.h"
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32. SensorYoung: 2024/1/29 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES     10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };
const int TrigPin = 16;
const int EchoPin = 17;
const int WarningPinExt = 4;
const int WarningPin = 2; //2/D9 is the User LED on ESP32,高电平点亮LED
static float distance = 0;
void HC_SR04_DistMeasure(void);
//----------------------------MQTT Related Start ---------------------
char ssid[] = SECRET_SSID;   // your network SSID (name) 
char pass[] = SECRET_PASS;   // your network password
const char* mqtt_server = "broker.hivemq.com";     // hivemq 的信息中转服务
const unsigned short mqtt_server_port = 1883;
const char* pubTOPIC = "car/backseat/childDetect/";    // 发布信息主题
const char* client_id = "clientId-tobeasafecar";    // 标识当前设备的客户端编号
WiFiClient  espClient;
PubSubClient client(espClient);   // 定义PubSubClient的实例
long lastMsg = 0;                 // 记录上一次发送信息的时长
unsigned char childDetectFlag = 0;
//----------------------------MQTT Related END ---------------------
/*-------------------------------------------------------------*/
/*---------------------- Tasks - setup () ---------------------*/
/*-------------------------------------------------------------*/
void setup() {
  Serial.begin(115200);
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  WiFi.mode(WIFI_STA); 
  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds
  pinMode(TrigPin, OUTPUT);
  pinMode(EchoPin, INPUT);
  pinMode(WarningPin, OUTPUT);
  digitalWrite(WarningPin, LOW);
  pinMode(WarningPinExt, OUTPUT);
  digitalWrite(WarningPinExt, LOW);
  Serial.println("HC-SR04 Init done.");  
  // Now set up tasks to run independently.
  #if 1
  xTaskCreatePinnedToCore(
    TaskMqtt
    ,  "TaskMqtt"   // A name just for humans
    ,  10240  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  1  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  NULL 
    ,  1);
#endif
  xTaskCreatePinnedToCore(
    TaskSensor
    ,  "TaskSensor"   // A name just for humans
    ,  1024  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  NULL 
    ,  1);
}
/*-------------------------------------------------------------*/
/*---------------------- Tasks - mainloop ---------------------*/
/*-------------------------------------------------------------*/
void TaskSensor(void *pvParameters)  // This is a task.
{
  (void) pvParameters;
  for(;;){
      digitalWrite(TrigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(TrigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(TrigPin, LOW);
      distance = pulseIn(EchoPin, HIGH)/58.00;
      vTaskDelay(pdMS_TO_TICKS(1000));    //休眠1000毫秒 
  }
}
void HC_SR04_DistMeasure(void){
  digitalWrite(TrigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(TrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TrigPin, LOW);
  distance = pulseIn(EchoPin, HIGH)/58;  
}
void loop() {
  //HC_SR04_DistMeasure();
  display.clearDisplay();
  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);     // Start at top-left corner
  display.println(F("HC-SR04"));    //display.display(); 
  display.println(F("DISTANCE:"));  //display.display(); 
  display.println((int)distance);   //display.display(); 
  if(fabs((int)distance -  57) >= 5){
    display.println(F("HASCHILD"));
    digitalWrite(WarningPin, HIGH);
    digitalWrite(WarningPinExt, HIGH);
    childDetectFlag = 1;
    Serial.println("Child Detected");
  }else{
    display.println(F("NO CHILD"));
    digitalWrite(WarningPin, LOW);
    digitalWrite(WarningPinExt, LOW);
    Serial.println("No Child Found");
 }
     
  display.display(); 
   
  Serial.print(distance);
  Serial.println("cm");  
  delay(1000);
}
/*-------------------------------------------------------------*/
/*---------------------- Tasks - TaskMqtt ---------------------*/
/*-------------------------------------------------------------*/
void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(client_id)) {
      Serial.println("connected");
      // 连接成功时订阅主题
      //client.subscribe(TOPIC);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
#if 0
void TaskMqtt(void *pvParameters)  // This is a task.
{
  (void) pvParameters;
  for(;;){
    ;
  }
}
#endif
#if 1
void TaskMqtt(void *pvParameters)  // This is a task.
{
  (void) pvParameters;
  Serial.print("TaskMqtt 在核心 ");Serial.print(xPortGetCoreID());Serial.println(" 上运行");
  // Connect or reconnect to WiFi
  // Connect or reconnect to WiFi
  if(WiFi.status() != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print(".");
      delay(5000);    
    } 
    Serial.println("\nConnected.");
  }
  client.setServer(mqtt_server, mqtt_server_port);  //设定MQTT服务器与使用的端口,1883是默认的MQTT端口
  for (;;) // A Task shall never return or exit.
  {
      if (!client.connected()) {
        reconnect();
      }
      client.loop();
      
      if (childDetectFlag) {
        childDetectFlag = 0;
        if(client.publish(pubTOPIC, "Child in the CAR!!")){
            Serial.println("Publish Topic:");Serial.println(pubTOPIC);
            Serial.println("Publish message:");Serial.println("Child in the CAR!!");    
          } else {
            Serial.println("Message Publish Failed."); 
          } 
          
      }//endif
  }//end for-loop
}//end TaskMQTT
#endif
 
					
				
 
			
			
			
						
			 我要赚赏金
 我要赚赏金 STM32
STM32 MCU
MCU 通讯及无线技术
通讯及无线技术 物联网技术
物联网技术 电子DIY
电子DIY 板卡试用
板卡试用 基础知识
基础知识 软件与操作系统
软件与操作系统 我爱生活
我爱生活 小e食堂
小e食堂

