VR FabLab - RoboVal / Mbed 2 deprecated Chronometer_V2_Infrared

Dependencies:   TextLCD keypadLib mbed

Fork of Chronometer_V2 by VR FabLab - RoboVal

Committer:
peps
Date:
Tue May 22 20:34:09 2018 +0000
Revision:
4:23472c2b246b
Parent:
3:fd1353986910
Child:
5:47a452a6f248
Versione funzionante, con tastierino e best time speed mode.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Ghiri 0:1a92e4a37697 1 //##############################################################
Ghiri 0:1a92e4a37697 2 //##
Ghiri 0:1a92e4a37697 3 //## Event: RoboVal - Robot Race
Ghiri 0:1a92e4a37697 4 //##
Ghiri 0:1a92e4a37697 5 //## Chronometer double use
Ghiri 0:1a92e4a37697 6 //##
Ghiri 0:1a92e4a37697 7 //## Version 1.99A
Ghiri 0:1a92e4a37697 8 //##
Ghiri 0:1a92e4a37697 9 //## Hardware platform used: ST NUCLEO-F401RE
Ghiri 0:1a92e4a37697 10 //##
Ghiri 0:1a92e4a37697 11 //## Software IDE used: mbed online version
Ghiri 0:1a92e4a37697 12 //##
Ghiri 0:1a92e4a37697 13 //## Organizzation: Verona FabLab
Ghiri 0:1a92e4a37697 14 //##
Ghiri 0:1a92e4a37697 15 //## Date creation: 2018.01.01
Ghiri 0:1a92e4a37697 16 //##
Ghiri 0:1a92e4a37697 17 //## Software developpers: FdF,GV, AG
Ghiri 0:1a92e4a37697 18 //##
Ghiri 0:1a92e4a37697 19 //## Base on original version of by FdF
Ghiri 0:1a92e4a37697 20 //##
Ghiri 0:1a92e4a37697 21 //##############################################################
Ghiri 0:1a92e4a37697 22
Ghiri 0:1a92e4a37697 23 #include <stdlib.h>
Ghiri 0:1a92e4a37697 24 #include "mbed.h"
Ghiri 0:1a92e4a37697 25 #include "TextLCD.h"
peps 2:bd0c735e81d6 26
Ghiri 0:1a92e4a37697 27 // Default Number Lap
Ghiri 0:1a92e4a37697 28 #define NUM_LAP 3
Ghiri 0:1a92e4a37697 29
Ghiri 0:1a92e4a37697 30 // Reference for Low/Min Voltage battery
Ghiri 0:1a92e4a37697 31 #define VBAT_MIN 7.2
peps 2:bd0c735e81d6 32
peps 3:fd1353986910 33 // Different function modes
peps 3:fd1353986910 34 // Switch among them using the USER button
peps 3:fd1353986910 35 // (waiting for the keypad to work properly)
peps 2:bd0c735e81d6 36 enum modes {
peps 2:bd0c735e81d6 37 LABYRINTH,
peps 2:bd0c735e81d6 38 SPEED
peps 2:bd0c735e81d6 39 } mode = SPEED;
peps 2:bd0c735e81d6 40
peps 3:fd1353986910 41 // Human-readable time helper
peps 2:bd0c735e81d6 42 typedef struct time_screen {
peps 2:bd0c735e81d6 43 int cents;
peps 2:bd0c735e81d6 44 int seconds;
peps 2:bd0c735e81d6 45 int minutes;
peps 2:bd0c735e81d6 46 } measured_time;
Ghiri 1:26bcd89c18e5 47
peps 3:fd1353986910 48 // Heartbeat LED
Ghiri 0:1a92e4a37697 49 DigitalOut heartbeat(LED1);
Ghiri 0:1a92e4a37697 50
Ghiri 0:1a92e4a37697 51 // read Voltage battery, analog pin used PC_3 (Pin 37 of Morpho layout)
Ghiri 1:26bcd89c18e5 52 //AnalogIn vbat(PC_3);
Ghiri 0:1a92e4a37697 53
Ghiri 0:1a92e4a37697 54 // User button pressure
Ghiri 0:1a92e4a37697 55 InterruptIn user_button(USER_BUTTON);
Ghiri 0:1a92e4a37697 56
peps 3:fd1353986910 57 // Gates connected to digital input PA_15 and PB_7
peps 3:fd1353986910 58 InterruptIn gateStart(PA_15), gateEnd(PB_7);
Ghiri 0:1a92e4a37697 59
Ghiri 0:1a92e4a37697 60 // LCD Display (RS, E, D4, D5, D6, D7);
Ghiri 0:1a92e4a37697 61 TextLCD lcd(D2,D3,D4,D5,D6,D7);
peps 2:bd0c735e81d6 62
peps 3:fd1353986910 63 // Timer for the chrono function
peps 2:bd0c735e81d6 64 Timer t;
Ghiri 0:1a92e4a37697 65
peps 3:fd1353986910 66 // Number of laps
peps 3:fd1353986910 67 int lap = -1;
peps 3:fd1353986910 68 // Best lap
peps 3:fd1353986910 69 int best_lap = 0;
peps 3:fd1353986910 70 // Last time read
peps 2:bd0c735e81d6 71 int last_read = 0;
peps 3:fd1353986910 72 // Last lap time
peps 2:bd0c735e81d6 73 int lap_time = 0;
peps 3:fd1353986910 74 // Best lap time
peps 3:fd1353986910 75 int best_time = -1;
peps 3:fd1353986910 76 // Pointer to the loop function (depending on the selected mode)
peps 2:bd0c735e81d6 77 void (*loopMethod)(void);
peps 2:bd0c735e81d6 78
peps 4:23472c2b246b 79 /*** Gestione keypad ****/
peps 4:23472c2b246b 80 PinName rowPins[4] = { PA_13, PA_14, PC_2, PC_3 };
peps 4:23472c2b246b 81 PinName colPins[4] = { PA_0, PA_1, PA_4, PB_0 };
peps 4:23472c2b246b 82
peps 4:23472c2b246b 83 DigitalOut* _rows[4];
peps 4:23472c2b246b 84 DigitalIn* _cols[4];
peps 4:23472c2b246b 85
peps 4:23472c2b246b 86 // Define your own keypad values
peps 4:23472c2b246b 87 char Keytable[] = {
peps 4:23472c2b246b 88 '1', '2', '3', 'A', // r0
peps 4:23472c2b246b 89 '4', '5', '6', 'B', // r1
peps 4:23472c2b246b 90 '7', '8', '9', 'C', // r2
peps 4:23472c2b246b 91 '*', '0', '#', 'D' // r3
peps 4:23472c2b246b 92 // c0 c1 c2 c3
peps 4:23472c2b246b 93 };
peps 4:23472c2b246b 94
peps 4:23472c2b246b 95 int getKeyIndex() {
peps 4:23472c2b246b 96 int result = -1;
peps 4:23472c2b246b 97 for (int r = 0; r < 4; r++) {
peps 4:23472c2b246b 98 _rows[r]->write(1);
peps 4:23472c2b246b 99 for(int c = 0;c < 4 ;c++){
peps 4:23472c2b246b 100 DigitalIn *col = _cols[c];
peps 4:23472c2b246b 101 if(col->read() == 1) {
peps 4:23472c2b246b 102 result = r*4+c;
peps 4:23472c2b246b 103 }
peps 4:23472c2b246b 104 }
peps 4:23472c2b246b 105 _rows[r]->write(0);
peps 4:23472c2b246b 106 }
peps 4:23472c2b246b 107 return result;
peps 4:23472c2b246b 108 }
peps 4:23472c2b246b 109
peps 4:23472c2b246b 110 char getKey() {
peps 4:23472c2b246b 111 int idx = getKeyIndex();
peps 4:23472c2b246b 112 return idx != -1 ? Keytable[idx] : '\0';
peps 4:23472c2b246b 113 }
peps 4:23472c2b246b 114
peps 4:23472c2b246b 115 void keypadInit() {
peps 4:23472c2b246b 116 for(int i = 0;i < 4; i++){
peps 4:23472c2b246b 117 _rows[i] = new DigitalOut(rowPins[i]);
peps 4:23472c2b246b 118 _rows[i]->write(0);
peps 4:23472c2b246b 119 }
peps 4:23472c2b246b 120 for(int i = 0;i < 4; i++){
peps 4:23472c2b246b 121 _cols[i] = new DigitalIn(colPins[i],PullDown);
peps 4:23472c2b246b 122 }
peps 4:23472c2b246b 123 }
peps 4:23472c2b246b 124 /**** fine gestione keypad ****/
peps 4:23472c2b246b 125
peps 2:bd0c735e81d6 126 //Conversione da millisecondi a mm:ss:cc
peps 2:bd0c735e81d6 127 measured_time human_read(int ms){
peps 2:bd0c735e81d6 128 measured_time read;
peps 2:bd0c735e81d6 129 div_t qr = div(ms,1000);
peps 2:bd0c735e81d6 130
peps 2:bd0c735e81d6 131 read.cents = qr.rem % 100;
peps 2:bd0c735e81d6 132
peps 2:bd0c735e81d6 133 qr = div(qr.quot,60);
peps 2:bd0c735e81d6 134 read.seconds = qr.rem;
peps 2:bd0c735e81d6 135
peps 2:bd0c735e81d6 136 qr = div(qr.quot,60);
peps 2:bd0c735e81d6 137 read.minutes = qr.rem;
peps 2:bd0c735e81d6 138
peps 2:bd0c735e81d6 139 return read;
peps 2:bd0c735e81d6 140 }
peps 2:bd0c735e81d6 141
peps 3:fd1353986910 142 // Invoked when startGate triggered.
peps 3:fd1353986910 143 // Start the timer or read the timer and store lap and best time
peps 3:fd1353986910 144 void measure_time() {
peps 2:bd0c735e81d6 145 int read = t.read_ms();
peps 3:fd1353986910 146
peps 3:fd1353986910 147 if(lap == -1){
peps 2:bd0c735e81d6 148 t.start();
peps 2:bd0c735e81d6 149 lap++;
peps 2:bd0c735e81d6 150 }else{
peps 2:bd0c735e81d6 151 //Dabouncing per evitare problemi
peps 2:bd0c735e81d6 152 if(read - last_read > 1000){
peps 2:bd0c735e81d6 153
peps 3:fd1353986910 154 lap++;
peps 2:bd0c735e81d6 155 lap_time = read - last_read;
peps 3:fd1353986910 156 if (best_time < 0 || lap_time < best_time) {
peps 3:fd1353986910 157 best_time = lap_time;
peps 3:fd1353986910 158 best_lap = lap;
peps 3:fd1353986910 159 }
peps 2:bd0c735e81d6 160
peps 3:fd1353986910 161 if(lap >= NUM_LAP) {
peps 2:bd0c735e81d6 162 t.stop();
peps 2:bd0c735e81d6 163 }
peps 2:bd0c735e81d6 164
peps 2:bd0c735e81d6 165 last_read = read;
peps 2:bd0c735e81d6 166 }
peps 3:fd1353986910 167 }
peps 2:bd0c735e81d6 168 }
peps 2:bd0c735e81d6 169
peps 4:23472c2b246b 170 // Handler for loop when in SPEED mode
peps 2:bd0c735e81d6 171 void speedLoop() {
peps 2:bd0c735e81d6 172 int read = t.read_ms();
peps 2:bd0c735e81d6 173
peps 2:bd0c735e81d6 174 measured_time time = human_read(read);
peps 2:bd0c735e81d6 175
peps 2:bd0c735e81d6 176 lcd.locate(0,0);
peps 2:bd0c735e81d6 177 lcd.printf("Totale %02d:%02d:%02d",time.minutes,time.seconds,time.cents);
peps 4:23472c2b246b 178
peps 4:23472c2b246b 179 // Handle lap time display
peps 4:23472c2b246b 180 switch(lap) {
peps 4:23472c2b246b 181 // only display time if at least 1 lap completed
peps 4:23472c2b246b 182 case -1:
peps 4:23472c2b246b 183 case 0:
peps 4:23472c2b246b 184 break;
peps 4:23472c2b246b 185 // all laps completed - display best lap time
peps 4:23472c2b246b 186 case NUM_LAP + 1:
peps 4:23472c2b246b 187 time = human_read(best_time);
peps 4:23472c2b246b 188 lcd.locate(0,1);
peps 4:23472c2b246b 189 lcd.printf("Best %d %02d:%02d:%02d",best_lap,time.minutes,time.seconds,time.cents);
peps 4:23472c2b246b 190 break;
peps 4:23472c2b246b 191 // Default - display last completed lap time
peps 4:23472c2b246b 192 // In case of last lap, wait 1 sec -- next time, best lap will be displayed
peps 4:23472c2b246b 193 default:
peps 4:23472c2b246b 194 time = human_read(lap_time);
peps 4:23472c2b246b 195 lcd.locate(0,1);
peps 4:23472c2b246b 196 lcd.printf("Giro %d %02d:%02d:%02d",lap,time.minutes,time.seconds,time.cents);
peps 4:23472c2b246b 197 if (lap == NUM_LAP) {
peps 4:23472c2b246b 198 wait(1);
peps 4:23472c2b246b 199 lap++;
peps 4:23472c2b246b 200 }
peps 4:23472c2b246b 201 break;
peps 2:bd0c735e81d6 202 }
peps 2:bd0c735e81d6 203 }
peps 2:bd0c735e81d6 204
peps 2:bd0c735e81d6 205 void start_time() {
peps 2:bd0c735e81d6 206 lap = 0;
peps 2:bd0c735e81d6 207 t.start();
peps 2:bd0c735e81d6 208 }
peps 2:bd0c735e81d6 209
peps 2:bd0c735e81d6 210 void stop_time() {
peps 2:bd0c735e81d6 211 lap = 1;
peps 2:bd0c735e81d6 212 t.stop();
peps 2:bd0c735e81d6 213 int read = t.read_ms();
peps 2:bd0c735e81d6 214
peps 2:bd0c735e81d6 215 measured_time time = human_read(read);
peps 2:bd0c735e81d6 216
peps 3:fd1353986910 217 lcd.cls();
peps 3:fd1353986910 218 lcd.locate(0,0);
peps 4:23472c2b246b 219 lcd.printf("Finish!");
peps 2:bd0c735e81d6 220 lcd.locate(0,1);
peps 2:bd0c735e81d6 221 lcd.printf("Totale %02d:%02d:%02d",time.minutes,time.seconds,time.cents);
peps 4:23472c2b246b 222 gateStart.disable_irq();
peps 4:23472c2b246b 223 gateEnd.disable_irq();
peps 2:bd0c735e81d6 224 }
peps 2:bd0c735e81d6 225
peps 2:bd0c735e81d6 226 void labyrinthLoop() {
peps 4:23472c2b246b 227 int read = t.read_ms();
peps 4:23472c2b246b 228 measured_time time = human_read(read);
peps 4:23472c2b246b 229 lcd.locate(0,1);
peps 4:23472c2b246b 230 lcd.printf("Elapsed %02d:%02d:%02d",time.minutes,time.seconds,time.cents);
peps 2:bd0c735e81d6 231 }
peps 2:bd0c735e81d6 232
peps 2:bd0c735e81d6 233 void configMode() {
peps 2:bd0c735e81d6 234 switch(mode) {
peps 2:bd0c735e81d6 235 case LABYRINTH:
peps 4:23472c2b246b 236 gateStart.enable_irq();
peps 2:bd0c735e81d6 237 gateStart.rise(&start_time);
peps 3:fd1353986910 238 gateEnd.enable_irq();
peps 2:bd0c735e81d6 239 gateEnd.rise(&stop_time);
peps 2:bd0c735e81d6 240 loopMethod = &labyrinthLoop;
peps 3:fd1353986910 241 lcd.cls();
peps 3:fd1353986910 242 lcd.locate(0,0);
peps 3:fd1353986910 243 lcd.printf("Mode: LABYRINTH ");
peps 3:fd1353986910 244 wait(1);
peps 2:bd0c735e81d6 245 break;
peps 2:bd0c735e81d6 246
peps 2:bd0c735e81d6 247 case SPEED:
peps 2:bd0c735e81d6 248 default:
peps 4:23472c2b246b 249 gateStart.enable_irq();
peps 2:bd0c735e81d6 250 gateStart.rise(&measure_time);
peps 3:fd1353986910 251 gateEnd.disable_irq();
peps 2:bd0c735e81d6 252 loopMethod = &speedLoop;
peps 3:fd1353986910 253 lcd.cls();
peps 3:fd1353986910 254 lcd.locate(0,0);
peps 3:fd1353986910 255 lcd.printf("Mode: SPEED ");
peps 3:fd1353986910 256 wait(1);
peps 3:fd1353986910 257 lcd.cls();
peps 2:bd0c735e81d6 258 break;
peps 2:bd0c735e81d6 259 }
peps 2:bd0c735e81d6 260 }
peps 2:bd0c735e81d6 261
peps 3:fd1353986910 262 void reset_measure(){
peps 3:fd1353986910 263 t.stop();
peps 3:fd1353986910 264 t.reset();
peps 3:fd1353986910 265 lap = -1;
peps 3:fd1353986910 266 last_read = 0;
peps 3:fd1353986910 267 best_lap = 0;
peps 3:fd1353986910 268 best_time = -1;
peps 4:23472c2b246b 269 configMode();
peps 3:fd1353986910 270 }
peps 3:fd1353986910 271
peps 3:fd1353986910 272 void switchMode() {
peps 3:fd1353986910 273 mode = mode == SPEED ? LABYRINTH : SPEED;
peps 3:fd1353986910 274 reset_measure();
peps 3:fd1353986910 275 }
peps 3:fd1353986910 276
Ghiri 0:1a92e4a37697 277 //------------------------------------------------------------
Ghiri 0:1a92e4a37697 278 //
Ghiri 0:1a92e4a37697 279 // Main body
Ghiri 0:1a92e4a37697 280 //
Ghiri 0:1a92e4a37697 281 //------------------------------------------------------------
Ghiri 0:1a92e4a37697 282 int main() {
peps 2:bd0c735e81d6 283 char key;
peps 4:23472c2b246b 284 keypadInit();
peps 4:23472c2b246b 285
peps 3:fd1353986910 286 user_button.fall(&switchMode);
peps 2:bd0c735e81d6 287
peps 2:bd0c735e81d6 288 gateStart.mode(PullDown);
peps 2:bd0c735e81d6 289 gateEnd.mode(PullDown);
peps 2:bd0c735e81d6 290
peps 4:23472c2b246b 291 reset_measure();
peps 2:bd0c735e81d6 292
peps 2:bd0c735e81d6 293 while(true) {
Ghiri 0:1a92e4a37697 294 heartbeat = !heartbeat;
peps 2:bd0c735e81d6 295 loopMethod();
peps 2:bd0c735e81d6 296 wait(0.1);
peps 4:23472c2b246b 297 key = getKey();
peps 4:23472c2b246b 298 if (key != '\0') {
peps 2:bd0c735e81d6 299 if(key == 'A') {
peps 2:bd0c735e81d6 300 mode = LABYRINTH;
peps 4:23472c2b246b 301 reset_measure();
peps 2:bd0c735e81d6 302 } else if(key == 'B') {
peps 2:bd0c735e81d6 303 mode = SPEED;
peps 4:23472c2b246b 304 reset_measure();
peps 4:23472c2b246b 305 } else if(key == '#') {
peps 2:bd0c735e81d6 306 reset_measure();
peps 2:bd0c735e81d6 307 }
Ghiri 0:1a92e4a37697 308 }
Ghiri 0:1a92e4a37697 309 }
Ghiri 0:1a92e4a37697 310 }
Ghiri 0:1a92e4a37697 311