/*
Project: Slumber
Discription: This device will create a soothing environment to help those that suffer from insomnia and night anxiety, to fall asleep.
Author: Ammani
Date: 5/12/2017
Version: 2.0
*/
//------DEFINITIONS------
#include "neopixel.h"
#define PIXEL_PIN D0
#define PIXEL_COUNT 30
#define PIXEL_TYPE SK6812RGBW
// Currently, I think this is what is sent to the serial as output verification data. Haven't deleted it because I'm sure
// To understand more about this, look at DFplayer_basic_sample.ino in the audio folder
Adafruit_NeoPixel ring = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
// These are used by the DF Player
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
// These definitions are the various states the device will run through
# define STATE_OFF 0
# define STATE_WELCOME 1 // When you switch on device
# define STATE_LISTENING 2 // When the device is monitering your movement and hand gesture
# define STATE_PRIMARY 3 // The state in which the device is actuating the various outputs for the first time or when it's consciously activated by the user
# define STATE_SECONDARY 4 // When the device detects you might be waking up and responds minimally to put you back to sleep
//------- VARIABLES, INPUTS & OUTPUTS -------
int onSwitch = A0; // Input for the button
int aromapin = D1; // Output to diffuser
int Command; // Input for the DF Player
int Parameter1; // Input for the DF Player
int Parameter2; // Input for the DF Player
int state = 0; //
int pirState = D5;
int pirSense = 0;
int head = 0;
int tail = -10; // Index of first 'on' and 'off' pixels
void setup()
{
Serial.begin(9600);
Serial1.begin(9600); // Input for the DF Player
pinMode(aromapin, OUTPUT);
pinMode(onSwitch, INPUT);
Particle.subscribe( "ammani/movement" , callingMovement );
pinMode(pirState, INPUT);
ring.begin();
ring.show();
Particle.variable("pir", &pirSense, INT);
delay(30);
execute_CMD(0x3F, 0, 0); //Initialises the MP3 player
execute_CMD(0x06, 0, 30); // Initialize sound to very low volume. Adapt according used speaker and wanted volume
execute_CMD(0x16, 0 , 1);
}
void loop()
{
// This command switches between all the states of the device
switch( state )
{ case STATE_OFF:
doOffState();
break;
case STATE_WELCOME:
Serial.println("Welcome State");
doWelcomeState();
break;
case STATE_LISTENING:
//Serial.println("Listening State");
doListeningState();
break;
case STATE_PRIMARY:
// Serial.println("Primary State");
doPrimaryState();
break;
case STATE_SECONDARY:
Serial.println("Secondary State");
doSecondaryState();
break;
}
}
// ------ VARIABLES USED FOR TIMING AND TO INITIATE STATES ------
long lastDebounceTime = 0;
long debounceDelay = 5000;
long lastMovementCalled = 0;
bool primaryStateOn = FALSE;
bool movement = FALSE;
long enteredWelcomeStateAt = -1;
bool secondaryStateOn = FALSE;
bool isPrimaryStatePlaying = false;
bool aromaOn = false;
long startedPlayingAt = -1;
int primaryStateDuration = 1000 * 30;
int aromaStartTime = -1;
int aromaTime = 1000 * 10;
bool isSecondaryStatePlaying = false;
long startedSecondaryPlayingAt = -1;
int secondaryStateDuration = 1000 * 30;
// ------ FUNCTIONS FOR ALL THE STATES ------
void doOffState(){
off();
execute_CMD(0x16, 0 ,1);
if (analogRead(onSwitch) < 100){
state = STATE_WELCOME;
}
}
void doWelcomeState()
{
if( enteredWelcomeStateAt == -1 ) enteredWelcomeStateAt = millis();
star();
if (analogRead(onSwitch) > 100){
off();
enteredWelcomeStateAt = -1;
lastDebounceTime = millis();
head = 0;
tail = -10;
state = STATE_OFF;
}
else if( enteredWelcomeStateAt + 8000 < millis() )
{
lastDebounceTime = millis();
enteredWelcomeStateAt = -1;
head = 0;
tail = -10;
changeColor(ring.Color(10,160,0,0));
Serial.println("listeningstate");
state = STATE_LISTENING;
}
}
void doListeningState()
{
pirSense = digitalRead(pirState);
if (analogRead(onSwitch) > 100){
off();
state = STATE_OFF;
}
else if (movement == TRUE )
{
movement == FALSE;
secondaryStateOn = TRUE;
state = STATE_SECONDARY;
}
else if ( lastDebounceTime + debounceDelay < millis())
{if (pirSense == 1)
{
lastDebounceTime = millis();
primaryStateOn = TRUE;
state = STATE_PRIMARY;
}
}
}
void doPrimaryState(){
pirSense = digitalRead(pirState);
Serial.println("primarystate");
Serial.println(millis()-aromaStartTime);
yellowcolor();
if (primaryStateOn == TRUE and isPrimaryStatePlaying == FALSE)
{
Serial.println("2nd loop");
startedPlayingAt = millis();
aromaStartTime = millis();
aromaOn = true;
execute_CMD(0x01,0,1); //Plays the next track in SD card once timer is started
digitalWrite(aromapin,HIGH);
isPrimaryStatePlaying = true;
Serial.println("aroma on");
}
if (aromaOn)
{
if (aromaStartTime + aromaTime < millis())
{
digitalWrite(aromapin, LOW);
aromaOn = false;
Serial.println("aroma off");
}
}
else
if ( aromaStartTime + 20000 < millis())
{
digitalWrite(aromapin,HIGH);
Serial.println("aroma on");
aromaStartTime = millis();
}
if( isPrimaryStatePlaying && startedPlayingAt + primaryStateDuration < millis() )
{
primaryStateOn = FALSE;
isPrimaryStatePlaying = FALSE;
changeColor(ring.Color(10,160,0,0));
Serial.println("3rdloop");
digitalWrite(aromapin, LOW);
Serial.println("aroma off");
Serial.println("listeningstate");
aromaStartTime = -1;
startedPlayingAt = -1;
state = STATE_LISTENING;
}
else
{
//return; //
}
if (analogRead(onSwitch) > 100){
off();
state = STATE_OFF;
}
else if (lastDebounceTime + debounceDelay < millis())
{
if (pirSense == 1)
{
Serial.println("The Pir break");
lastDebounceTime = millis();
execute_CMD(0x16,0,1);
primaryStateOn = FALSE;
isPrimaryStatePlaying = FALSE;
digitalWrite(aromapin, LOW);
Serial.println("aroma off");
changeColor(ring.Color(10,160,0,0));
state = STATE_LISTENING;
}
}
}
void doSecondaryState(){
pirSense = digitalRead(pirState);
Serial.println("secondary state");
Serial.println(millis()-aromaStartTime);
orangecolor();
if (secondaryStateOn == TRUE and isSecondaryStatePlaying == FALSE)
{
Serial.println("2nd loop");
startedSecondaryPlayingAt = millis();
aromaStartTime = millis();
aromaOn = true;
execute_CMD(0x01,0,1);
digitalWrite(aromapin,HIGH);
isSecondaryStatePlaying = true;
Serial.println("aroma on");
}
if (aromaOn)
{
if (aromaStartTime + aromaTime < millis())
{
digitalWrite(aromapin, LOW);
aromaOn = false;
Serial.println("aroma off");
}
}
else
if ( aromaStartTime + 20000 < millis())
{
digitalWrite(aromapin,HIGH);
Serial.println("aroma on");
aromaStartTime = millis();
}
if( isSecondaryStatePlaying && startedSecondaryPlayingAt + secondaryStateDuration < millis() )
{
secondaryStateOn = FALSE;
isSecondaryStatePlaying = FALSE;
changeColor(ring.Color(10,160,0,0));
Serial.println("3rdloop");
digitalWrite(aromapin, LOW);
Serial.println("aroma off");
Serial.println("listeningstate");
aromaStartTime = -1;
startedSecondaryPlayingAt = -1;
state = STATE_LISTENING;
}
else
{
//return; //
}
if (analogRead(onSwitch) > 100){
off();
state = STATE_OFF;
}
else if (lastDebounceTime + debounceDelay < millis())
{
if (pirSense == 1)
{
Serial.println("The Pir break");
lastDebounceTime = millis();
execute_CMD(0x16,0,1);
secondaryStateOn = FALSE;
isSecondaryStatePlaying = FALSE;
digitalWrite(aromapin, LOW);
Serial.println("aroma off");
changeColor(ring.Color(10,160,0,0));
state = STATE_LISTENING;
}
}
}
// ------ FUNCTION FOR THE DF PLAYER ------
void execute_CMD(byte CMD, byte Par1, byte Par2) // Excecute the command and parameters
{
// Calculate the checksum (2 bytes)
int16_t checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Build the command line
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, checksum >> 8, checksum & 0xFF, End_Byte};
//Send the command line to the module
for (byte k=0; k<10; k++)
{
Serial1.write( Command_line[k]);
}
}
// ------ FUNCTIONS FOR THE LED STRIP ------
uint32_t color = 0x00ff08; // 'On' color (starts red)
void star(){
ring.setPixelColor(head, color); // 'On' pixel at head
ring.setPixelColor(tail, 0); // 'Off' pixel at tail
ring.show(); // Refresh strip
delay(5); // Pause 20 milliseconds (~50 FPS)
if(++head >= ring.numPixels()) { // Increment head index. Off end of strip?
head = 0; // Yes, reset head index to start
/*if((color >>= 8) == 0) // Next color (R->G->B) ... past blue now?
color = 0xFF0000; // Yes, reset to red*/
}
if(++tail >= ring.numPixels()) tail = 0; // Increment, reset tail index
}
void yellowcolor(){
for(int i = 0; i <= 10; i += 5) {
changeColor(ring.Color(i,i*13,0,0));
delay(50);
}
delay(500);
for(int i = 10; i >= 0; i -= 5) {
changeColor(ring.Color(i,i*13,0,0));
delay(50);
}
}
void orangecolor(){
for(int i = 0; i <= 10; i += 5) {
changeColor(ring.Color(i,i*10,0,0));
delay(50);
}
delay(500);
for(int i = 10; i >= 0; i -= 5) {
changeColor(ring.Color(i,i*10,0,0));
delay(50);
}
}
void off() {
changeColor(ring.Color(0, 0, 0, 0));
}
void changeColor(uint32_t color) {
for(uint16_t i=0; i < ring.numPixels(); i++) {
ring.setPixelColor(i, color);
ring.show();
}
}
// ------ FUNCTION TO RESPOND TO THE PILLOW SENSOR ------
void callingMovement(const char *event, const char *data)
{
Serial.println("Reached Calling Movement Handler");
if (data == "yes"){
moving();
}
}
void moving()
{
if ( lastMovementCalled + 20000 < millis() )
{
lastMovementCalled = millis();
movement = TRUE;
}
}
Click to Expand
Content Rating
Is this a good/useful/informative piece of content to include in the project? Have your say!
You must login before you can post a comment. .