Code for the following project: https://www.instructables.com/id/Ultimate-Hamster-Tracker-Wheel-Featuring-Mbed-C-LC/

Dependencies:   4DGL-uLCD-SE PinDetect mbed

main.cpp

Committer:
bstrickland9
Date:
2017-04-03
Revision:
0:d0e2fe309777

File content as of revision 0:d0e2fe309777:

#include "mbed.h"
#include "PinDetect.h"
#include "uLCD_4DGL.h"
#include "Shiftbrite.h"

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);

// use class to setup pushbuttons pins
PinDetect pb1(p23);
PinDetect pb2(p24);

// use class to setup the  Color LCD
uLCD_4DGL uLCD(p28, p27, p29); // create a global uLCD object

// Global variables used in callbacks and main program
// C variables in interrupt routines should use volatile keyword
int volatile magnetHit=0;

//timer setup
Timer t;

// Callback routine is interrupt activated by a debounced magnet hit
void pb1_hit_callback (void)
{
        magnetHit=1;
}

// Callback routine is interrupt activated by a debounced magnet unhit
void pb2_hit_callback (void)
{
        magnetHit=1;
}

// use class to setup Shiftbrite pins
Shiftbrite myShiftbrite(p9, p10, p11, p12, p13);// ei li di n/c ci

// init
float circumference=0, speed=0, tempFloat=0, changePercent=0, averageBlock=0; //average is float
int a1=10000, a2=10000, a3=10000, a4=10000, a5=10000, cumulativeDistBlock=0, recentBlock=0; //avg values assume ~7.5km
int highestBlock=0, lowestBlock=99999999, dayCount=0;
unsigned int myColor = 0x000000;
unsigned int shiftR=0, shiftG=0, shiftB=0;
bool execSpaces=0;

