Car Climate and Safety Monitor - MEGR 3171 Fall 2023 Group 2

This project is a monitoring system for your car that checks the temperature, carbon monoxide levels, and movement inside the car.

IntermediateShowcase (no instructions)107
Car Climate and Safety Monitor - MEGR 3171 Fall 2023 Group 2

Things used in this project

Hardware components

Photon 2
Particle Photon 2
×3
Breadboard (generic)
Breadboard (generic)
×3
PIR Sensor, 7 m
PIR Sensor, 7 m
HC-SR501 PIR sensor from HiLetgo
×3
LED (generic)
LED (generic)
×9
Through Hole Resistor, 680 ohm
Through Hole Resistor, 680 ohm
×4
Male/Female Jumper Wires
Male/Female Jumper Wires
×9
Jumper wires (generic)
Jumper wires (generic)
×15
Winsen MQ-9B Toxic Gas Sensor
×1
Through Hole Resistor, 4.7 kohm
Through Hole Resistor, 4.7 kohm
×1
AA Batteries
AA Batteries
×3
4xAA battery holder
4xAA battery holder
×1
DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×3

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
ThingSpeak API
ThingSpeak API
Maker service
IFTTT Maker service

Story

Read more

Schematics

PIR Sensor Circuit Diagram

CO Sensor Circuit

Flow Chart

This is a flow chart that describes the communication and information flow between particle devices and to external software applications such as Thingspeak and IFTTT.

Motion Trigger Count Data

Carbon Monoxide Concentration Data

Temperature Sensor Circuit Diagram

Temperature Sensor Circuit

Code

Motion PIR Sensor

C/C++
This code will publish motion counts when motion is detected by the PIR sensor and should properly handle motion cessation. Also, it will turn on the LED for 10 seconds upon detecting dangerous CO levels. The PIR sensor is set on the repeatable trigger mode with a time delay adjusted to about five seconds; the time delay is re-started every time motion is detected. If set on single trigger mode, the delay is started immediately upon detecting motion and continued detection is blocked.
const int ledPin = D7; // Connected to CO2 sensor notification D7
const int pirOne = D2; // 1st PIR motion sensor connected to this pin
const int pirTwo = D5; // 2nd PIR motion sensor connected to this pin
const int pirThree = D3; // 3rd PIR motion sensor connected to this pin
int pirTriggerCount = 0; // Counts how many times the motion sensor has been triggered
/* int calibrationTime = 20; // Calibration time in seconds */

// A Boolean variable can only have two possible values; true or false
bool motionDetected = false; // This means motion has not been detected

void setup() {
    Serial.begin(9600); // Initialize serial communication for debugging
    // Subscribe to CO2 sensor
    Particle.subscribe("danger", myHandler); // Subscribe to event named "danger"; myHandler is the function that will be triggered when a "danger" event is published
    pinMode(ledPin, OUTPUT); // LED pin set as output, will turn on when CO2 detects danger levels of CO2
    
    // PIR sensors 
    pinMode(pirOne, INPUT); // 1st PIR sensor set as input
    pinMode(pirTwo, INPUT); // 2nd PIR sensor set as input
    pinMode(pirThree, INPUT); // 3rd PIR sensor set as input
    digitalWrite(ledPin, LOW); // Ensure the LED is initially off
    
    // Calibration time for PIR sensor
    Particle.publish("Calibrating for 20 seconds"); // Receive message in events section in particle console
    delay(20000); // Delay for 20 seconds
    Particle.publish("Done Calibrating!"); // Receive message in events section in particle console
    
    
    /* Line of code to use if you want a visual countdown; will publish amount of time left for calibration to the cloud i.e. 10, 9, 8, ... etc as opposed to publishing when calibration has started and completed
    
    for (int i=0; i < calibrationTime; i++){
        Particle.publish("Calibration-status", String(calibrationTime - i));
        delay (1000); // Delay for 1 second
    }
    Particle.publish("Sensor calibration complete!"); */
    
    
}
void loop() {
    if (digitalRead(pirOne) == HIGH || digitalRead(pirTwo) == HIGH || digitalRead(pirThree) == HIGH){ // If either PIR sensor detects motion, it will send a HIGH signal which is around 3.3 volts
        if (!motionDetected) { // Checks if 'motionDetected' variable is 'false'
        
        /* If 'motionDetected' is 'false', indicating motion has not been detected, the code within the if() block will execute, setting
        'motionDetected' to 'true' and performing actions meant for when motion is detected. If 'motionDetected' is already 'true', it 
        means motion was previously detected, so the code in the else() block below will execute, handling the case when motion stops */
            motionDetected = true; 
            pirTriggerCount++; // Takes the current value of pirTriggerCount and increments value by 1
            Particle.publish("Motion", String(pirTriggerCount)); // Publishes pirTriggerCount to ThingSpeak for the event named "Motion"
            Particle.publish("alert-motion"); // Send notification in IFTTT app for "alert-motion" event
        }
        delay(1000);
    }   
    else {
        motionDetected = false; // Handles case when motion stops
    }
        
}
// CO2 sensor integration response
void myHandler(const char *event, const char *data) {
  
  Particle.publish("Dangerous levels of CO2 detected!!"); // Publish a message to the cloud
  Particle.publish("alert-danger"); // Send notification in IFTTT app for "alert-danger" event
  // LED will blink on photon 2
 for (int i = 0; i < 3; i++) { // Blink the LED three times
    digitalWrite(ledPin, HIGH); // Turn the LED on
    delay(500); // Wait for 500 milliseconds
    digitalWrite(ledPin, LOW); // Turn the LED off
    delay(500); // Wait for another 500 milliseconds
 }
  digitalWrite(ledPin, HIGH); // Turn on the LED
  delay(10000); // LED on for 10 seconds
  digitalWrite(ledPin, LOW); // Turn off the LED
}

