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

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

Revision:
0:2fa4b8d8fbd0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Dec 09 18:12:57 2014 +0000
@@ -0,0 +1,348 @@
+/*
+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);
+}
\ No newline at end of file