int main() {
    //start timer
    t.start();
    myled1 = 1;
    
    shiftR = 50;
    myShiftbrite.write( shiftR, shiftG, shiftB);
    
    uLCD.color(0xff3333);
    uLCD.locate(0,0);
    uLCD.printf(" ...Starting...");
    
    // Use internal pullups/downs for the pushbutton
    pb1.mode(PullDown); //PullUp gnd and input. PullDown vcc and input.
    pb2.mode(PullUp);
    // Delay for initial pullup to take effect
    wait(.1);
    // Setup Interrupt callback functions for a pb hit
    //pb1.attach_deasserted(&pb1_unhit_callback);
    pb1.attach_asserted(&pb1_hit_callback);
    pb2.attach_deasserted(&pb2_hit_callback);
    // Start sampling pb inputs using interrupts. leave as () default 20ms aka 20000.
    pb1.setSampleFrequency(10000); //using 10ms aka 10000
    pb2.setSampleFrequency(10000);
    //setSamplesTillAssert, default is 50 continuous samples
    pb1.setSamplesTillAssert(6);
    pb2.setSamplesTillAssert(6);
    
    // Set RTC time to Wed, 28 Oct 2009 11:35:37 (January 1, 1970)
    set_time(1);
    //time_t mktime (tm * timeptr) //needed?
    
    //setup circumference
    circumference = 3.14159*0.24; //pi * diam (m) //tweakMe was 0.254
    
    wait(0.4);
    uLCD.locate(0,0);
    uLCD.color(0x4444ff);
    uLCD.printf(" Ultimate Hamster");
    
    //labels print in this color
    uLCD.color(0x8888ff);
    
    // set up permanent characters on display
        uLCD.locate(0,2);
        uLCD.printf("Speed:       (m/s)");
        
        uLCD.locate(0,4);
        uLCD.printf("Change:        (%%)");
        
        //optimize other labels too one day...
        uLCD.locate(0,6);
        uLCD.printf("Recent:        (m)");
        uLCD.locate(0,8);
        uLCD.printf("Average:       (m)");
        uLCD.locate(0,10);
        uLCD.printf("Highest:       (m)");
        uLCD.locate(0,12);
        uLCD.printf("Lowest:        (m)");
        
        uLCD.locate(0,15);
        uLCD.printf("0 /24hr    day 0  ");
        
        //old debug display...
        //uLCD.locate(0,14);
        //uLCD.printf("Time:");
        //uLCD.locate(0,15);
        //uLCD.printf("Hour:");
        
    // end
    
    //numbers print in this color
    uLCD.color(0xcccc33);
    //if you want to change this, also change value near changePercent print!
    
    shiftR=0;
    shiftG=0;
    shiftB=50;
    myShiftbrite.write( shiftR, shiftG, shiftB);
    
    
    while(1) {
        
        myled1 = !myled1; // show loop is active
        //shiftR = (rand()*40) % 40;
        //shiftG = (rand()*40) % 40;
        //shiftB = (rand()*40) % 40;
        shiftR = 0;
        shiftG = 0;
        shiftB = 0;
        myShiftbrite.write( shiftR, shiftG, shiftB);
                
        switch (magnetHit) {
            case 0:
                myled2 = 1; 
                myled3 = 0;
                break;
            case 1:
                
                myled2 = 0; 
                myled3 = 1; 
                
                //change title color
                //myColor = (rand()*0xffffff) % 0xffffff;
                
                //change shiftbrite color
                myShiftbrite.write( 20, 20, 20);
                
                //speed calc
                //using timer t.
                tempFloat = t.read();
                t.reset();
                
                //send speed to display
                speed = circumference / tempFloat;
                uLCD.locate(7,2);
                uLCD.printf("%5.2F", speed); //speed: number
                
                //4mph or 1.8m/s is a timer value of 0.44s per revolution
                if (tempFloat > 0.3) { //instead use 0.3
                    cumulativeDistBlock = cumulativeDistBlock + 1;
                } else {
                    //shiftbrite
                }
                
                magnetHit=0; //force to zero
                
                myShiftbrite.write( shiftR, shiftG, shiftB);
                
                break;
        }
        
        //for debug only
        //uLCD.locate(0,10);
        //uLCD.printf("t.read: %5.2F", t.read());
        
        //check if wheel is still for more than 5 seconds
        //t.stop(); //line not needed if t.read() can occur without pause
        if (t.read() > 3 && t.read() < 4) { //1 second window (24hr takes ~0.7s)
            uLCD.locate(8,2);
            uLCD.printf("zero"); //speed: zero
        }
        //t.start(); //line not needed if t.read() can occur without pause
        
        if (t.read() > 300) { //every 5 mins, reset speed timer
            //prevent overflow, max value is 1800, 30 mins
            t.reset();
        }
        
        //get the current time
        time_t seconds = time(NULL);
        
        uLCD.locate(0,15);
        uLCD.printf("%u", seconds/60/60 ); //change seconds to seconds/60/60
        
        //time display for debug
        //uLCD.locate(6,14);
        //uLCD.printf("%u ", seconds );
        //uLCD.locate(6,15);
        //uLCD.printf("%u ", seconds/60/60 );
        
        //this runs every 24hr block
        if (seconds >= 86400) { //86400 is 24hrs
            myShiftbrite.write( 50, 0, 0);
            
            //compute 24hr block values
            recentBlock = cumulativeDistBlock;
            cumulativeDistBlock = 0; //reset
            dayCount++; //add one to day
            
            //change tracking
            changePercent = 100*(recentBlock-averageBlock) / (averageBlock); //signed float
            
            //shift numbers in array to delete oldest value
            a1 = a2; //oldest 
            a2 = a3;
            a3 = a4;
            a4 = a5;
            a5 = recentBlock; //newest
            averageBlock = (a1 + a2 + a3 + a4 + a5)/5; //int becomes float
            
            //check if recentBlock is new high or new low
            if (recentBlock > highestBlock) { //new high
                highestBlock = recentBlock;
                //Highest (m) store max value 
                tempFloat = highestBlock*circumference;
                uLCD.locate(8,10);
                uLCD.printf("%7.0F", tempFloat);
                uLCD.locate(5,14);
                uLCD.printf("NEW HIGH");
                execSpaces = 1; //if no update on next round, set spaces
            } else if (recentBlock < lowestBlock) { //new low
                lowestBlock = recentBlock;
                //Lowest (m) store min value
                tempFloat = lowestBlock*circumference;
                uLCD.locate(8,12);
                uLCD.printf("%7.0F", tempFloat);
                uLCD.locate(5,14);
                uLCD.printf("NEW LOW ");
                execSpaces = 1;
            } else if (execSpaces == 1) {
                uLCD.locate(5,14);
                uLCD.printf("        ");
                execSpaces = 0;
            } //state machine so that spaces will not overwrite spaces every time
            
            //use tempFloat to convert int rotations to distance (m)
            //use circumference float
            //update the following on display
            
            //Change (%) past 24hr block vs average
            if (changePercent > 0) {
                //green
                uLCD.color(0x33ff33);
            } else if (changePercent < 0) {
                //red
                uLCD.color(0xff3333);
            } else {
                //purple, white??
                uLCD.color(0xff33ff);
            }
            //tempFloat = changePercent;
            uLCD.locate(8,4);
            uLCD.printf("%7.0F", changePercent); //NAN and INF possible!
            uLCD.color(0xcccc33); //reset color value!!!!! copy value from way above.
            
            //Recent (m) past 24hr block
            tempFloat = recentBlock*circumference;
            uLCD.locate(8,6);
            uLCD.printf("%7.0F", tempFloat);
            //Average (m) average of the past 5 24hr
            tempFloat = averageBlock*circumference;
            uLCD.locate(8,8);
            uLCD.printf("%7.0F", tempFloat);
            //print for low and high happens only when value updated
            
            //bottom line updates
            uLCD.locate(0,15);
            uLCD.printf("0 "); // remove leftover characters from XX/24hr
            uLCD.locate(15,15); //modify this
            uLCD.printf("%u", dayCount);
            
            set_time(1); //reset
            
            myShiftbrite.write( shiftR, shiftG, shiftB);
        }
        
    } //while end
}