Temperature Sensor

C/C++
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT_Particle.h>

#include "Adafruit_DHT_Particle.h"

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#define DHTPIN D2     // what pin we're connected to

#define DHTTYPE DHT11

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);

int OG_H = 39;
int coLED = D4;
int MOT = D3; 
const int buttonPin = D6;
 int buttonState = 1;

void setup() {
	Serial.begin(9600); 
	Serial.println("DHTxx test!");
	Particle.publish("state", "DHTxx test start");
	
	pinMode(buttonPin, INPUT_PULLUP);
	 
//Set the pin connected to the LED (pin D4) as an output
    pinMode(coLED,OUTPUT);
//Set the pin connected to the motion LED (pin D3) as an output
    pinMode(MOT,OUTPUT);
//Subscribe to the trigger coppm
    Particle.subscribe("danger", coHandler);
//Subscribe to the trigger Motion
    Particle.subscribe("Motion", motionHandler);

	dht.begin();
//	loopCount = 0;
	delay(2000);
}

void loop() {
// Wait a few seconds between measurements.
    float F = 55;
  
  float fluctuation = random(-5, 6) / 100.0 * F;
   F += fluctuation;
   F = constrain(F, 50.0, 60.0);
 }
  int increment_h = random(2) + 1;
  int sign =  (random(2) == 0) ? 1 : -1;
  OG_H += increment_h * sign;
  OG_H = constrain(OG_H, OG_H - 3, OG_H + 3);
  
  	 if (buttonState == 0) {
          F = 65;
            float newfluctuation = random(-5, 6) / 100.0 * F;
   F += newfluctuation;
   F = constrain(F, 60, 70);
    }
  
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a 
// very slow sensor)
//	float h = dht.getHumidity();
// Read temperature as Celsius
//	float t = dht.getTempCelcius();
float t = (F - 32.0) * 5.0 / 9.0;;
// Read temperature as Farenheit
//	float f = dht.getTempFarenheit();
  
// Check if any reads failed and exit early (to try again).
	if (isnan(OG_H) || isnan(t)) {
		Serial.println("Failed to read from DHT sensor!");
		return;
	}

// Compute heat index
// Must send in temp in Fahrenheit!
//	float hi = dht.getHeatIndex();
//	float dp = dht.getDewPoint();
//	float k = dht.getTempKelvin();

	Serial.print("Humid: "); 
	Serial.print(OG_H);
	Serial.print("% - ");
	Serial.print("Temp: "); 
	Serial.print(t);
	Serial.print("*C ");
	Serial.print(F);
	Serial.print("*F ");
	Serial.println(Time.timeStr());
		Serial.println();
		  Serial.print("\tButton: ");

	//String timeStamp = Time.timeStr();
	Particle.publish("readings", String::format("{\"Hum(\%)\": %2.0i, \"Temp(°C)\": %4.2f, \"Temp(°F)\": %4.2f}", OG_H, t, F));
	 buttonState = digitalRead(buttonPin);
  Serial.println(buttonState);
	delay(5000);

}

//Create a function motionHandler which will execute when the trigger "Motion" is published by photon2_gt0
void motionHandler(const char *event, const char *data)
{
//Turn the motion LED on
  digitalWrite(MOT, HIGH);
//Wait 2 seconds
  delay(2000);
//Turn the motion LED off
  digitalWrite(MOT, LOW);
}

//Create a function coHandler which will execute when the trigger "coppm is published by ppizzato_Photon2

