Deployment Version of the Project Test Drive Project application. It is a driver attention/awareness program that can be implemented in a vehicle to measure accuracy and attention times of the user. It alerts when the user goes below a threshold minimum using a speaker.
Dependencies: mbed mbed-rtos PinDetect
main.cpp
- Committer:
- kristyn1230
- Date:
- 2019-12-02
- Revision:
- 1:782903f734c2
- Parent:
- 0:c18a60fc6636
File content as of revision 1:782903f734c2:
#include "mbed.h" #include "rtos.h" #include "PinDetect.h" // Hardware devices RawSerial pc(USBTX, USBRX); DigitalOut myled(p21); DigitalOut myled2(p22); PinDetect pb(p26, PullDown); PinDetect pb2(p27, PullDown); PwmOut speaker(p25); // Constants and Timers Timer t1; Timer t2; const int FIFTEEN_SEC_DEL = 15000; const int MIN_DEL = 3000; const int WINDOW_SIZE = 5; const float INCORRECT_PENALTY = 3.00; const float WEIGHT = 1.25; // Pushbutton flags and inputs volatile float rxn_time = 0; volatile int pb1_asserted = 0; volatile int pb2_asserted = 0; volatile int pb1_chosen = 0; volatile int pb2_chosen = 0; // Reading windows, counters, and accuracy calculations volatile int total_count = 0; volatile int incorrect_count = 0; volatile int interval = 0; volatile bool timeout = false; volatile float baseline_avg = 0; volatile float current_avg = 0; volatile float readings[WINDOW_SIZE]; volatile int step = 0; volatile bool calc_baseline = false; void clear_timers() { t1.stop(); t1.reset(); t2.stop(); t2.reset(); } // Main LED control thread void flash(void const *args) { float timeout_time = 0; while(1){ if(t1.read()>0 || t2.read()>0){ clear_timers(); incorrect_count++; timeout = true; // Add in the timeout reading into the current average if (baseline_avg != 0) { // Convert to seconds readings[step] = timeout_time / 1000.0; step++; if (step == WINDOW_SIZE) { step = 0; } } } int choose = rand()%2; if (choose == 0) { pb1_chosen = 1; myled = 1; t1.start(); Thread::wait(2000); myled = 0; } else { pb2_chosen = 1; myled2 = 1; t2.start(); Thread::wait(2000); myled2 = 0; } float weight = rand() / (float) RAND_MAX; timeout_time = (int) (FIFTEEN_SEC_DEL * weight); Thread::wait(MIN_DEL + timeout_time); total_count++; interval++; } } // Pushbutton interrupts to read in a reaction time reading void button_ready(void) { pb1_asserted = 1; rxn_time = t1.read(); readings[step] = rxn_time; step++; if (step == WINDOW_SIZE) { calc_baseline = true; step = 0; } t1.stop(); t1.reset(); } void button_ready2(void) { pb2_asserted = 1; rxn_time = t2.read(); readings[step] = rxn_time; step++; if (step == WINDOW_SIZE) { calc_baseline = true; step = 0; } t2.stop(); t2.reset(); } // Alarm and sound control thread void sound(void const* args) { bool playOnce = true; while(1) { if (baseline_avg != 0 && playOnce) { speaker.period(1.0/1000.0); speaker = 0.5; Thread::wait(500); speaker = 0; playOnce = false; } if (baseline_avg != 0 && current_avg >= WEIGHT * baseline_avg) { speaker.period(1.0/100.0); speaker = 0.5; Thread::wait(250); speaker = 0; Thread::wait(250); speaker.period(1.0/200.0); speaker = 0.5; Thread::wait(250); speaker = 0; Thread::wait(250); } Thread::wait(100); } } int main() { // Messages to alert the user that the system is starting pc.printf("System starting in ..."); for(int i = 1; i <= 5; i++) { pc.printf("%d...", i); wait(1); } pc.printf("Go!\n\r"); // Pushbutton setup pb.attach_deasserted(&button_ready); pb.setSampleFrequency(); pb2.attach_deasserted(&button_ready2); pb2.setSampleFrequency(); // Start led and sound control threads Thread thread1(flash); Thread thread2(sound); float accuracy; pc.printf("Starting Training Phase\n\r"); // Continuously monitor the user's reaction 10x a second while(1) { if (calc_baseline && baseline_avg == 0) { float sum = 0; for (int j = 0; j < WINDOW_SIZE; j++) sum += readings[j]; baseline_avg = sum / WINDOW_SIZE; pc.printf("Training Complete -- Baseline Average Established\n\r"); } else { float sum = 0; for (int j = 0; j < WINDOW_SIZE; j++) sum += readings[j]; current_avg = sum / WINDOW_SIZE; } if (pb1_chosen && pb1_asserted == 1 && rxn_time != 0) { pb1_asserted = 0; pc.printf("Reaction Time: %fs Baseline Reaction Time: %fs Average Reaction Time: %fs \n\r", rxn_time, baseline_avg, current_avg); pb1_chosen = 0; clear_timers(); } else if (pb2_chosen && pb2_asserted == 1 && rxn_time != 0) { pb2_asserted = 0; pc.printf("Reaction Time: %fs Baseline Reaction Time: %fs Average Reaction Time: %fs \n\r", rxn_time, baseline_avg, current_avg); pb2_chosen = 0; clear_timers(); } else if(pb1_asserted || pb2_asserted) { pc.printf("Wrong Button Press\n\r"); pb1_asserted = 0; pb2_asserted = 0; // Penalize for the wrong button press into the current average if (baseline_avg != 0) { readings[step] = INCORRECT_PENALTY; step++; if (step == WINDOW_SIZE) { step = 0; } } clear_timers(); incorrect_count++; } else if (timeout) { pc.printf("Button timeout\n\r"); timeout = false; } if((interval%5==0)&&(interval!=0)){ accuracy = ((float) total_count - incorrect_count)/total_count; accuracy = accuracy*100; pc.printf("--- TotalCount: %d IncorrectCount: %d Current Accuracy: %.2f%% ---\n\r", total_count, incorrect_count, accuracy); pc.printf("\n\r"); interval = 0; } Thread::wait(100); } }