Back to Parent

Primary Circuit
//Created by Langley V, Swapnil A, and Ussama N on 11/17/2019
//Creative Project II

//Last edited: 11-26-2019

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

DFPlayer dfPlayer;


int folder = 0;
int volume = 0;
bool powerOn = false;

//********************************************************************
//Neopixel
//********************************************************************

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

//Set pixel pin, number of pins, and type
#define PIXEL_PIN D2
#define PIXEL_COUNT 7
#define PIXEL_TYPE WS2812

const uint8_t KEYFRAMES[]  = {
  // Rising
  20, 21, 22, 24, 26, 28, 31, 34, 38, 41, 45, 50, 55, 60, 66, 73, 80, 87, 95,
  103, 112, 121, 131, 141, 151, 161, 172, 182, 192, 202, 211, 220, 228, 236,
  242, 247, 251, 254, 255,

  // Falling
  254, 251, 247, 242, 236, 228, 220, 211, 202, 192, 182, 172, 161, 151, 141,
  131, 121, 112, 103, 95, 87, 80, 73, 66, 60, 55, 50, 45, 41, 38, 34, 31, 28,
  26, 24, 22, 21, 20,
  20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 
};

int keyframePointer = 0;
int numKeyframes = sizeof(KEYFRAMES) - 1;

//define neopixel strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

//Global variable delcaration
//int timeDuration;

//Declare booleans that go along with the message received from the sender
bool displayNotif = false; //calendar event boolean
bool isRunning = false;
long timeStartedAt = -1; 
int timeElapsed = -1;


//Define colorOff: 0,0,0
uint32_t colorOff = strip.Color( 0, 0, 0 );

//********************************************************************
//Publishing Events
//********************************************************************
// This value will store the last time we published an event
long lastPublishedAt = 0;

int last_published = -1;


//********************************************************************
//Flex Sensor
//********************************************************************
int flexPin = A0;
int flexReading = 0;

//********************************************************************
//LED indicator
//********************************************************************
//int ledPin = A1;

int RedPin = D5; //To identify the state of the RED Button
int GreenPin = D3; //To identify the state of the GREEN Button
int YellowPin = D4; //To identify the state of the YELLOW Button
int BluePin = D6; //To identify the state of the BLUE Button

int RedButton = A1; //For recording the Message
int GreenButton = A2; //For sending the Message
int YellowButton = A3; //For saving the Message
int BlueButton = A4; //For listening to the Message

int publishAfter = 10000;

//High  = 1;
int RedButtonState = 0;
int GreenButtonState = 0;
int YellowButtonState = 0;
int BlueButtonState = 0;

bool messageExists = false;
int PreviousRBS = 0;
bool messageHeared = false;

int here = 0;


void setup() {
    
    //another event starts, stop current event and then reset timer, then start over.
    Particle.function("startNotif", startNotif);
    Particle.function("endNotif", endNotif);

    //Code initialization
    strip.begin();
    strip.show();
    //strip.setBrightness(30); //dim lights
    
    //get time particle io started at
    timeStartedAt = millis(); 

    //initial color, Yellow glow
    uint32_t c = strip.Color(0, 255, 255);

    //reset all the colors
    for (int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, c);
        delay(100);
    }
    strip.show();
    
    for (int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, colorOff);
        delay(100);
    }
    strip.show();
    
