Code for Mbed Dashboard project. http://developer.mbed.org/users/julieefreeman/notebook/mbed-dashboard---obdii/

Dependencies:   4DGL-uLCD-SE SDFileSystem mbed-rtos mbed

main.cpp

Committer:
julieefreeman
Date:
2014-12-09
Revision:
0:2fa4b8d8fbd0

File content as of revision 0:2fa4b8d8fbd0:

/*
mbed Dashboard trip computer
December 2014
********************************************************************************
WARNING: Use at your own risk, sadly this software comes with no guarantees.
This software is provided 'free' and in good faith, but the author does not
accept liability for any damage arising from its use.
********************************************************************************
*/
 
#include "mbed.h"
#include "ecu_reader.h"
#include "globals.h"
#include "rtos.h"
#include "SDFileSystem.h"

Mutex stdio_mutex; 
ecu_reader obdii1(CANSPEED_125);    //supports different CAN speeds
ecu_reader obdii2(CANSPEED_250);
ecu_reader obdii3(CANSPEED_500);
InterruptIn switch_reading(p8);
SDFileSystem sd(p5, p6, p7, p12, "sd");
DigitalOut myled4(LED4);
DigitalOut myled3(LED3);

int flag; //indicates which reading to get from vehicle
int change; //signifies that the system is switching readings
char temp_buffer[20];   //buffers for readings from vehicle
char rpm_buffer[20];
char speed_buffer[20];
char time_buff[32];
char buffer[20];
float dial_len;
int ui_temp, ui_rpm;
float ui_speed;
int dist_init;
float dist;
time_t seconds;
int testing_temp; //not connected to car
int testing_rpm; //not connected to car
int testing_speed; 

void display_coolant_temp();
void display_rpm();
void draw_tachometer();
void draw_thermometer();
void display_speed();
void draw_speedometer();
void display_trip();
 
void pb_hit_interrupt (void) {
    myled4 = 1;
    flag = flag+1;
    if (flag>3) {
        flag = 0;
        ui_temp = -1;
    }
    else if (flag == 1)
        ui_rpm = -1;
    else if (flag == 2)
        ui_speed = -1;
    wait(0.5);
    myled4 = 0;
    change = 1;
}
void testingThread(void const *args) {  // run this thread and set main OBD request conditions to 0 to test UI
    ui_temp = -1;
    ui_rpm = -1;
    testing_temp = 100;
    testing_rpm = 0;
    dist_init = 0;
    testing_speed = 0;
    while(1){
        // --- TESTING ONLY - WITHOUT CAR --- 
        sprintf(temp_buffer,"%d",testing_temp);
        sprintf(rpm_buffer,"%d",testing_rpm);
        sprintf(speed_buffer,"%d", testing_speed);
        dist += 0.1;
        testing_temp -= 1;
        testing_rpm += 100;
        testing_speed +=5;
        if (testing_temp<5) {
            testing_temp = 100;
        }
        if (testing_rpm>5000) {
            testing_rpm = 900;
        }
        // --- TESTING ONLY - WITHOUT CAR ---
        Thread::wait(1000);
    }
}

void sdThread(void const *args) {
    dist = -1;
    dist_init = -1;
    set_time(0);
    char file[35];
    char buffer[32];
    char hours[5];
    char minutes[5];
    float hrs = 0;
    FILE *fp;

    mkdir("/sd/tripStats",0777);
    sprintf(file, "/sd/tripStats/log.txt");
    while (dist_init == -1){ //
        stdio_mutex.lock();
        if(obdii3.request(DIST_SINCE_CLR, buffer) == 1){
             dist_init = atoi(buffer);
        }
        stdio_mutex.unlock();
    }

    while (1){
       fp = fopen(file, "w");
       myled3 = 1;
       seconds = time(NULL);
       strftime(time_buff, 32, "%R:%S", localtime(&seconds));
       strftime(hours, 5, "%H", localtime(&seconds));
       strftime(minutes, 5, "%M", localtime(&seconds));
       hrs = atoi(hours) + ((float)atoi(minutes))/60;
        if(fp == NULL) {
            error("Could not open file for write\n");
        }
        stdio_mutex.lock();
        if(obdii3.request(DIST_SINCE_CLR, buffer) == 1){
            dist = ((float)atoi(buffer)-dist_init)*0.62;
        }
        stdio_mutex.unlock();
        fprintf(fp, "Time since mbed start: %s\n\n", time_buff);
        fprintf(fp, "Distance Traveled: %2.2f miles\n", dist);
        fprintf(fp, "Average Speed: %2.2f mph\n", dist/hrs);
        fclose(fp);
        myled3 = 0;
        Thread::wait(30000);  //write to SD card every 30 seconds
    }
}
 
