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

Dependencies:   4DGL-uLCD-SE PinDetect mbed

Committer:
bstrickland9
Date:
Mon Apr 03 00:24:50 2017 +0000
Revision:
0:d0e2fe309777
Code for the following project:; https://www.instructables.com/id/Ultimate-Hamster-Tracker-Wheel-Featuring-Mbed-C-LC/

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bstrickland9 0:d0e2fe309777 1 #include "mbed.h"
bstrickland9 0:d0e2fe309777 2 #include "PinDetect.h"
bstrickland9 0:d0e2fe309777 3 #include "uLCD_4DGL.h"
bstrickland9 0:d0e2fe309777 4 #include "Shiftbrite.h"
bstrickland9 0:d0e2fe309777 5
bstrickland9 0:d0e2fe309777 6 DigitalOut myled1(LED1);
bstrickland9 0:d0e2fe309777 7 DigitalOut myled2(LED2);
bstrickland9 0:d0e2fe309777 8 DigitalOut myled3(LED3);
bstrickland9 0:d0e2fe309777 9 DigitalOut myled4(LED4);
bstrickland9 0:d0e2fe309777 10
bstrickland9 0:d0e2fe309777 11 // use class to setup pushbuttons pins
bstrickland9 0:d0e2fe309777 12 PinDetect pb1(p23);
bstrickland9 0:d0e2fe309777 13 PinDetect pb2(p24);
bstrickland9 0:d0e2fe309777 14
bstrickland9 0:d0e2fe309777 15 // use class to setup the Color LCD
bstrickland9 0:d0e2fe309777 16 uLCD_4DGL uLCD(p28, p27, p29); // create a global uLCD object
bstrickland9 0:d0e2fe309777 17
bstrickland9 0:d0e2fe309777 18 // Global variables used in callbacks and main program
bstrickland9 0:d0e2fe309777 19 // C variables in interrupt routines should use volatile keyword
bstrickland9 0:d0e2fe309777 20 int volatile magnetHit=0;
bstrickland9 0:d0e2fe309777 21
bstrickland9 0:d0e2fe309777 22 //timer setup
bstrickland9 0:d0e2fe309777 23 Timer t;
bstrickland9 0:d0e2fe309777 24
bstrickland9 0:d0e2fe309777 25 // Callback routine is interrupt activated by a debounced magnet hit
bstrickland9 0:d0e2fe309777 26 void pb1_hit_callback (void)
bstrickland9 0:d0e2fe309777 27 {
bstrickland9 0:d0e2fe309777 28 magnetHit=1;
bstrickland9 0:d0e2fe309777 29 }
bstrickland9 0:d0e2fe309777 30
bstrickland9 0:d0e2fe309777 31 // Callback routine is interrupt activated by a debounced magnet unhit
bstrickland9 0:d0e2fe309777 32 void pb2_hit_callback (void)
bstrickland9 0:d0e2fe309777 33 {
bstrickland9 0:d0e2fe309777 34 magnetHit=1;
bstrickland9 0:d0e2fe309777 35 }
bstrickland9 0:d0e2fe309777 36
bstrickland9 0:d0e2fe309777 37 // use class to setup Shiftbrite pins
bstrickland9 0:d0e2fe309777 38 Shiftbrite myShiftbrite(p9, p10, p11, p12, p13);// ei li di n/c ci
bstrickland9 0:d0e2fe309777 39
bstrickland9 0:d0e2fe309777 40 // init
bstrickland9 0:d0e2fe309777 41 float circumference=0, speed=0, tempFloat=0, changePercent=0, averageBlock=0; //average is float
bstrickland9 0:d0e2fe309777 42 int a1=10000, a2=10000, a3=10000, a4=10000, a5=10000, cumulativeDistBlock=0, recentBlock=0; //avg values assume ~7.5km
bstrickland9 0:d0e2fe309777 43 int highestBlock=0, lowestBlock=99999999, dayCount=0;
bstrickland9 0:d0e2fe309777 44 unsigned int myColor = 0x000000;
bstrickland9 0:d0e2fe309777 45 unsigned int shiftR=0, shiftG=0, shiftB=0;
bstrickland9 0:d0e2fe309777 46 bool execSpaces=0;
bstrickland9 0:d0e2fe309777 47
bstrickland9 0:d0e2fe309777 48 int main() {
bstrickland9 0:d0e2fe309777 49 //start timer
bstrickland9 0:d0e2fe309777 50 t.start();
bstrickland9 0:d0e2fe309777 51 myled1 = 1;
bstrickland9 0:d0e2fe309777 52
bstrickland9 0:d0e2fe309777 53 shiftR = 50;
bstrickland9 0:d0e2fe309777 54 myShiftbrite.write( shiftR, shiftG, shiftB);
bstrickland9 0:d0e2fe309777 55
bstrickland9 0:d0e2fe309777 56 uLCD.color(0xff3333);
bstrickland9 0:d0e2fe309777 57 uLCD.locate(0,0);
bstrickland9 0:d0e2fe309777 58 uLCD.printf(" ...Starting...");
bstrickland9 0:d0e2fe309777 59
bstrickland9 0:d0e2fe309777 60 // Use internal pullups/downs for the pushbutton
bstrickland9 0:d0e2fe309777 61 pb1.mode(PullDown); //PullUp gnd and input. PullDown vcc and input.
bstrickland9 0:d0e2fe309777 62 pb2.mode(PullUp);
bstrickland9 0:d0e2fe309777 63 // Delay for initial pullup to take effect
bstrickland9 0:d0e2fe309777 64 wait(.1);
bstrickland9 0:d0e2fe309777 65 // Setup Interrupt callback functions for a pb hit
bstrickland9 0:d0e2fe309777 66 //pb1.attach_deasserted(&pb1_unhit_callback);
bstrickland9 0:d0e2fe309777 67 pb1.attach_asserted(&pb1_hit_callback);
bstrickland9 0:d0e2fe309777 68 pb2.attach_deasserted(&pb2_hit_callback);
bstrickland9 0:d0e2fe309777 69 // Start sampling pb inputs using interrupts. leave as () default 20ms aka 20000.
bstrickland9 0:d0e2fe309777 70 pb1.setSampleFrequency(10000); //using 10ms aka 10000
bstrickland9 0:d0e2fe309777 71 pb2.setSampleFrequency(10000);
bstrickland9 0:d0e2fe309777 72 //setSamplesTillAssert, default is 50 continuous samples
bstrickland9 0:d0e2fe309777 73 pb1.setSamplesTillAssert(6);
bstrickland9 0:d0e2fe309777 74 pb2.setSamplesTillAssert(6);
bstrickland9 0:d0e2fe309777 75
bstrickland9 0:d0e2fe309777 76 // Set RTC time to Wed, 28 Oct 2009 11:35:37 (January 1, 1970)
bstrickland9 0:d0e2fe309777 77 set_time(1);
bstrickland9 0:d0e2fe309777 78 //time_t mktime (tm * timeptr) //needed?
bstrickland9 0:d0e2fe309777 79
bstrickland9 0:d0e2fe309777 80 //setup circumference
bstrickland9 0:d0e2fe309777 81 circumference = 3.14159*0.24; //pi * diam (m) //tweakMe was 0.254
bstrickland9 0:d0e2fe309777 82
bstrickland9 0:d0e2fe309777 83 wait(0.4);
bstrickland9 0:d0e2fe309777 84 uLCD.locate(0,0);
bstrickland9 0:d0e2fe309777 85 uLCD.color(0x4444ff);
bstrickland9 0:d0e2fe309777 86 uLCD.printf(" Ultimate Hamster");
bstrickland9 0:d0e2fe309777 87
bstrickland9 0:d0e2fe309777 88 //labels print in this color
bstrickland9 0:d0e2fe309777 89 uLCD.color(0x8888ff);
bstrickland9 0:d0e2fe309777 90
bstrickland9 0:d0e2fe309777 91 // set up permanent characters on display
bstrickland9 0:d0e2fe309777 92 uLCD.locate(0,2);
bstrickland9 0:d0e2fe309777 93 uLCD.printf("Speed: (m/s)");
bstrickland9 0:d0e2fe309777 94
bstrickland9 0:d0e2fe309777 95 uLCD.locate(0,4);
bstrickland9 0:d0e2fe309777 96 uLCD.printf("Change: (%%)");
bstrickland9 0:d0e2fe309777 97
bstrickland9 0:d0e2fe309777 98 //optimize other labels too one day...
bstrickland9 0:d0e2fe309777 99 uLCD.locate(0,6);
bstrickland9 0:d0e2fe309777 100 uLCD.printf("Recent: (m)");
bstrickland9 0:d0e2fe309777 101 uLCD.locate(0,8);
bstrickland9 0:d0e2fe309777 102 uLCD.printf("Average: (m)");
bstrickland9 0:d0e2fe309777 103 uLCD.locate(0,10);
bstrickland9 0:d0e2fe309777 104 uLCD.printf("Highest: (m)");
bstrickland9 0:d0e2fe309777 105 uLCD.locate(0,12);
bstrickland9 0:d0e2fe309777 106 uLCD.printf("Lowest: (m)");
bstrickland9 0:d0e2fe309777 107
bstrickland9 0:d0e2fe309777 108 uLCD.locate(0,15);
bstrickland9 0:d0e2fe309777 109 uLCD.printf("0 /24hr day 0 ");
bstrickland9 0:d0e2fe309777 110
bstrickland9 0:d0e2fe309777 111 //old debug display...
bstrickland9 0:d0e2fe309777 112 //uLCD.locate(0,14);
bstrickland9 0:d0e2fe309777 113 //uLCD.printf("Time:");
bstrickland9 0:d0e2fe309777 114 //uLCD.locate(0,15);
bstrickland9 0:d0e2fe309777 115 //uLCD.printf("Hour:");
bstrickland9 0:d0e2fe309777 116
bstrickland9 0:d0e2fe309777 117 // end
bstrickland9 0:d0e2fe309777 118
bstrickland9 0:d0e2fe309777 119 //numbers print in this color
bstrickland9 0:d0e2fe309777 120 uLCD.color(0xcccc33);
bstrickland9 0:d0e2fe309777 121 //if you want to change this, also change value near changePercent print!
bstrickland9 0:d0e2fe309777 122
bstrickland9 0:d0e2fe309777 123 shiftR=0;
bstrickland9 0:d0e2fe309777 124 shiftG=0;
bstrickland9 0:d0e2fe309777 125 shiftB=50;
bstrickland9 0:d0e2fe309777 126 myShiftbrite.write( shiftR, shiftG, shiftB);
bstrickland9 0:d0e2fe309777 127
bstrickland9 0:d0e2fe309777 128
bstrickland9 0:d0e2fe309777 129 while(1) {
bstrickland9 0:d0e2fe309777 130
bstrickland9 0:d0e2fe309777 131 myled1 = !myled1; // show loop is active
bstrickland9 0:d0e2fe309777 132 //shiftR = (rand()*40) % 40;
bstrickland9 0:d0e2fe309777 133 //shiftG = (rand()*40) % 40;
bstrickland9 0:d0e2fe309777 134 //shiftB = (rand()*40) % 40;
bstrickland9 0:d0e2fe309777 135 shiftR = 0;
bstrickland9 0:d0e2fe309777 136 shiftG = 0;
bstrickland9 0:d0e2fe309777 137 shiftB = 0;
bstrickland9 0:d0e2fe309777 138 myShiftbrite.write( shiftR, shiftG, shiftB);
bstrickland9 0:d0e2fe309777 139
bstrickland9 0:d0e2fe309777 140 switch (magnetHit) {
bstrickland9 0:d0e2fe309777 141 case 0:
bstrickland9 0:d0e2fe309777 142 myled2 = 1;
bstrickland9 0:d0e2fe309777 143 myled3 = 0;
bstrickland9 0:d0e2fe309777 144 break;
bstrickland9 0:d0e2fe309777 145 case 1:
bstrickland9 0:d0e2fe309777 146
bstrickland9 0:d0e2fe309777 147 myled2 = 0;
bstrickland9 0:d0e2fe309777 148 myled3 = 1;
bstrickland9 0:d0e2fe309777 149
bstrickland9 0:d0e2fe309777 150 //change title color
bstrickland9 0:d0e2fe309777 151 //myColor = (rand()*0xffffff) % 0xffffff;
bstrickland9 0:d0e2fe309777 152
bstrickland9 0:d0e2fe309777 153 //change shiftbrite color
bstrickland9 0:d0e2fe309777 154 myShiftbrite.write( 20, 20, 20);
bstrickland9 0:d0e2fe309777 155
bstrickland9 0:d0e2fe309777 156 //speed calc
bstrickland9 0:d0e2fe309777 157 //using timer t.
bstrickland9 0:d0e2fe309777 158 tempFloat = t.read();
bstrickland9 0:d0e2fe309777 159 t.reset();
bstrickland9 0:d0e2fe309777 160
bstrickland9 0:d0e2fe309777 161 //send speed to display
bstrickland9 0:d0e2fe309777 162 speed = circumference / tempFloat;
bstrickland9 0:d0e2fe309777 163 uLCD.locate(7,2);
bstrickland9 0:d0e2fe309777 164 uLCD.printf("%5.2F", speed); //speed: number
bstrickland9 0:d0e2fe309777 165
bstrickland9 0:d0e2fe309777 166 //4mph or 1.8m/s is a timer value of 0.44s per revolution
bstrickland9 0:d0e2fe309777 167 if (tempFloat > 0.3) { //instead use 0.3
bstrickland9 0:d0e2fe309777 168 cumulativeDistBlock = cumulativeDistBlock + 1;
bstrickland9 0:d0e2fe309777 169 } else {
bstrickland9 0:d0e2fe309777 170 //shiftbrite
bstrickland9 0:d0e2fe309777 171 }
bstrickland9 0:d0e2fe309777 172
bstrickland9 0:d0e2fe309777 173 magnetHit=0; //force to zero
bstrickland9 0:d0e2fe309777 174
bstrickland9 0:d0e2fe309777 175 myShiftbrite.write( shiftR, shiftG, shiftB);
bstrickland9 0:d0e2fe309777 176
bstrickland9 0:d0e2fe309777 177 break;
bstrickland9 0:d0e2fe309777 178 }
bstrickland9 0:d0e2fe309777 179
bstrickland9 0:d0e2fe309777 180 //for debug only
bstrickland9 0:d0e2fe309777 181 //uLCD.locate(0,10);
bstrickland9 0:d0e2fe309777 182 //uLCD.printf("t.read: %5.2F", t.read());
bstrickland9 0:d0e2fe309777 183
bstrickland9 0:d0e2fe309777 184 //check if wheel is still for more than 5 seconds
bstrickland9 0:d0e2fe309777 185 //t.stop(); //line not needed if t.read() can occur without pause
bstrickland9 0:d0e2fe309777 186 if (t.read() > 3 && t.read() < 4) { //1 second window (24hr takes ~0.7s)
bstrickland9 0:d0e2fe309777 187 uLCD.locate(8,2);
bstrickland9 0:d0e2fe309777 188 uLCD.printf("zero"); //speed: zero
bstrickland9 0:d0e2fe309777 189 }
bstrickland9 0:d0e2fe309777 190 //t.start(); //line not needed if t.read() can occur without pause
bstrickland9 0:d0e2fe309777 191
bstrickland9 0:d0e2fe309777 192 if (t.read() > 300) { //every 5 mins, reset speed timer
bstrickland9 0:d0e2fe309777 193 //prevent overflow, max value is 1800, 30 mins
bstrickland9 0:d0e2fe309777 194 t.reset();
bstrickland9 0:d0e2fe309777 195 }
bstrickland9 0:d0e2fe309777 196
bstrickland9 0:d0e2fe309777 197 //get the current time
bstrickland9 0:d0e2fe309777 198 time_t seconds = time(NULL);
bstrickland9 0:d0e2fe309777 199
bstrickland9 0:d0e2fe309777 200 uLCD.locate(0,15);
bstrickland9 0:d0e2fe309777 201 uLCD.printf("%u", seconds/60/60 ); //change seconds to seconds/60/60
bstrickland9 0:d0e2fe309777 202
bstrickland9 0:d0e2fe309777 203 //time display for debug
bstrickland9 0:d0e2fe309777 204 //uLCD.locate(6,14);
bstrickland9 0:d0e2fe309777 205 //uLCD.printf("%u ", seconds );
bstrickland9 0:d0e2fe309777 206 //uLCD.locate(6,15);
bstrickland9 0:d0e2fe309777 207 //uLCD.printf("%u ", seconds/60/60 );
bstrickland9 0:d0e2fe309777 208
bstrickland9 0:d0e2fe309777 209 //this runs every 24hr block
bstrickland9 0:d0e2fe309777 210 if (seconds >= 86400) { //86400 is 24hrs
bstrickland9 0:d0e2fe309777 211 myShiftbrite.write( 50, 0, 0);
bstrickland9 0:d0e2fe309777 212
bstrickland9 0:d0e2fe309777 213 //compute 24hr block values
bstrickland9 0:d0e2fe309777 214 recentBlock = cumulativeDistBlock;
bstrickland9 0:d0e2fe309777 215 cumulativeDistBlock = 0; //reset
bstrickland9 0:d0e2fe309777 216 dayCount++; //add one to day
bstrickland9 0:d0e2fe309777 217
bstrickland9 0:d0e2fe309777 218 //change tracking
bstrickland9 0:d0e2fe309777 219 changePercent = 100*(recentBlock-averageBlock) / (averageBlock); //signed float
bstrickland9 0:d0e2fe309777 220
bstrickland9 0:d0e2fe309777 221 //shift numbers in array to delete oldest value
bstrickland9 0:d0e2fe309777 222 a1 = a2; //oldest
bstrickland9 0:d0e2fe309777 223 a2 = a3;
bstrickland9 0:d0e2fe309777 224 a3 = a4;
bstrickland9 0:d0e2fe309777 225 a4 = a5;
bstrickland9 0:d0e2fe309777 226 a5 = recentBlock; //newest
bstrickland9 0:d0e2fe309777 227 averageBlock = (a1 + a2 + a3 + a4 + a5)/5; //int becomes float
bstrickland9 0:d0e2fe309777 228
bstrickland9 0:d0e2fe309777 229 //check if recentBlock is new high or new low
bstrickland9 0:d0e2fe309777 230 if (recentBlock > highestBlock) { //new high
bstrickland9 0:d0e2fe309777 231 highestBlock = recentBlock;
bstrickland9 0:d0e2fe309777 232 //Highest (m) store max value
bstrickland9 0:d0e2fe309777 233 tempFloat = highestBlock*circumference;
bstrickland9 0:d0e2fe309777 234 uLCD.locate(8,10);
bstrickland9 0:d0e2fe309777 235 uLCD.printf("%7.0F", tempFloat);
bstrickland9 0:d0e2fe309777 236 uLCD.locate(5,14);
bstrickland9 0:d0e2fe309777 237 uLCD.printf("NEW HIGH");
bstrickland9 0:d0e2fe309777 238 execSpaces = 1; //if no update on next round, set spaces
bstrickland9 0:d0e2fe309777 239 } else if (recentBlock < lowestBlock) { //new low
bstrickland9 0:d0e2fe309777 240 lowestBlock = recentBlock;
bstrickland9 0:d0e2fe309777 241 //Lowest (m) store min value
bstrickland9 0:d0e2fe309777 242 tempFloat = lowestBlock*circumference;
bstrickland9 0:d0e2fe309777 243 uLCD.locate(8,12);
bstrickland9 0:d0e2fe309777 244 uLCD.printf("%7.0F", tempFloat);
bstrickland9 0:d0e2fe309777 245 uLCD.locate(5,14);
bstrickland9 0:d0e2fe309777 246 uLCD.printf("NEW LOW ");
bstrickland9 0:d0e2fe309777 247 execSpaces = 1;
bstrickland9 0:d0e2fe309777 248 } else if (execSpaces == 1) {
bstrickland9 0:d0e2fe309777 249 uLCD.locate(5,14);
bstrickland9 0:d0e2fe309777 250 uLCD.printf(" ");
bstrickland9 0:d0e2fe309777 251 execSpaces = 0;
bstrickland9 0:d0e2fe309777 252 } //state machine so that spaces will not overwrite spaces every time
bstrickland9 0:d0e2fe309777 253
bstrickland9 0:d0e2fe309777 254 //use tempFloat to convert int rotations to distance (m)
bstrickland9 0:d0e2fe309777 255 //use circumference float
bstrickland9 0:d0e2fe309777 256 //update the following on display
bstrickland9 0:d0e2fe309777 257
bstrickland9 0:d0e2fe309777 258 //Change (%) past 24hr block vs average
bstrickland9 0:d0e2fe309777 259 if (changePercent > 0) {
bstrickland9 0:d0e2fe309777 260 //green
bstrickland9 0:d0e2fe309777 261 uLCD.color(0x33ff33);
bstrickland9 0:d0e2fe309777 262 } else if (changePercent < 0) {
bstrickland9 0:d0e2fe309777 263 //red
bstrickland9 0:d0e2fe309777 264 uLCD.color(0xff3333);
bstrickland9 0:d0e2fe309777 265 } else {
bstrickland9 0:d0e2fe309777 266 //purple, white??
bstrickland9 0:d0e2fe309777 267 uLCD.color(0xff33ff);
bstrickland9 0:d0e2fe309777 268 }
bstrickland9 0:d0e2fe309777 269 //tempFloat = changePercent;
bstrickland9 0:d0e2fe309777 270 uLCD.locate(8,4);
bstrickland9 0:d0e2fe309777 271 uLCD.printf("%7.0F", changePercent); //NAN and INF possible!
bstrickland9 0:d0e2fe309777 272 uLCD.color(0xcccc33); //reset color value!!!!! copy value from way above.
bstrickland9 0:d0e2fe309777 273
bstrickland9 0:d0e2fe309777 274 //Recent (m) past 24hr block
bstrickland9 0:d0e2fe309777 275 tempFloat = recentBlock*circumference;
bstrickland9 0:d0e2fe309777 276 uLCD.locate(8,6);
bstrickland9 0:d0e2fe309777 277 uLCD.printf("%7.0F", tempFloat);
bstrickland9 0:d0e2fe309777 278 //Average (m) average of the past 5 24hr
bstrickland9 0:d0e2fe309777 279 tempFloat = averageBlock*circumference;
bstrickland9 0:d0e2fe309777 280 uLCD.locate(8,8);
bstrickland9 0:d0e2fe309777 281 uLCD.printf("%7.0F", tempFloat);
bstrickland9 0:d0e2fe309777 282 //print for low and high happens only when value updated
bstrickland9 0:d0e2fe309777 283
bstrickland9 0:d0e2fe309777 284 //bottom line updates
bstrickland9 0:d0e2fe309777 285 uLCD.locate(0,15);
bstrickland9 0:d0e2fe309777 286 uLCD.printf("0 "); // remove leftover characters from XX/24hr
bstrickland9 0:d0e2fe309777 287 uLCD.locate(15,15); //modify this
bstrickland9 0:d0e2fe309777 288 uLCD.printf("%u", dayCount);
bstrickland9 0:d0e2fe309777 289
bstrickland9 0:d0e2fe309777 290 set_time(1); //reset
bstrickland9 0:d0e2fe309777 291
bstrickland9 0:d0e2fe309777 292 myShiftbrite.write( shiftR, shiftG, shiftB);
bstrickland9 0:d0e2fe309777 293 }
bstrickland9 0:d0e2fe309777 294
bstrickland9 0:d0e2fe309777 295 } //while end
bstrickland9 0:d0e2fe309777 296 }