Versione modificata con sensore e IR LED a 38kHz.

Dependencies:   TextLCD keypadLib mbed

Fork of Chronometer_V2 by VR FabLab - RoboVal

Committer:
peps
Date:
Thu May 24 22:13:20 2018 +0000
Revision:
6:853da83fe5a9
Parent:
5:47a452a6f248
Versione modificata con sensore infrarosso.

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 6:853da83fe5a9 57 // Gate connected to digital input PA_15
peps 6:853da83fe5a9 58 InterruptIn gateStart(PA_15);
peps 6:853da83fe5a9 59
peps 6:853da83fe5a9 60 // IR LED connected to PWM out PB_7
peps 6:853da83fe5a9 61 PwmOut IRLED(PB_7);
Ghiri 0:1a92e4a37697 62
Ghiri 0:1a92e4a37697 63 // LCD Display (RS, E, D4, D5, D6, D7);
Ghiri 0:1a92e4a37697 64 TextLCD lcd(D2,D3,D4,D5,D6,D7);
peps 2:bd0c735e81d6 65
peps 3:fd1353986910 66 // Timer for the chrono function
peps 2:bd0c735e81d6 67 Timer t;
Ghiri 0:1a92e4a37697 68
peps 3:fd1353986910 69 // Number of laps
peps 3:fd1353986910 70 int lap = -1;
peps 6:853da83fe5a9 71
peps 3:fd1353986910 72 // Best lap
peps 3:fd1353986910 73 int best_lap = 0;
peps 6:853da83fe5a9 74
peps 3:fd1353986910 75 // Last time read
peps 2:bd0c735e81d6 76 int last_read = 0;
peps 6:853da83fe5a9 77
peps 3:fd1353986910 78 // Last lap time
peps 2:bd0c735e81d6 79 int lap_time = 0;
peps 6:853da83fe5a9 80
peps 3:fd1353986910 81 // Best lap time
peps 3:fd1353986910 82 int best_time = -1;
peps 6:853da83fe5a9 83
peps 3:fd1353986910 84 // Pointer to the loop function (depending on the selected mode)
peps 2:bd0c735e81d6 85 void (*loopMethod)(void);
peps 6:853da83fe5a9 86
peps 5:47a452a6f248 87 // Flag to avoid unwanted mode switch when running
peps 5:47a452a6f248 88 bool isRunning = false;
peps 2:bd0c735e81d6 89
peps 5:47a452a6f248 90 /*** Keypad handling ****/
peps 4:23472c2b246b 91 PinName rowPins[4] = { PA_13, PA_14, PC_2, PC_3 };
peps 4:23472c2b246b 92 PinName colPins[4] = { PA_0, PA_1, PA_4, PB_0 };
peps 4:23472c2b246b 93
peps 4:23472c2b246b 94 DigitalOut* _rows[4];
peps 4:23472c2b246b 95 DigitalIn* _cols[4];
peps 4:23472c2b246b 96
peps 4:23472c2b246b 97 // Define your own keypad values
peps 4:23472c2b246b 98 char Keytable[] = {
peps 4:23472c2b246b 99 '1', '2', '3', 'A', // r0
peps 4:23472c2b246b 100 '4', '5', '6', 'B', // r1
peps 4:23472c2b246b 101 '7', '8', '9', 'C', // r2
peps 4:23472c2b246b 102 '*', '0', '#', 'D' // r3
peps 4:23472c2b246b 103 // c0 c1 c2 c3
peps 4:23472c2b246b 104 };
peps 4:23472c2b246b 105
peps 4:23472c2b246b 106 int getKeyIndex() {
peps 4:23472c2b246b 107 int result = -1;
peps 4:23472c2b246b 108 for (int r = 0; r < 4; r++) {
peps 4:23472c2b246b 109 _rows[r]->write(1);
peps 4:23472c2b246b 110 for(int c = 0;c < 4 ;c++){
peps 4:23472c2b246b 111 DigitalIn *col = _cols[c];
peps 4:23472c2b246b 112 if(col->read() == 1) {
peps 4:23472c2b246b 113 result = r*4+c;
peps 4:23472c2b246b 114 }
peps 4:23472c2b246b 115 }
peps 4:23472c2b246b 116 _rows[r]->write(0);
peps 4:23472c2b246b 117 }
peps 4:23472c2b246b 118 return result;
peps 4:23472c2b246b 119 }
peps 4:23472c2b246b 120
peps 4:23472c2b246b 121 char getKey() {
peps 4:23472c2b246b 122 int idx = getKeyIndex();
peps 4:23472c2b246b 123 return idx != -1 ? Keytable[idx] : '\0';
peps 4:23472c2b246b 124 }
peps 4:23472c2b246b 125
peps 4:23472c2b246b 126 void keypadInit() {
peps 4:23472c2b246b 127 for(int i = 0;i < 4; i++){
peps 4:23472c2b246b 128 _rows[i] = new DigitalOut(rowPins[i]);
peps 4:23472c2b246b 129 _rows[i]->write(0);
peps 4:23472c2b246b 130 }
peps 4:23472c2b246b 131 for(int i = 0;i < 4; i++){
peps 4:23472c2b246b 132 _cols[i] = new DigitalIn(colPins[i],PullDown);
peps 4:23472c2b246b 133 }
peps 4:23472c2b246b 134 }
peps 5:47a452a6f248 135 /**** End keypad handling ****/
peps 4:23472c2b246b 136
peps 5:47a452a6f248 137 //Convert milliseconds in human-readabe (mm:ss:cc) format
peps 2:bd0c735e81d6 138 measured_time human_read(int ms){
peps 2:bd0c735e81d6 139 measured_time read;
peps 2:bd0c735e81d6 140 div_t qr = div(ms,1000);
peps 2:bd0c735e81d6 141
peps 2:bd0c735e81d6 142 read.cents = qr.rem % 100;
peps 2:bd0c735e81d6 143
peps 2:bd0c735e81d6 144 qr = div(qr.quot,60);
peps 2:bd0c735e81d6 145 read.seconds = qr.rem;
peps 2:bd0c735e81d6 146
peps 2:bd0c735e81d6 147 qr = div(qr.quot,60);
peps 2:bd0c735e81d6 148 read.minutes = qr.rem;
peps 2:bd0c735e81d6 149
peps 2:bd0c735e81d6 150 return read;
peps 2:bd0c735e81d6 151 }
peps 2:bd0c735e81d6 152
peps 5:47a452a6f248 153 // Invoked when startGate triggered in SPEED mode.
peps 3:fd1353986910 154 // Start the timer or read the timer and store lap and best time
peps 3:fd1353986910 155 void measure_time() {
peps 5:47a452a6f248 156 isRunning = true;
peps 2:bd0c735e81d6 157 int read = t.read_ms();
peps 3:fd1353986910 158
peps 3:fd1353986910 159 if(lap == -1){
peps 2:bd0c735e81d6 160 t.start();
peps 2:bd0c735e81d6 161 lap++;
peps 2:bd0c735e81d6 162 }else{
peps 2:bd0c735e81d6 163 //Dabouncing per evitare problemi
peps 2:bd0c735e81d6 164 if(read - last_read > 1000){
peps 2:bd0c735e81d6 165
peps 3:fd1353986910 166 lap++;
peps 2:bd0c735e81d6 167 lap_time = read - last_read;
peps 3:fd1353986910 168 if (best_time < 0 || lap_time < best_time) {
peps 3:fd1353986910 169 best_time = lap_time;
peps 3:fd1353986910 170 best_lap = lap;
peps 3:fd1353986910 171 }
peps 2:bd0c735e81d6 172
peps 3:fd1353986910 173 if(lap >= NUM_LAP) {
peps 2:bd0c735e81d6 174 t.stop();
peps 2:bd0c735e81d6 175 }
peps 2:bd0c735e81d6 176
peps 2:bd0c735e81d6 177 last_read = read;
peps 2:bd0c735e81d6 178 }
peps 3:fd1353986910 179 }
peps 2:bd0c735e81d6 180 }
peps 2:bd0c735e81d6 181
peps 4:23472c2b246b 182 // Handler for loop when in SPEED mode
peps 2:bd0c735e81d6 183 void speedLoop() {
peps 2:bd0c735e81d6 184 int read = t.read_ms();
peps 2:bd0c735e81d6 185
peps 2:bd0c735e81d6 186 measured_time time = human_read(read);
peps 2:bd0c735e81d6 187
peps 2:bd0c735e81d6 188 lcd.locate(0,0);
peps 2:bd0c735e81d6 189 lcd.printf("Totale %02d:%02d:%02d",time.minutes,time.seconds,time.cents);
peps 4:23472c2b246b 190
peps 4:23472c2b246b 191 // Handle lap time display
peps 4:23472c2b246b 192 switch(lap) {
peps 4:23472c2b246b 193 // only display time if at least 1 lap completed
peps 4:23472c2b246b 194 case -1:
peps 4:23472c2b246b 195 case 0:
peps 4:23472c2b246b 196 break;
peps 4:23472c2b246b 197 // all laps completed - display best lap time
peps 4:23472c2b246b 198 case NUM_LAP + 1:
peps 4:23472c2b246b 199 time = human_read(best_time);
peps 4:23472c2b246b 200 lcd.locate(0,1);
peps 4:23472c2b246b 201 lcd.printf("Best %d %02d:%02d:%02d",best_lap,time.minutes,time.seconds,time.cents);
peps 5:47a452a6f248 202 isRunning = false;
peps 4:23472c2b246b 203 break;
peps 4:23472c2b246b 204 // Default - display last completed lap time
peps 4:23472c2b246b 205 // In case of last lap, wait 1 sec -- next time, best lap will be displayed
peps 4:23472c2b246b 206 default:
peps 4:23472c2b246b 207 time = human_read(lap_time);
peps 4:23472c2b246b 208 lcd.locate(0,1);
peps 4:23472c2b246b 209 lcd.printf("Giro %d %02d:%02d:%02d",lap,time.minutes,time.seconds,time.cents);
peps 4:23472c2b246b 210 if (lap == NUM_LAP) {
peps 4:23472c2b246b 211 wait(1);
peps 4:23472c2b246b 212 lap++;
peps 4:23472c2b246b 213 }
peps 4:23472c2b246b 214 break;
peps 2:bd0c735e81d6 215 }
peps 2:bd0c735e81d6 216 }
peps 2:bd0c735e81d6 217
peps 5:47a452a6f248 218 // Invoked when startGate triggered in LABIRYNTH mode.
peps 2:bd0c735e81d6 219 void start_time() {
peps 5:47a452a6f248 220 isRunning = true;
peps 2:bd0c735e81d6 221 lap = 0;
peps 2:bd0c735e81d6 222 t.start();
peps 2:bd0c735e81d6 223 }
peps 2:bd0c735e81d6 224
peps 2:bd0c735e81d6 225
peps 2:bd0c735e81d6 226
peps 2:bd0c735e81d6 227 void configMode() {
peps 2:bd0c735e81d6 228 switch(mode) {
peps 2:bd0c735e81d6 229
peps 2:bd0c735e81d6 230 case SPEED:
peps 2:bd0c735e81d6 231 default:
peps 4:23472c2b246b 232 gateStart.enable_irq();
peps 2:bd0c735e81d6 233 gateStart.rise(&measure_time);
peps 2:bd0c735e81d6 234 loopMethod = &speedLoop;
peps 3:fd1353986910 235 lcd.cls();
peps 3:fd1353986910 236 lcd.locate(0,0);
peps 3:fd1353986910 237 lcd.printf("Mode: SPEED ");
peps 3:fd1353986910 238 wait(1);
peps 3:fd1353986910 239 lcd.cls();
peps 2:bd0c735e81d6 240 break;
peps 2:bd0c735e81d6 241 }
peps 2:bd0c735e81d6 242 }
peps 2:bd0c735e81d6 243
peps 5:47a452a6f248 244 // Reset state and configure current mode
peps 5:47a452a6f248 245 // Invoked when RESET (#) key pressed on the keypad
peps 3:fd1353986910 246 void reset_measure(){
peps 5:47a452a6f248 247 isRunning = false;
peps 3:fd1353986910 248 t.stop();
peps 3:fd1353986910 249 t.reset();
peps 3:fd1353986910 250 lap = -1;
peps 3:fd1353986910 251 last_read = 0;
peps 3:fd1353986910 252 best_lap = 0;
peps 3:fd1353986910 253 best_time = -1;
peps 4:23472c2b246b 254 configMode();
peps 3:fd1353986910 255 }
peps 3:fd1353986910 256
peps 3:fd1353986910 257 void switchMode() {
peps 6:853da83fe5a9 258 mode = SPEED;
peps 3:fd1353986910 259 reset_measure();
peps 3:fd1353986910 260 }
peps 3:fd1353986910 261
Ghiri 0:1a92e4a37697 262 //------------------------------------------------------------
Ghiri 0:1a92e4a37697 263 //
Ghiri 0:1a92e4a37697 264 // Main body
Ghiri 0:1a92e4a37697 265 //
Ghiri 0:1a92e4a37697 266 //------------------------------------------------------------
Ghiri 0:1a92e4a37697 267 int main() {
peps 2:bd0c735e81d6 268 char key;
peps 4:23472c2b246b 269 keypadInit();
peps 4:23472c2b246b 270
peps 3:fd1353986910 271 user_button.fall(&switchMode);
peps 2:bd0c735e81d6 272
peps 2:bd0c735e81d6 273 gateStart.mode(PullDown);
peps 6:853da83fe5a9 274
peps 6:853da83fe5a9 275 IRLED.period(1.0/38000.0);
peps 6:853da83fe5a9 276 IRLED = 0.5;
peps 2:bd0c735e81d6 277
peps 4:23472c2b246b 278 reset_measure();
peps 2:bd0c735e81d6 279
peps 2:bd0c735e81d6 280 while(true) {
Ghiri 0:1a92e4a37697 281 heartbeat = !heartbeat;
peps 2:bd0c735e81d6 282 loopMethod();
peps 2:bd0c735e81d6 283 wait(0.1);
peps 5:47a452a6f248 284 key = getKey();
peps 4:23472c2b246b 285 if (key != '\0') {
peps 5:47a452a6f248 286 if (!isRunning) {
peps 5:47a452a6f248 287 if(key == 'A') {
peps 5:47a452a6f248 288 mode = SPEED;
peps 5:47a452a6f248 289 reset_measure();
peps 5:47a452a6f248 290 }
peps 5:47a452a6f248 291 }
peps 5:47a452a6f248 292 if(key == '#') {
peps 2:bd0c735e81d6 293 reset_measure();
peps 2:bd0c735e81d6 294 }
Ghiri 0:1a92e4a37697 295 }
Ghiri 0:1a92e4a37697 296 }
Ghiri 0:1a92e4a37697 297 }
Ghiri 0:1a92e4a37697 298