int main() {
    ui_temp = -1;   //initialize default values
    ui_rpm = -1;
    ui_speed = -1;
    change = 0;
    flag = 0;
    dial_len = 60.0;
    lcd.cls();
    lcd.baudrate(3000000);
    switch_reading.mode(PullUp);
    wait(0.2);
    switch_reading.fall(&pb_hit_interrupt);
    Thread t2(sdThread);
    //Thread test(testingThread); //run this thread and change OBD request conditions to 0 to test UI
    
    while (1) {  //main thread
        if (change == 0) { //update LCD only when not in process of switching screens
            switch (flag){ 
                case 0: //engine coolant temperature
                    if(obdii3.request(ENGINE_COOLANT_TEMP, temp_buffer) == 1){  //set to 1 for car, 0 for testing UI
                        stdio_mutex.lock();
                        display_coolant_temp();
                        stdio_mutex.unlock();
                    }
                    else { 
                        can2.reset();
                        wait(0.5);
                    }                    
                    break;
                case 1: //engine rpm 
                    if (obdii3.request(ENGINE_RPM, rpm_buffer) == 1){  //set to 1 for car, 0 for testing UI
                        stdio_mutex.lock();
                        display_rpm();
                        stdio_mutex.unlock();
                    }
                    else { 
                        can2.reset();   
                        wait(0.5);
                    }
                    break;
                case 2: //vehicle speed
                    if (obdii3.request(VEHICLE_SPEED, speed_buffer) == 1){  //set to 1 for car, 0 for testing UI
                        stdio_mutex.lock();
                        display_speed();
                        stdio_mutex.unlock();
                    }
                    else { 
                        can2.reset();   
                        wait(0.5);
                    }
                    break;
                case 3: //distance since codes last cleared
                    if(obdii3.request(DIST_SINCE_CLR, buffer) == 1){
                        dist = ((float)atoi(buffer)-(float)dist_init)*0.62;
                        stdio_mutex.lock();
                        display_trip();
                        stdio_mutex.unlock();
                    }
                    else { 
                            stdio_mutex.lock();
                            display_trip();
                            stdio_mutex.unlock();
                        can2.reset();   
                        wait(0.5);
                    }
                    break;
            }
        }
        else {
            lcd.cls();
            change = 0;
        }
    }
}

void display_coolant_temp(){ //displays temperature
    float farenheit = atoi(temp_buffer) * 9/5 +32;
    draw_thermometer();
    lcd.color(0x909090);
    lcd.text_width(2); 
    lcd.text_height(2);
    lcd.locate(1,0);
    lcd.printf("%s\n\r", "COOLANT\n  TEMP.");
    lcd.color(0x66CCFF);
    lcd.locate(0,3);
    lcd.printf("%3.0f \n\r", farenheit);
    lcd.locate(0,4);
    lcd.printf("oF\n\r");
}

void draw_thermometer(){ //draws temperature animation
    lcd.rectangle(73,47,119,128,0xFFFFFF);
    int new_temp = atoi(temp_buffer);
    int height = 128-ceil((float)new_temp*.8);

    if (new_temp > 100 && ui_temp!=new_temp) {          //red 
        lcd.filled_rectangle(74,48,118,67,0xFF0000);
    }
    else if (new_temp > 75 && ui_temp!=new_temp) {
        if (ui_temp>new_temp) lcd.filled_rectangle(74,48,118,height,0x000000);
        lcd.filled_rectangle(74,height,118,67,0xFF0000);
    }
    else lcd.filled_rectangle(74,48,118,67,0x000000);
    if (new_temp > 75 && ui_temp!=new_temp) {           //dark orange 
        lcd.filled_rectangle(74,68,118,87,0xFF4719);
    }
    else if (new_temp > 50 && ui_temp!=new_temp) {
        if (ui_temp>new_temp) lcd.filled_rectangle(74,68,118,height,0x000000);
        lcd.filled_rectangle(74,height,118,87,0xFF4719);
    }
    else lcd.filled_rectangle(74,68,118,87,0x000000);
    if (new_temp > 50 && ui_temp!=new_temp) {           //orange
        lcd.filled_rectangle(74,88,118,107,0xFF9933);
    }
    else if (new_temp > 25 && ui_temp!=new_temp) {
        if (ui_temp>new_temp) lcd.filled_rectangle(74,88,118,height,0x000000);
        lcd.filled_rectangle(74,height,118,107,0xFF9933);
    }
    else lcd.filled_rectangle(74,88,118,107,0x000000);
    if (new_temp > 25 && ui_temp!=new_temp) {           //yellow
        lcd.filled_rectangle(74,108,118,128,0xFFFF99);
    }
    else if (new_temp > 0 && ui_temp!=new_temp) {
        if (ui_temp>new_temp) lcd.filled_rectangle(74,108,118,height,0x000000);
        lcd.filled_rectangle(74,height,118,128,0xFFFF99);
    }
    else lcd.filled_rectangle(74,108,118,128,0x000000);
    ui_temp = new_temp;
}

