Michael MarsicoHtoohtet
Published © MIT

Fire Alert Project

Our project is a sculpture of a building that "catches fire" whenever a new fire call is made in our local area.

IntermediateShowcase (no instructions)15 hours28
Fire Alert Project

Things used in this project

Hardware components

Photon 2
Particle Photon 2
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×3
LED Strip, NeoPixel Digital RGB
LED Strip, NeoPixel Digital RGB
×1
Speaker 5 Watt 8 Ohm
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE

Hand tools and fabrication machines

Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Box Cutter
Soldering iron (generic)
Soldering iron (generic)
Solder Wire
Paper
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Schematics

Soldered Wires

Have fun

Code

Codebase

C/C++
All of the code for this project is here in this one file :)
// import code ppl wrote for me
#include "Particle.h"
#include "neopixel.h"

// who knows what this does
SYSTEM_MODE(AUTOMATIC);

// logging stuff
SerialLogHandler logHandler(LOG_LEVEL_INFO);

// main consts
const int MOVIE_DURATION = 10000;
const unsigned long CALL_COOLDOWN = 300000; // 5 minutes: 1000 * 60 * 5

// main vars
unsigned long movieStartTime = 0;
unsigned long lastFireCall = 0;
String lastTimeStamp = "";
bool moviePlaying = false;
int eventsRan = 0;

// neopixel
#define PIXEL_PIN SPI1
#define PIXEL_COUNT 7
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

const int MIN_G = 15; // 90, 77, 40, 15
const int MAX_G = 90; // 206, 180, 110, 90
const unsigned long G_DURATION = 2000.0;

// speaker pin value
const int SPEAKER_PIN = D3;
const int LOW_TONE = 800;
const int HIGH_TONE = 1800;
const unsigned long SIREN_DURATION = 3000.0;

// servo stuff for flames
const int FLAME1_PIN = A2;
const int FLAME2_PIN = A5;
const int FLAME3_PIN = D1;

const int NUM_DELAYS = 6;
const int MOVIE_DELAYS[NUM_DELAYS] = { 300, 150, MOVIE_DURATION, 100, 100, 0 };

Servo flame1;
Servo flame2;
Servo flame3;

// light up/down lights
void renderFire() {
    strip.clear();
    if (moviePlaying) {
        double ratio = (millis() % G_DURATION) / (G_DURATION / 2.0);
        double g = 0;
        if (ratio < 1) {
            g = MIN_G + (ratio * (MAX_G - MIN_G));
        } else {
            ratio -= 1;
            g = MAX_G - (ratio * (MAX_G - MIN_G));
        }
        for (int i = 0; i < strip.numPixels(); i++) {
            strip.setColor(i, 255, g, 0);
        }
    }
    strip.setBrightness(255);
    strip.show();
}

// plays tone, thanks mccaffery
void playTone(int frequency) {
    if (frequency != 0) {
        int period = 1000000 / frequency; // Calculate period in microseconds
        int pulseWidth = period / 2; // 50% duty cycle
        digitalWrite(SPEAKER_PIN, HIGH); // Turn on the speaker
        delayMicroseconds(pulseWidth); // Keep it on for half the period
        digitalWrite(SPEAKER_PIN, LOW); // Turn off the speaker
        delayMicroseconds(pulseWidth); // Keep it off for half the period
    } else {
        digitalWrite(SPEAKER_PIN, LOW);
    }
}

void renderSiren() {
    if (moviePlaying) {
        double ratio = (millis() % SIREN_DURATION) / (SIREN_DURATION / 2.0);
        double freq = 0;
        if (ratio < 1) {
            freq = LOW_TONE + (ratio * (HIGH_TONE - LOW_TONE));
        } else {
            ratio -= 1;
            freq = HIGH_TONE - (ratio * (HIGH_TONE - LOW_TONE));
        }
        playTone(freq);
    } else {
        playTone(0);
    }
}

// "cue the music" ahh function
void renderMovie() {
    if (!moviePlaying) return;
    
    unsigned long difference = millis() - movieStartTime;
    unsigned long timePassed = 0;
    
    for (int i = 0; i < eventsRan; i++) {
        timePassed += MOVIE_DELAYS[i];
    }
    
    if (difference > timePassed) {
        if (eventsRan == 0) {
            flame1.write(10);
        } else if (eventsRan == 1) {
            flame2.write(170);
        } else if (eventsRan == 2) {
            flame3.write(10);
        } else if (eventsRan == 3) {
            flame1.write(170);
        } else if (eventsRan == 4) {
            flame2.write(10);
        } else if (eventsRan == 5) {
            flame3.write(170);
        } else if (eventsRan == 6) {
            moviePlaying = false;
        }
        eventsRan++;
    }
}

void setup() {
    // neopixel
    strip.begin();
    strip.clear();
    strip.show();
    
    // speaker
    pinMode(SPEAKER_PIN, OUTPUT);
    
    // servos
    flame1.attach(FLAME1_PIN);
    flame2.attach(FLAME2_PIN);
    flame3.attach(FLAME3_PIN);
    
    flame1.write(170);
    flame2.write(10);
    flame3.write(170);
    
    // webhook connection to event response
    Particle.subscribe("hook-response/get-last-fire-call", handleEventResponse);
    Serial.begin(9600);
    Serial.println("Photon Setup Complete!");
    Serial.println();
    
    delay(1000);
    
    // call api to have a value to compare to
    Serial.println("Publishing get-last-fire-call...");
    Serial.println("");
    Particle.publish("get-last-fire-call");
}

void loop() {
    // call api every CALL_COOLDOWN (5 minutes)
    const unsigned long now = millis();
    if (now > lastFireCall + CALL_COOLDOWN) {
        lastFireCall = now;
        Serial.println("Publishing get-last-fire-call...");
        Serial.println("");
        Particle.publish("get-last-fire-call");
    }
    
    // make sure components are in the correct state depending on if movie is playing
    renderFire();
    renderSiren();
    renderMovie();
}

void handleEventResponse(const char *event, const char *data)
{
    String responseString = String(data);
    
    char stringBuffer[256] = "";
    responseString.toCharArray(stringBuffer, 256);
    
    String timeStamp = strtok(stringBuffer, "_");
    String dateTime = strtok(NULL, "_");
    String fireDepartment = strtok(NULL, "_");
    
    Serial.println("Response Received: " + responseString);
    Serial.println("Time Stamp: " + timeStamp);
    Serial.println("Date Time: " + dateTime);
    Serial.println("Fire Department: " + fireDepartment);
    Serial.println();
    
    if (timeStamp == NULL || timeStamp.equals(lastTimeStamp)) return;
    lastTimeStamp = timeStamp;
    
    Serial.println("New Fire Call Found!");
    
    if (moviePlaying) return;
    movieStartTime = millis();
    eventsRan = 0;
    moviePlaying = true;
    
    Serial.println("Starting Movie...");
    Serial.println();
}

Credits

Michael Marsico
2 projects • 0 followers
life is roblox
Htoohtet
0 projects • 0 followers
Thanks to Htoo Htet.

Comments