//********************************************************************
    
    //Declare pin modes for flex, speaker and LED
    pinMode(flexPin, INPUT);

    pinMode( RedButton , INPUT_PULLUP ); // sets pin as input
    pinMode( GreenButton , INPUT_PULLUP); // sets pin as input
    pinMode( YellowButton , INPUT_PULLUP); // sets pin as input
    pinMode( BlueButton , INPUT_PULLUP); // sets pin as input
    
    pinMode( RedPin , OUTPUT ); // sets pin as output
    pinMode( GreenPin , OUTPUT ); // sets pin as output
    pinMode( YellowPin , OUTPUT ); // sets pin as output
    pinMode( BluePin , OUTPUT ); // sets pin as output
    
    dfPlayer.setLogging(true);
    volume = dfPlayer.getVolume();
    
    delay(5000);

    Particle.variable("force", flexReading);
    Particle.subscribe("swapnil/2019/enchantedBook/" , handleSharedEvent);
    Particle.subscribe("langley/2019/iot/enchantedBookMessage/" , handleSharedEventSpeaker);

    Particle.variable("RedState", RedButtonState);
    Particle.variable("PreviousRBS", PreviousRBS);
    Particle.variable("GreenState", GreenButtonState);
    Particle.variable("BlueButtonState", BlueButtonState);
    Particle.variable("Here", here);
    
    
    Particle.variable("force", flexReading);
    Particle.variable("folder", folder);
    Particle.variable("volume", volume);
    Particle.variable("power", powerOn);
    Particle.function("setVolume", setVolume);
    Particle.function("playFolder", playFolder);
    Particle.function("setPower", setPower);
  
    setVolume("20");
    setPower("true");
    folder = 1;
    delay(200);
    
    //dfPlayer.playTrack(1);
    PlayMessage();
    delay(1000);
    //playFolder(String(folder));

}

void loop() {
    
    //Get flex sensor reading 
    flexReading = analogRead(flexPin);
    //delay(100);

    RedButtonState = digitalRead( RedButton );
    GreenButtonState = digitalRead( GreenButton );
    YellowButtonState = digitalRead( YellowButton );
    BlueButtonState = digitalRead( BlueButton );

    //Recording the Message
    
    if( PreviousRBS == HIGH && RedButtonState == LOW)
    {
        //Start recording 
        digitalWrite( RedPin, HIGH); // turn the LED On
        PreviousRBS = RedButtonState;
        messageExists = true;
    }
    else if(PreviousRBS == LOW && RedButtonState == HIGH)
    {
        //Stop recording 
        digitalWrite( RedPin, LOW); // turn the LED Off
    }
    PreviousRBS = RedButtonState;
    
    //Sending the Message
    if( GreenButtonState == LOW && messageExists == true )
    {
        digitalWrite(GreenPin, HIGH);
        delay(100);
        digitalWrite(GreenPin, LOW);
        
        SendMessage();
        delay(2000);
        // delay for a bit
        messageExists = false;

    }
    else
    {
        digitalWrite( GreenPin, LOW);
    }
    

    
    //If there is a message waiting, go into this loop
    if(displayNotif) {
        
        //CASE 1: GLOW
        //If there is a message and the flex sensor is bent (book is closed)
        if(flexReading > 700) {
        
            for (int i = 0; i < strip.numPixels(); i++) {
                uint8_t color = (127 * KEYFRAMES[keyframePointer]) / 256;
                strip.setPixelColor(i, 0, 0, color);
            }
            strip.show();   
            
            // Increment the keyframe pointer.
            if (++keyframePointer > numKeyframes) {
              // Reset to 0 after the last keyframe.
              keyframePointer = 0;
            }   
   
        }
        
        //CASE 2: PLAY MESSAGE 
        //There is a notification and the book is opened
        else if(flexReading < 700) {
            
            //LED glows because there is a message
            digitalWrite( BluePin, HIGH);

            //delay(1000);
            
            // delay(100);
            
            // PlayMessage();
            
            // delay(4000);
            
            // digitalWrite( BluePin, LOW);

            //Play message
            if(BlueButtonState == LOW )
            {
                Particle.publish("bluebutton", "low-prev-high");
                here = 1;
                PlayMessage();
                
                delay(100);
                
                displayNotif = false;
                
                messageHeared = true;
                
                digitalWrite( BluePin, LOW);


            }


 
            //Set notification back to false, message has been heard
            //displayNotif = false;
            isRunning = false;

            for (int i = 0; i < strip.numPixels(); i++) {
                strip.setPixelColor(i, 0, 0, 0);
            }
            strip.show();   

            
            //digitalWrite( BluePin, LOW);

        }
        
        else {
            //do nothing
            //return;
        }
    }
    
    // NO message, do nothing
    else {
        //do nothing
    }
    
       //Save the Message
    if(YellowButtonState == LOW && messageHeared == true)
    {
        // store the time when you last published
        int last_published = -1;
        
        digitalWrite(YellowPin, HIGH);
        delay(500);
        
        SaveMessage();
        
        messageHeared = false;
       
    }
    else
    {
        digitalWrite( YellowPin, LOW);
    }
    
    delay(500);
}