void display_rpm(){ //displays rpm
    draw_tachometer();
    lcd.color(0x909090);
    lcd.text_width(2); 
    lcd.text_height(2);
    lcd.locate(1,0);
    lcd.printf("%s\n\r", "ENG RPM");
    lcd.color(0x66CCFF);
    lcd.text_width(3);
    lcd.text_height(3);
    lcd.locate(1,1);
    lcd.printf("%s \n\r", rpm_buffer);
}

void draw_tachometer(){ //draws rpm gauge
    lcd.circle(64,120,60,0xFFFFFF);   
    int new_rpm = atoi(rpm_buffer);
    int x = int(cos(float(new_rpm)*0.00041887902)*dial_len);
    int y = int(sin(float(new_rpm)*0.00041887902)*dial_len);
    if (ui_rpm!=new_rpm && ui_rpm!=-1) {
        int old_x = int(cos(float(ui_rpm)*0.00041887902)*dial_len);
        int old_y = int(sin(float(ui_rpm)*0.00041887902)*dial_len);
        lcd.line(64-old_x,120-old_y,64,120,0x000000);
    }
    lcd.line(64-x,120-y,64,120,0xFF8C00);
    ui_rpm = new_rpm;
}

void display_speed() { //displays speed
    draw_speedometer();
    lcd.color(0x909090);
    lcd.text_width(2); 
    lcd.text_height(2);
    lcd.locate(1,0);
    lcd.printf("%s\n\r", "SPEED");
    lcd.color(0x66CCFF);
    lcd.text_width(3);
    lcd.text_height(3);
    lcd.locate(1,1);
    lcd.printf("%3.0f \n\r", (((float)atoi(speed_buffer))*0.62));
}

void draw_speedometer(){ //draws gauge for speed
    lcd.circle(64,120,60,0xFFFFFF);   
    float new_speed = atoi(speed_buffer) * 0.62;
    int x = int(cos(new_speed*0.0314159265)*dial_len);
    int y = int(sin(new_speed*0.0314159265)*dial_len);
    if (ui_speed!=new_speed && ui_speed!=-1) {
        int old_x = int(cos(ui_speed*0.0314159265)*dial_len);
        int old_y = int(sin(ui_speed*0.0314159265)*dial_len);
        lcd.line(64-old_x,120-old_y,64,120,0x000000);
    }
    lcd.line(64-x,120-y,64,120,0xFF8C00);
    ui_speed = new_speed;
}

void display_trip() { //displays data being output to SD card
    lcd.color(0x909090);
    lcd.text_width(2); 
    lcd.text_height(2);
    lcd.locate(0,0);
    lcd.printf("%s\n\r", "TOTALTIME");
    lcd.color(0x66CCFF);
    lcd.text_width(3);
    lcd.text_height(3);
    lcd.locate(0,1);
    strftime(time_buff, 32, "%R", localtime(&seconds));
    lcd.printf("%s \n\r", time_buff);
    
    lcd.color(0x909090);
    lcd.text_width(2); 
    lcd.text_height(2);
    lcd.locate(0,4);
    lcd.printf("%s\n\r", "DISTANCE");
    lcd.color(0x66CCFF);
    lcd.text_width(3);
    lcd.text_height(3);
    lcd.locate(0,4);
    lcd.printf("%3.1f \n\r", dist);
}