Clayton Parrish
Published

Photon Time Tracker

This portable device is a dedicated time tracking device to help manage your time. Multiple photons are used to set up automatic triggers.

IntermediateWork in progress703
Photon Time Tracker

Things used in this project

Hardware components

Photon
Particle Photon
×1
Tactile Switch, Top Actuated
Tactile Switch, Top Actuated
×4
SunFounder LCD 20x4 character display
×1
SparkFun Photon Battery Shield
×1
Adafruit Lithium Ion Polymer Battery - 3.7V 2500mAh
×1

Story

Read more

Schematics

Circuit Diagram

Circuit diagram of main time tracker. LiPo battery shield not included as it is attached to all pins. Additionally, keep in mind the pins D3, D4, D5, and D6 have internal pull-down resistors.

Code

Time Tracker Code

C/C++
Code of main console.
/*Time tracker code 
Clayton Parrish
For UNCC MEGR 3171 IOT Project
Create - 4/10/2019
Edited - 4/16/2019
Finished  1.0.0 - 4/17/2019 (early morning)
Edited - 4/18/2019 
*/

//LIBRARIES __ START

#include <Encoder.h>                //For Rotary Encoder (No longer included)
#include <LiquidCrystal_I2C2.h>     //For LCD Display
#include <Wire.h>                   //I don't know what this is for, but I dare not delete it :-)

//LIBRARIES __ END

/*******************************/

//DEFINE VARIABLES __ START

LiquidCrystal_I2C2 lcd(0x27,20,4);  //Defines LCD at bus adress of 0x27. 20 char per line, 4 lines.

//Holding variable for rotary encoder
int cursor_abs;                     //Current encoder position              
int aLastState = digitalRead(D5);   //Previous encoder position
int lag = 10;                        //Delay time to check difference in positions
bool rotating = false;              //Flag that is turned true upon rotary encoder movement

//Define ports
int GB = D5;        // Green button
int RB = D3;        // Red button
int LCD_PWR = D7;   // Power to LCD character display
int ROT_1 = A2;     // Analog input 1 for rotary encoder
int ROT_2 = A3;     // Analog input 2 for rotary encoder
int UB = D4;        // Up button
int DB = D6;        // Down button

//Define state of the program
int status = 0;                  //State determines the "loop" that will occur
                                //0 = main screen, 1 = change status, 2 = current status, 3 = shut down 

//Define different time categories that can be sent to google 
int cate_max = 11;
String Cate[] = {"Homework", "Projects", "Career", "Free Time", "Social", "Sleep", "Transit", "Meals", "Meetings", "Family", "Chores"};

//Menu navigation variables
int cursor = 0;
int cursor_b = 0;
int last_cursor;
int M_select;
String CURRENT_STATUS; 



//DEFINE VARIABLES __ END

/*********************************************************/

void setup()
{
    //Open up serial monitoring for debugging
    Serial.begin(9600);
    
    //Set up pins    
    pinMode(LCD_PWR, OUTPUT);
    pinMode(ROT_1, INPUT);
    pinMode(ROT_2, INPUT);
    pinMode(GB, INPUT_PULLDOWN);
    pinMode(RB, INPUT_PULLDOWN);
    pinMode(UB, INPUT_PULLDOWN);
    pinMode(DB, INPUT_PULLDOWN);
    
    //LCD Screen set up
    digitalWrite(LCD_PWR, HIGH);    //Turn on LCD screen
    lcd.init();                     //initialize the lcd
    lcd.backlight();                //open the backlight 
    
    //Encoder 
    attachInterrupt(A2, doEncoder, CHANGE); //Sets doEncoder to trigger upon rotary encoder movement

    //Two way communciation with other photon
    Particle.subscribe("Sleepy", myHandler, ALL_DEVICES);
    
    //Inital Screen
    lcd.setCursor(0,0);
    lcd.print("Time Tracker   ");
    lcd.setCursor(0,1);
    lcd.print("Clayton Parrish");
    lcd.setCursor(0,2);
    lcd.print("Version 1.0.0");
    lcd.setCursor(0,3);
    lcd.print("  ");
    delay(1000);
    
    
    MainScreen();
}
/*********************************************************/
void loop() {
    //If the rotary encoder is rotating, change the position
    while(rotating) {
        updateEncoder();
    }

    // MAIN SCREEN _ START
    
    if(status == 0) {
        if(digitalRead(UB) == HIGH) { 
            cursor += 1;
            if(cursor > 2) {
                cursor = 0;
            }
            delay(250);
        }
        if(digitalRead(DB) == HIGH) {
            cursor -= 1; 
            if(cursor < 0) {
                cursor = 2;
            }
            delay(250);
        }
        
        if(cursor != cursor_b) {
            M_Change(cursor);
        }
        cursor_b = cursor;
        
        if(digitalRead(GB) == HIGH) {
            switch(cursor) {
                case 0:
                    ChangeStatusMenu();
                break;
                case 1:
                    CheckStatusMenu();
                break;
                case 2:
                    ShutDown();
                break;
            }
        }
        if(digitalRead(RB) == HIGH) {
            ShutDown();
            delay(250);
        }
    
    }
    
    // MAIN SCREEN __ END
    
    /***********************/
    
    // CHANGE STATUS __ START
    
    if(status == 1){
        if(digitalRead(UB) == HIGH) {
            cursor += 1;
            if(cursor > (cate_max - 1)) {cursor = 0;}
            C_Change();
            delay(250);
        }
        if(digitalRead(DB) == HIGH) {
            cursor -= 1;
            if(cursor < 0) {cursor = (cate_max - 1);}
            C_Change();
            delay(250);
        }
        
        if(digitalRead(GB) == HIGH) {
            CURRENT_STATUS = Cate[cursor];
            String sc   = String("Status_Change_");
            String mnth = String(Time.month());
            Particle.publish(sc + mnth, Cate[cursor]);
            delay(250);
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("  Updated :)  ");
            delay(1000);
            MainScreen();
        }
        if(digitalRead(RB) == HIGH) {
            MainScreen();
            delay(250);
        }
    }
    
    // CHANGE STATUS __ END
    
    /***********************/
    
    // CHECK STATUS __ START
    
    if(status == 2){
        if(digitalRead(RB) == HIGH) {
            MainScreen();
            delay(250);
        }
    }

    // CHECK STATUS __ END
    
    /***********************/
    
    // SHUT DOWN __ START

	if(status == 3) {
	   if(digitalRead(GB) == HIGH) {
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Goodnight :-)");
            delay(1500);
            System.sleep(SLEEP_MODE_DEEP);
        } 
        if(digitalRead(RB) == HIGH) {
            MainScreen();
            delay(500);
        }
	}
    
    // SHUT DOWN __ END
    
    
}
/************************************************************/

