Code for the following project: https://www.instructables.com/id/Ultimate-Hamster-Tracker-Wheel-Featuring-Mbed-C-LC/
Dependencies: 4DGL-uLCD-SE PinDetect mbed
Diff: main.cpp
- 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 +}