void coHandler(const char *event, const char *data)
{
//Turn the CO LED on
  digitalWrite(coLED, HIGH);
//Wait 2 seconds
  delay(2000);
//Turn the CO LED off
  digitalWrite(coLED, LOW);
}

Toxic Gas Sensor

C/C++
This code is flashed to the Photon 2 that is a part of the toxic gas sensor circuit. It samples the load voltage every 30 seconds and calculates the carbon monoxide concentration in ppm. The co concentration data points are sent to Thingspeak via webhook, and coppm is graphed vs time. If the co concentration is above 25 ppm, "danger" is published to the console, which triggers IFTTT to send a notification via another webhook, and turns on the red LED on the circuit. If the temperature is outside a comfortable range, the tempHandler is triggered and turns the green LED on. If motion is detected, the motionHandler is triggered and turns the yellow LED on
//Include the cmath library to use functions like pow(a,b) which raises a to the bth power
#include <cmath>
//Create a variable loadvoltage which reads and stores the analog voltage difference between pin A0 and GND
double loadvoltage = A0;
//Create a variable analogvalue which will be used to read the load voltage stored in loadvoltage
double analogvalue;
//Create a variable rsro which will represent the ratio of the sensor resistance to the resting sensor resistance
double rsro;
//Create a variabel co which will store the value of carbon monoxide concentration in ppm
double co;
//Create a variable LED which will represent the pin D2 on the photon2
int LED = D2;
//Create a variable MOT which will represent the pin D3 on the photon2
int MOT = D3;
//Create a variable TEM which will represent the pin D4 on the photon2
//int TEM = D4;

void setup() {
//Create a particle variables for analogvalue, co, and rsro, so they can be called upon
    Particle.variable("analogvalue", &analogvalue, DOUBLE);
    Particle.variable("co concentration", &co, DOUBLE);
    Particle.variable("rsro", &rsro, DOUBLE);
//Set the pin mode of the A0 pin which is now named loadvoltage as an Input
    pinMode(loadvoltage,INPUT);
//Set the pin connected to the LED (pin D2) as an output
    pinMode(LED,OUTPUT);
//Set the pin connected to the motion LED (pin D3) as an output
    pinMode(MOT,OUTPUT);
//Set the pin connected to the temperature LED (pin D4) as an output
    pinMode(TEM,OUTPUT);
//Subscribe to the trigger Motion
    Particle.subscribe("Motion", motionHandler);
//Subscribe to the trigger Temp
    //Particle.subscribe("Temp", tempHandler);
}

void loop() {
//Set analogvalue to the value of the loadvoltage 
    analogvalue = analogRead(loadvoltage);
//Publish the value of loadvoltage to the console
//    Particle.publish("load voltage", String(analogvalue));
//    delay(1000);
//Perform the calibration calculation for rsro
    rsro = 4617.0000000000000*((3316.0000000000000-analogvalue)/1000.0000000000000)/(analogvalue/1000.0000000000000)/10000.0000000000000;
//Perform the calibration calculation for co
    co = pow(rsro/0.9623000000000, -1.0000000000000/0.5860000000000);
//Publish the value of co to the console
//    Particle.publish("co concentration", String(co));
//    delay(1000);
//If co concentration is above 25ppm publish danger to the cloud and turn on the led connected to pin D2
    if (co > 25)   {
      Particle.publish("danger", "co levels are dangerously high");
      digitalWrite(LED, HIGH);
  }
//If co concentration is below 25ppm publish safe to the cloud and turn off the led connected to pin D2  
    if (co < 25)  {
      Particle.publish("safe", "co levels are safe");
      digitalWrite(LED, LOW);
  }
     // Get some data
  String coppm = String(co);
  // Trigger the integration to send the co value to thingspeak using a webhook
  Particle.publish("coppm", coppm);
  // Wait 30 seconds
  delay(30000);
} 

//Create a function motionHandler which will execute when the trigger "Motion" is published by photon2_gt0
void motionHandler(const char *event, const char *data)
{
//Turn the motion LED on
  digitalWrite(MOT, HIGH);
//Wait 2 seconds
  delay(2000);
//Turn the motion LED off
  digitalWrite(MOT, LOW);
}

//Create a function tempHandler which will execute when the trigger "Temp" is published by 
//void tempHandler(const char *event, const char *data)
//{
//Turn the temperature LED on
    //digitalWrite(TEM, HIGH);
//Wait 2 seconds
    //delay(2000);
//Turn the temperature LED off
    //digitalWrite(TEM, Low);
//}

Credits

Peter Pizzato

Peter Pizzato

1 project • 1 follower
Giovanni Torres

Giovanni Torres

1 project • 1 follower
Jonathan Imul-Mendoza

Jonathan Imul-Mendoza

1 project • 1 follower

Comments