void doEncoder(){
    rotating = true;
}

void updateEncoder(){
    delay(lag);
    if (digitalRead(ROT_1) == digitalRead(ROT_2)) {  
        cursor_abs--;
    } 
    else {                                   
        cursor_abs++;
    }
    rotating=false;     //Set the rotating to false, will become true again if still rotating
    
}

void MainScreen() {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  **Time Tracker**  ");
    lcd.setCursor(0,1);
    lcd.print(">Change Status");
    lcd.setCursor(0,2);
    lcd.print("Check Status");
    lcd.setCursor(0,3);
    lcd.print("Shut Down");
    cursor = 0;
    status = 0;
}

void ShutDown() {
    lcd.clear(); 
    lcd.setCursor(0,0);
    lcd.print("     Shut down?     ");
    lcd.setCursor(0,2);
    lcd.print("    Green -> Yes    ");
    lcd.setCursor(0,3);
    lcd.print("    Red -> Back     ");
    //cursor
    delay(500);
    status = 3;
}

void M_Change(int i) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  **Time Tracker**  ");
    switch(i) {
        case 0:
            lcd.setCursor(0,1);
            lcd.print(">Change Status");
            lcd.setCursor(0,2);
            lcd.print("Check Status");
            lcd.setCursor(0,3);
            lcd.print("Shut Down");
            break;
        case 1:
            lcd.setCursor(0,1);
            lcd.print("Change Status");
            lcd.setCursor(0,2);
            lcd.print(">Check Status");
            lcd.setCursor(0,3);
            lcd.print("Shut Down");
            break;
        case 2:
            lcd.setCursor(0,1);
            lcd.print("Change Status");
            lcd.setCursor(0,2);
            lcd.print("Check Status");
            lcd.setCursor(0,3);
            lcd.print(">Shut Down");
            break;
            }
}

void ChangeStatusMenu() {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("***Change Status***");
    lcd.setCursor(0,1);
    lcd.print(Cate[cate_max - 1]);
    lcd.setCursor(0,2);
    lcd.print(">" + Cate[0]);
    lcd.setCursor(0,3);
    lcd.print(Cate[1]);
    delay(250);
    cursor = 0;
    status = 1; 
}

void C_Change() {
    int i_min = cursor - 1;
    int i_plu = cursor + 1;
    if(cursor == 0) { i_min = (cate_max - 1); }
    if(cursor == (cate_max - 1)) { i_plu = 0; }
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("***Change Status***");
    lcd.setCursor(0,1);
    lcd.print(Cate[i_min]);
    lcd.setCursor(0,2);
    lcd.print(">" + Cate[cursor]);
    lcd.setCursor(0,3);
    lcd.print(Cate[i_plu]); 
}

void CheckStatusMenu() {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("***Current Status***");
    lcd.setCursor(0,1);
    lcd.print("You are currently:");
    lcd.setCursor(0,2);
    lcd.print(CURRENT_STATUS);
    status = 2;
}

void myHandler(const char *event, const char *data)
{
    CURRENT_STATUS = "Sleep";
    String sc   = String("Status_Change_");
    String mnth = String(Time.month());
    Particle.publish(sc + mnth, "Sleep");
}

Light Trigger

C/C++
Example of trigger. Will use as foundation for later triggers.
bool dark = false;
bool light = true;
unsigned long current_time;       // ms of no light to send sleep message 
unsigned long holding_time; 

void setup() {
    pinMode(A2, INPUT);
    pinMode(D7, OUTPUT);
    Particle.subscribe("Status_Change", myHandler, ALL_DEVICES);
    Serial.begin(9600);
    //digitalWrite(D7, HIGH);
}

void loop() {
    analogRead(A2);
    Serial.write(analogRead(A2));
    if(analogRead(A2) < 1000) {  //Sleeping
            if(light)    {
                if(dark == false) {
                holding_time = millis();
                dark = true;
            }
                else {
                    current_time = millis();
                        if(current_time - holding_time > 20000) {
                            Particle.publish("Sleepy");
                            digitalWrite(D7, HIGH);
                            delay(750);
                            light = false;
                
            }
        }
        }   
    }
    else{                       //Light is on
       dark = false;
       light = true;
    }
    digitalWrite(D7, LOW);
}

void myHandler(const char *event, const char *data)
{
    digitalWrite(D7, HIGH);
    delay(750);
    digitalWrite(D7, LOW);
    delay(750);
    digitalWrite(D7, HIGH);
    delay(750);
    digitalWrite(D7, LOW);
    delay(750);
    digitalWrite(D7, HIGH);
    delay(750);
    digitalWrite(D7, LOW);
    delay(750);
}

Credits

Clayton Parrish

Clayton Parrish

1 project • 0 followers

Comments