Hackster is hosting Impact Spotlights: Industrial Automation. Watch the stream live on Thursday!Hackster is hosting Impact Spotlights: Industrial Automation. Stream on Thursday!
Michael Marsico
Published © MIT

Warm Welcome Machine

Automatically prepares your room for whatever you want to do, treating you like royalty

BeginnerFull instructions provided2 hours53
Warm Welcome Machine

Things used in this project

Hardware components

Photon 2
Particle Photon 2
×1
Surge Protector, 1 Outlets
Surge Protector, 1 Outlets
I used one with multiple outlets because I already had one at home, but a singular outlet will work just fine.
×1
Any Old Lamp
×1
Hall Effect Sensor Module
×1
Relay Module
×1
Button
×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
To cut your old lamp's ground wires to the relay module.
Multitool, Screwdriver
Multitool, Screwdriver
To screw the wires of your old lamp down into the relay module.
Box Cutter
Cut out holes in the storage box.
Photon 2 Storage Box
Comes with your Photon 2 package.

Story

Read more

Schematics

Breadboard Diagram

This breadboard diagram should work with the current code if you do not change anything. However, there are some things to consider: the relay module I used only had three inputs, so on the diagram instead of D4, use the SWITCH pin. Also on the hall effect sensor module, 1 is analog input, 2 is power, 3 is ground. If your sensor supports overriding the LED, just connect that to D5. VIN may also be called VUSB on your Photon 2, so keep that in mind.

Code

Codebase

C/C++
All of the code for this project is here in this one file. It handles everything: managing magnetic sensor for the door, enabling the relay module, playing the song on the speaker with very little yield (just delayMicroseconds), and handling the reset button. Every pin can be easily changed in the code through the constants I declare starting on line 87.
// get libraries
#include "Particle.h"
#include <string>

// particle yap
SYSTEM_MODE(AUTOMATIC);
SerialLogHandler logHandler(LOG_LEVEL_INFO);

// constants for "Like That" by Future, Kendrick Lamar, and Metro Boomin
const int HI = 1100;
const int MID = 1000;
const int LO = 900;
const int DURATION = 133;
const int DELAY = 33;

// songs
const int SONG_LENGTH = 35;
const int SONG[SONG_LENGTH][3] = {
    // {1000, 250, 100},
    // {500, 500, 100},
    // {1000, 125, 100},
    // {1000, 125, 100},
    // {500, 500, 100},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {MID, DURATION, DELAY},
    {LO, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {HI, DURATION, DELAY},
    {HI, DURATION, DELAY},
    {HI, DURATION, DELAY},
    
    {HI, DURATION, DELAY},
    {LO, DURATION, DELAY},
    {MID, DURATION, DELAY},
    
    // {1000, 250, 0},
    // {650, 250, 0},
    // {1000, 250, 0},
    // {650, 250, 0},
    // {1000, 250, 0},
    // {650, 250, 0},
    // {1000, 250, 0},
    // {650, 250, 0},
    // {1000, 250, 0},
    // {650, 250, 0},
};

const int ANALOG_VALUE = 4095;
// const int BALANCED_VALUE = ANALOG_VALUE / 2; // 2047.5 --> 2047

// set magnet sensor pin values
const int SENSOR_POWER = D6;
const int SENSOR_LED = D5;
const int SENSOR_DATA = A0;

// set relay module pin values
const int RELAY_TOGGLE = D4;

// off button pin values
const int BUTTON = D7;

// settings values
const int STARTUP_DELAY = 1000;
const int SENSOR_BUFFER = 100;
const int BALANCED_VALUE = 2150; // im just gonna manually set it to my own tested val
const int TRIGGER_SENSITIVITY = 300;

// speaker pin values
const int SPEAKER = D1;

// last magnetic sensor value
int lastSensor = LOW;
unsigned long lastSensorTime = 0;
bool relayOn = false;
bool turnedOff = true;

// song management
bool isPlaying = false;
bool isOnDelay = false;
int noteIndex = -1;
unsigned long nextToneTime = 0;

// 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, HIGH); // Turn on the speaker
        delayMicroseconds(pulseWidth); // Keep it on for half the period
        digitalWrite(SPEAKER, LOW); // Turn off the speaker
        delayMicroseconds(pulseWidth); // Keep it off for half the period
    } else {
        digitalWrite(SPEAKER, LOW);
    }
}

void startSong() {
    isPlaying = true;
}

void stopSong() {
    isPlaying = false;
    isOnDelay = false;
    noteIndex = -1;
    nextToneTime = 0;
}

void songLoop() {
    unsigned long currentMillis = millis();
    if (currentMillis >= nextToneTime) {
        if (!isOnDelay) {
            noteIndex++;
        }
        nextToneTime = currentMillis + SONG[noteIndex][isOnDelay ? 2 : 1];
        isOnDelay = !isOnDelay;
    }
    if (noteIndex >= SONG_LENGTH) {
        stopSong();
    } else {
        playTone(isOnDelay ? SONG[noteIndex][0] : 0);
    }
}

// prepares microcontroller for use
void setup() {
    // acts as constant 5 volt power (idek if its 5 volts)
    pinMode(SENSOR_POWER, OUTPUT);
    digitalWrite(SENSOR_POWER, HIGH);
    
    // gets pin ready to toggle relay module
    pinMode(RELAY_TOGGLE, OUTPUT);
    digitalWrite(RELAY_TOGGLE, LOW);
    
    // overrides sensor default led
    pinMode(SENSOR_LED, OUTPUT);
    
    // sets input for off button
    pinMode(BUTTON, INPUT_PULLUP);
    
    // set speaker
    pinMode(SPEAKER, OUTPUT);
}

// runs over and over again
void loop() {
    // gets sensor data on strength of magnetic signal
    int sensorValue = analogRead(SENSOR_DATA);
    
    // checks if the sensor is detecting a value stronger than the trigger sensitivity
    bool isTriggered = abs(sensorValue - BALANCED_VALUE) >= TRIGGER_SENSITIVITY;
    int triggerValue = isTriggered ? HIGH : LOW;
    
    // sets led on sensor to see the sensor in action
    digitalWrite(SENSOR_LED, triggerValue);
    
    // turn on relay when door opens
    unsigned long currentMillis = millis();
    if (triggerValue == LOW) {
        if (lastSensor == HIGH) {
            lastSensorTime = currentMillis;
            turnedOff = false;
        } else if (currentMillis > STARTUP_DELAY && !turnedOff && currentMillis > lastSensorTime + SENSOR_BUFFER && !relayOn) {
            // this only runs once
            digitalWrite(RELAY_TOGGLE, HIGH);
            relayOn = true;
            startSong();
        }
    }
    lastSensor = triggerValue;
    
    // turn off song and relay module if button pressed
    int offButtonValue = digitalRead(BUTTON);
    if (offButtonValue == LOW) {
        digitalWrite(RELAY_TOGGLE, LOW);
        relayOn = false;
        turnedOff = true;
        stopSong();
    }
    
    // since this is in the loop function, continue song process
    // songLoop() does not yield like delay()
    if (isPlaying) {
        songLoop();
    }
}

Credits

Michael Marsico
2 projects • 0 followers
life is roblox
Contact
Thanks to Michael McCaffery.

Comments

Please log in or sign up to comment.