Versione modificata con sensore e IR LED a 38kHz.

Dependencies:   TextLCD keypadLib mbed

Fork of Chronometer_V2 by VR FabLab - RoboVal

main.cpp

Committer:
peps
Date:
2018-05-24
Revision:
6:853da83fe5a9
Parent:
5:47a452a6f248

File content as of revision 6:853da83fe5a9:

//##############################################################
//##
//## Event: RoboVal - Robot Race
//##
//## Chronometer double use
//##
//## Version 1.99A
//##
//## Hardware platform used: ST NUCLEO-F401RE
//##
//## Software IDE used: mbed online version
//##
//## Organizzation: Verona FabLab
//##
//## Date creation: 2018.01.01
//##
//## Software developpers: FdF,GV, AG
//##
//## Base on original version of by FdF
//##
//##############################################################

#include <stdlib.h>
#include "mbed.h"
#include "TextLCD.h"

// Default Number Lap
#define NUM_LAP 3

// Reference for Low/Min Voltage battery
#define VBAT_MIN 7.2

// Different function modes
// Switch among them using the USER button
// (waiting for the keypad to work properly)
enum modes {
    LABYRINTH,
    SPEED
} mode = SPEED;

// Human-readable time helper
typedef struct time_screen {
   int cents;
   int seconds;
   int minutes;
} measured_time;
 
// Heartbeat LED
DigitalOut heartbeat(LED1);

// read Voltage battery, analog pin used PC_3 (Pin 37 of Morpho layout)
//AnalogIn vbat(PC_3);
 
// User button pressure 
InterruptIn user_button(USER_BUTTON); 

// Gate connected to digital input PA_15
InterruptIn gateStart(PA_15);

// IR LED connected to PWM out PB_7
PwmOut IRLED(PB_7);

// LCD Display (RS, E, D4, D5, D6, D7);
TextLCD lcd(D2,D3,D4,D5,D6,D7); 

// Timer for the chrono function
Timer t;
 
// Number of laps
int lap = -1;

// Best lap
int best_lap = 0;

// Last time read
int last_read = 0;

// Last lap time
int lap_time = 0;

// Best lap time
int best_time = -1;

// Pointer to the loop function (depending on the selected mode)
void (*loopMethod)(void);

// Flag to avoid unwanted mode switch when running
bool isRunning = false;

/*** Keypad handling ****/
PinName rowPins[4] = { PA_13, PA_14, PC_2, PC_3 };
PinName colPins[4] = { PA_0, PA_1, PA_4, PB_0 };

DigitalOut* _rows[4];
DigitalIn* _cols[4];

// Define your own keypad values
char Keytable[] = { 
    '1', '2', '3', 'A', // r0
    '4', '5', '6', 'B', // r1
    '7', '8', '9', 'C', // r2
    '*', '0', '#', 'D'  // r3
  // c0   c1  c2   c3
};

int getKeyIndex() {
    int result = -1;
    for (int r = 0; r < 4; r++) {
        _rows[r]->write(1);
        for(int c = 0;c < 4 ;c++){
            DigitalIn *col = _cols[c];
            if(col->read() == 1) {
                result = r*4+c;
            }
        }
        _rows[r]->write(0);
    }
    return result;
}

char getKey() {
    int idx = getKeyIndex();
    return idx != -1 ? Keytable[idx] : '\0';
}

void keypadInit() {
    for(int i = 0;i < 4; i++){
        _rows[i] = new DigitalOut(rowPins[i]);
        _rows[i]->write(0);
    }
    for(int i = 0;i < 4; i++){
        _cols[i] = new DigitalIn(colPins[i],PullDown);
    }
}
/**** End keypad handling ****/

//Convert milliseconds in human-readabe (mm:ss:cc) format
measured_time human_read(int ms){
    measured_time read;
    div_t qr = div(ms,1000);
    
    read.cents = qr.rem % 100;
    
    qr = div(qr.quot,60);
    read.seconds = qr.rem;
    
    qr = div(qr.quot,60);
    read.minutes = qr.rem;
    
    return read;    
}

// Invoked when startGate triggered in SPEED mode.
// Start the timer or read the timer and store lap and best time
void measure_time() {
    isRunning = true;
    int read = t.read_ms();

    if(lap == -1){
        t.start();
        lap++;
    }else{
        //Dabouncing per evitare problemi
        if(read - last_read > 1000){
            
            lap++;
            lap_time = read - last_read;
            if (best_time < 0 || lap_time < best_time) {
                best_time = lap_time;
                best_lap = lap;
            }
            
            if(lap >= NUM_LAP) {
                t.stop();
            }
            
            last_read = read;     
        }
    }    
}

// Handler for loop when in SPEED mode
void speedLoop() {
    int read = t.read_ms(); 
    
    measured_time time = human_read(read);
    
    lcd.locate(0,0);
    lcd.printf("Totale %02d:%02d:%02d",time.minutes,time.seconds,time.cents);

    // Handle lap time display    
    switch(lap) {
        // only display time if at least 1 lap completed
        case -1:
        case 0:
            break;
        // all laps completed - display best lap time
        case NUM_LAP + 1:
            time = human_read(best_time);
            lcd.locate(0,1);
            lcd.printf("Best %d %02d:%02d:%02d",best_lap,time.minutes,time.seconds,time.cents);
            isRunning = false;
            break;
        // Default - display last completed lap time
        // In case of last lap, wait 1 sec -- next time, best lap will be displayed
        default:
            time = human_read(lap_time);
            lcd.locate(0,1);
            lcd.printf("Giro %d %02d:%02d:%02d",lap,time.minutes,time.seconds,time.cents);
            if (lap == NUM_LAP) {
                wait(1);
                lap++;
            }
            break;
    }
}

// Invoked when startGate triggered in LABIRYNTH mode.
void start_time() {
    isRunning = true;
    lap = 0;
    t.start();
}



void configMode() {
    switch(mode) {
        
        case SPEED:
        default:
            gateStart.enable_irq();
            gateStart.rise(&measure_time);
            loopMethod = &speedLoop;
            lcd.cls();
            lcd.locate(0,0);
            lcd.printf("Mode: SPEED     ");
            wait(1);
            lcd.cls();
            break;
    }
}

// Reset state and configure current mode
// Invoked when RESET (#) key pressed on the keypad
void reset_measure(){
    isRunning = false;
    t.stop();
    t.reset();
    lap = -1;
    last_read = 0;
    best_lap = 0;
    best_time = -1;
    configMode();
}

void switchMode() {
    mode = SPEED;
    reset_measure(); 
}

//------------------------------------------------------------ 
//
//       Main body
//
//------------------------------------------------------------
int main() {
    char key;
    keypadInit();

    user_button.fall(&switchMode);

    gateStart.mode(PullDown);

    IRLED.period(1.0/38000.0);
    IRLED = 0.5; 

    reset_measure();

    while(true) {
        heartbeat = !heartbeat;
        loopMethod();
        wait(0.1);
        key = getKey();
        if (key != '\0') {
            if (!isRunning) {
                if(key == 'A') {
                    mode = SPEED;
                    reset_measure();
                }
            }
            if(key == '#') {
                reset_measure();
            }
        }
    }
}