//Particle Functions that change boolean value to true or false
//For now, have console "send the message" to this particle board that there is a message
//Next steps: Use another particle board to publish an event and use this particle board to receive it
bool startNotif(String val) {
    
    //if it is not running then start it
    if (!isRunning) {
        //timeStartedAt = millis(); //reset time 
        displayNotif = true;
        isRunning = true;

        //goes into loop and runs light code
    }
    //A calendar event ambient notification is already running
    else {
        //Stop what is happening 
        //turn all off 
        for (int i = 0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, colorOff);
            delay(50);
        }
        strip.show();
    }
    
}

//End the message notification
bool endNotif(String val) {

    //turn all off 
    for (int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, colorOff);
        delay(50);
    }
    strip.show();
        
    //no ambient notification
    displayNotif = false;
    //code is not running
    isRunning = false;
    
}

void SendMessage()
{
  // Remember that a device can publish at rate of about 1 event/sec,
  // with bursts of up to 4 allowed in 1 second.
  // Back to back burst of 4 messages will take 4 seconds to recover.
  // So we want to limit the amount of publish events that happen.

  // check that it's been 10 secondds since our last publish
  if( lastPublishedAt + publishAfter < millis() )
  {
      // Remember our subscribe is matching  "db2018/paired/"
      // We'll append the device id to get more specific
      // about where the event came from

      // System.deviceID() provides an easy way to extract the device
      // ID of your device. It returns a String object of the device ID,
      // which is used to identify your device.

      String eventName = "langley/2019/iot/sendenchantedBookMessage/" + System.deviceID();

      // now we have something like "diot/2019/paired/0123456789abcdef"
      // and that corresponds to this devices info

      // then we share it out
      Particle.publish( eventName, "Message_Sent" );

      // And this will get shared out to all devices using this code

      // we just pubished so capture this.
      lastPublishedAt = millis();
  }

}

//Notify other person 
void ReceivedMessage()
{
  // Remember that a device can publish at rate of about 1 event/sec,
  // with bursts of up to 4 allowed in 1 second.
  // Back to back burst of 4 messages will take 4 seconds to recover.
  // So we want to limit the amount of publish events that happen.

  // check that it's been 10 secondds since our last publish
  if( lastPublishedAt + publishAfter < millis() )
  {
      // Remember our subscribe is matching  "db2018/paired/"
      // We'll append the device id to get more specific
      // about where the event came from

      // System.deviceID() provides an easy way to extract the device
      // ID of your device. It returns a String object of the device ID,
      // which is used to identify your device.

      String eventName = "langley/2019/iot/receivedenchantedBookMessage/" + System.deviceID();

      // now we have something like "diot/2019/paired/0123456789abcdef"
      // and that corresponds to this devices info

      // then we share it out
      Particle.publish( eventName, "Message_Sent" );

      // And this will get shared out to all devices using this code

      // we just pubished so capture this.
      lastPublishedAt = millis();
  }

}


//Write data to spreadsheet
void SaveMessage() {

  // check if 1 minute has elapsed
	if( last_published + 10000 < millis() ){
		Particle.publish( "messageLogged", String("Hi-I-love-youuuu") );
		last_published = millis();
	}
}

//
int playFolder(String buffer) {
    folder = atoi(buffer);
    
    // the following commands play 6 tracks that were stored in the root folder of the TFCard
    // the dfPlayer.playTrack method uses DFPlayer command 0x03
    // The tracks were named 001 - 006.
    // The tracks were added to the TFCard in the following sequence 001, 002, 003, 005, 004, and 006
    // This code plays the tracks in order 001 - 006
    delay(3000);
    dfPlayer.playTrack(1);
    delay(3000);
    dfPlayer.playTrack(2);
    delay(7000);

    return 0;
}

