Ferry Musters / Mbed 2 deprecated Clap_Unit

Dependencies:   mbed

main.cpp

Committer:
Ferryy
Date:
2015-07-03
Revision:
2:6b15e2363f00
Parent:
1:df9d6f3886f6

File content as of revision 2:6b15e2363f00:

//**************************************************//
//                   Clap_unit.cpp                  //
//**************************************************//
// Application to switch a light or other output    //
// whenever the correct handclapping pattern is     //
// detected. An external handclap detection board   //
// is used (works as a SR-latch).                   //
//
// The programmed pattern can be demonstrated by    //
// using SW3. An clapping pattern can be            //
// programmed by pressing switch SW2.               //
//                                                  //
// Board: FRDM-K64F (using mbed IDE)                //
// Ferry Musters & Thom Grasso - 26/06/2015         //
// Electrical Engineering - Hogeschool Utrecht      //
//**************************************************//


#include "mbed.h"

void BlinkLed(char color, float time);

//-------------------[ Parameters ]------------------
const int timeout_ms = 2000; //
const int allowedError = 200; //Allowed time difference between clap and set clap pattern

int clapPattern[100] = {0, 300, 900}; //initial clap pattern (in ms). Can be changed by user
int clapPatternSize = 3; //initial clap pattern size (to indicate which portion of the array is used)
//-------------------[ Variables ]-------------------
DigitalOut led_red(LED_RED);
DigitalOut led_blue(LED_BLUE);
DigitalOut led_green(LED_GREEN);
InterruptIn learningSwitch(SW2);
InterruptIn demoSwitch(SW3);

PwmOut lamp(A5);


DigitalOut boardGnd(D4); //pins
DigitalOut boardVcc(D5);
//InterruptIn boardClap(SW2);
InterruptIn boardClap(D6);
DigitalOut boardReset(D7);

Serial output(USBTX, USBRX);
Timer timer; //global timer
int clapData[100]; //buffer to save clap times
int currentClap = 0; //counter to keep track of current clap in buffer
int printedClap = 0; //counter to keep track of printf'ed claps
bool learning = false; //flag to indicate if the system is learning a new clap pattern

//-------------------[ Interrupts ]-------------------
void ClapDetected(void) //interrupt function for boardClap pin
{
    clapData[currentClap++] = timer.read_ms(); //save clap time and increment counter
    boardReset = 1; //reset the clap detecter board with a reset pulse
    BlinkLed('b',0.05); //wait to show led and also avoid handclap 'bounces'
    boardReset = 0;
}

void DemoPattern(void)  //interrupt function for userSwitch pin. Demonstrates
{
    const float demoBlinkLength = 0.05; //led blink length in ms
    wait(0.3);
    BlinkLed('r', demoBlinkLength); //blink the first clap
    for(int i = 1; i < clapPatternSize; i++) { //blink the second and next claps
        float delaytime = (clapPattern[i]-clapPattern[i-1])/1000.0 - demoBlinkLength;
        output.printf("Blinking clap %d for %.2f second\r\n", i, delaytime);
        //output.printf("clapPattern[i] = %d\r\n", clapPattern[i]);
        //output.printf("clapPattern[i-1] = %d\r\n", clapPattern[i-1]);
        wait(delaytime);
        BlinkLed('r', demoBlinkLength);
    }
}

void StartLearning(void) //when switch is pressed, system goes into learning mode.
{
    output.printf("--- Starting Learning Mode! Enter clap pattern");
    led_red = 0;
    learning = true;
}

//-------------------[ Functions ]-------------------
void Initialize()
{
    timer.start();
    boardVcc = 1;
    boardGnd = 0;
    boardReset = 0;
    led_red = 1;
    led_green = 1;
    led_blue = 1;
    lamp.period_ms(1);
    boardClap.rise(&ClapDetected);
    demoSwitch.rise(&DemoPattern);
    learningSwitch.rise(&StartLearning);
}

void PrintClaps()
{
    if(printedClap < currentClap) { //if the last clap isn't printed yet
        output.printf("* Detected clap %d: %d\r\n", ++printedClap, clapData[printedClap]); //debug the clap
    }
}

bool CheckTimeout() //check if clap timeout occurs(when last clap is more then x seconds ago)
{
    return ((currentClap > 0) && (timer.read_ms() > (clapData[currentClap-1] + timeout_ms)));
}

void SavePattern()
{
    for(int i = 0; i < currentClap; i++) clapPattern[i] = clapData[i]; //save clapped buffer as new pattern
    clapPatternSize = currentClap; //save pattern size (amount of claps)   
    led_red = 1; //turn off red 'recording' LED
}

bool CheckClapPattern() //check if clapped pattern matches
{
    if(clapPatternSize != currentClap) return false; //if nr of claps is not equal return mismatch

    bool mismatch = false; //variable to keep track if any mismatch is found
    
    for(int i = 1; i < clapPatternSize; i++) { //check for each clap (each time interval between claps
        int realClapDelta = clapData[i] - clapData[i-1]; //measured clap pattern
        int requiredClapDelta = clapPattern[i] - clapPattern[i-1]; //set clap pattern

        int maxClapDelta = requiredClapDelta + allowedError;
        int minClapDelta = requiredClapDelta - allowedError;

        if((realClapDelta < minClapDelta) || (realClapDelta > maxClapDelta)) {
            mismatch = true;
            break;
        }
    }
    return !mismatch; //return if clap pattern matches (true) or not (false)
}

void ResetMeasurement() //reset counters to start new measurement
{
    output.printf("--- Timeout. %d claps and took %.2fs in total ---\r\n", currentClap, (clapData[currentClap-1] - clapData[0])/1000.0);
    currentClap = 0; //reset clap counters
    printedClap = 0;
}

void BlinkLed(char color, float time) //Blink led ('r', 'g' or 'b'. 'p'urple, 'y'ellow, 'c'yan or 'w'hite) for given time (float in sec)
{
    if(color=='r' || color=='w' || color=='y' || color=='p') led_red = 0;
    if(color=='g' || color=='w' || color=='y' || color=='c') led_green = 0;
    if(color=='b' || color=='w' || color=='p' || color=='c') led_blue = 0;
    wait(time);
    if(color=='r' || color=='w' || color=='y' || color=='p') led_red = 1;
    if(color=='g' || color=='w' || color=='y' || color=='c') led_green = 1;
    if(color=='b' || color=='w' || color=='p' || color=='c') led_blue = 1;
}


//-------------------[ Main ]-------------------
int main()
{
    Initialize(); //initialize all required components and interrupts(!)

    while (true) {
        PrintClaps(); //update the serial terminal to print all detected claps

        if(learning) { //learning state can be enabled by interrupt by switch on devboard
            if( CheckTimeout() ) { // if timeout happened -> clap pattern ended
                SavePattern(); //save clapped pattern as the new reference pattern
                learning = false; //disable learning state
            }
        } else {
            bool clapMatches = CheckClapPattern(); //check if claps match set pattern
            if(clapMatches) {
                wait(0.2); //give a delay to make UI feel better
                lamp = 1 - lamp; //switch lamp on or off
                BlinkLed('g', 0.5); //pattern match -> blink green
                ResetMeasurement();
            } else if( CheckTimeout() ) { //give the user some time to enter additional claps, else a timeout will happen.
                BlinkLed('r', 0.5); //pattern mismatch -> blink red
                ResetMeasurement();
            }
        }
    }
}