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

Dependencies:   4DGL-uLCD-SE PinDetect mbed

Revision:
0:d0e2fe309777
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Apr 03 00:24:50 2017 +0000
@@ -0,0 +1,296 @@
+#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
+}