void PlayMessage()
{
  // Remember that a device can publish at rate of about 1 event/sec,
  // with bursts of up to 4 allowed in 1 second.
  // Back to back burst of 4 messages will take 4 seconds to recover.
  // So we want to limit the amount of publish events that happen.

  // check that it's been 10 second  since our last publish
  if( lastPublishedAt + publishAfter < millis() )
  {
      // Remember our subscribe is matching  "db2018/paired/"
      // We'll append the device id to get more specific
      // about where the event came from

      // System.deviceID() provides an easy way to extract the device
      // ID of your device. It returns a String object of the device ID,
      // which is used to identify your device.

      String eventName = "langley/2019/iot/playMessage/" + System.deviceID();

      // now we have something like "diot/2019/paired/0123456789abcdef"
      // and that corresponds to this devices info

      // then we share it out
      Particle.publish( eventName, "Message_Sent" );

      // And this will get shared out to all devices using this code

      // we just pubished so capture this.
      lastPublishedAt = millis();
  }

}


void handleSharedEvent(const char *event, const char *data)
{
    // Now we're getting ALL events published using "db2018/paired/"
    // This includes events from this device.
    // So we need to ignore any events that we sent.

    // Let's check the event name
    String eventName = String( event ); // convert to a string object
    // This gives us access to a bunch of built in methods
    // Like indexOf()
    // Locates a character or String within another String.
    // By default, searches from the beginning of the String,
    // but can also start from a given index,
    // allowing for the locating of all instances of the character or String.
    // It Returns: The index of val within the String, or -1 if not found.

    // We can use this to check if our event name contains the
    // id of this device

    String deviceID = System.deviceID();

    // device id = 0123456789abcdef
    // event = "diot/2019/paired/0123456789abcdef"

    if( eventName.indexOf( deviceID ) != -1 ){
      // if we get anything other than -1
      // the event came from this device.
      // so stop doing stuff
      return;
    }

    displayNotif = true;
    delay(1000);
    
    ReceivedMessage();
}


void handleSharedEventSpeaker(const char *event, const char *data)
{
    // Now we're getting ALL events published using "db2018/paired/"
    // This includes events from this device.
    // So we need to ignore any events that we sent.

    // Let's check the event name
    String eventName = String( event ); // convert to a string object
    // This gives us access to a bunch of built in methods
    // Like indexOf()
    // Locates a character or String within another String.
    // By default, searches from the beginning of the String,
    // but can also start from a given index,
    // allowing for the locating of all instances of the character or String.
    // It Returns: The index of val within the String, or -1 if not found.

    // We can use this to check if our event name contains the
    // id of this device

    String deviceID = System.deviceID();

    // device id = 0123456789abcdef
    // event = "diot/2019/paired/0123456789abcdef"

    if( eventName.indexOf( deviceID ) != -1 ){
      // if we get anything other than -1
      // the event came from this device.
      // so stop doing stuff
      return;
    }

    digitalWrite(GreenPin, HIGH);
    delay(200);
    digitalWrite(GreenPin, LOW);
    delay(200);
    
}


// setVolume is a Particle method that can be used to adjust volume via the Particle Console
int setVolume(String buffer) {
    volume = atoi(buffer);
    dfPlayer.setVolume(volume);
    return 0;
}

// setPower is a Particle method that that plays a gong when power is toggled false, and chirping birds when power is toggned true 
bool setPower(String buffer) {
    if ((buffer[0] == 'f') && (powerOn == true))  {
        powerOn = false;
        dfPlayer.playFolderTrack(1,2);
    }
    if ((buffer[0] == 't') && (powerOn == false)) {
        powerOn = true;
        dfPlayer.playFolderTrack(1,1);
    }
    return powerOn;
}
Click to Expand

Content Rating

Is this a good/useful/informative piece of content to include in the project? Have your say!

0