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 }