This is car control simulation by using Mbed controller and real time operating system.

Dependencies:   MCP23017 Servo WattBob_TextLCD mbed-rtos mbed

Fork of Ass3 by Muaiyd Al-Zandi

CAR.cpp

Committer:
muaiyd
Date:
2014-05-06
Revision:
11:7f2414ecb7ee
Parent:
10:2522e3878e1c
Child:
12:8eb2c1cccee6

File content as of revision 11:7f2414ecb7ee:

#include "CAR.h"

//Define semaphores to manage accessing the viriables
Semaphore CAR_MAIL_SEM(1);
Semaphore INPUT_SEM(3);
Semaphore SWITCH_SEM(2);
Semaphore AVR_SPEED_SEM(2);
/* Two counter the first is counting the number of element that
    was sended to the MAIL. The another is to count the number of
    element that dumped to a file */ 
uint32_t Element_Counter_W = 0;
uint32_t Element_Counter_R = 0;
//  Initialise a mail with 100 element
static Mail<CAR_MAIL, 100> mail_box;

bool LSide_Indicator_Value;
bool RSide_Indicator_Value;
 // Create the local filesystem under the name "local"
LocalFileSystem local("local");              

CAR::CAR(){
    Port.write_bit(1,BL_BIT); 
    // Open "out.txt" on the local file system for writing
    FILE *fp = fopen("/local/Car_Values.csv", "w");  
    fprintf(fp, "Counter,Average_Speed,Accelerometer_Value,Brake_Value\r\n");
    fclose(fp);      
}
// This two functions are save and read the ODO value in a register
//  in order to safe it when the mbed restart
void CAR::SAVE_ODO(float value) {
    LPC_RTC->GPREG0 = *((uint32_t*)&value);
}
float CAR::GET_ODO() {
    return *((float*)&(LPC_RTC->GPREG0));
}

/*   Read the accelerometer and brake value every 100 mSec and calculate the speed.
     Also save them in variabls.The speed is saved in an array of three element
     so the past three values of speed is saved. */
void CAR::Accelero_Brake_Read(void const *args){
    while (true) {
        INPUT_SEM.wait();
        Accelerometer_Value = Accelerometer.read();
        Brake_Value =  Brake.read();
        EngineStat = EngineSwitch;
        Speed[Counter] = Accelerometer_Value * MaxSpeed * (1 - Brake_Value) * EngineStat ;
        Counter++;
        if(Counter > 2) Counter = 0;
        INPUT_SEM.release();
        Thread::wait(100);
    }
}

// Average filter the speed every 200 mSec
void CAR::Average_Speed_Measure(void const *args) {
    while (true) {
        INPUT_SEM.wait();
        AVR_SPEED_SEM.wait();
        Average_Speed = ( Speed[0] + Speed[1] + Speed[2] )/3 ;
        INPUT_SEM.release();
        AVR_SPEED_SEM.release();
        Thread::wait(200);
    }
}

// Update the servo every 1 Sec with the average speed value
void CAR::Average_Speed_Show(void const *args){
    while(1){
        AVR_SPEED_SEM.wait();
        SpeedShow_Servo = 1.0 - (float)Average_Speed / (float)MaxSpeed ;
        AVR_SPEED_SEM.release();
        Thread::wait(1000);
    }
}

// Check the average speed if it over 70 MPH every 2Sec
void CAR::OverSpeed(void const *args){
    while(true){
    AVR_SPEED_SEM.wait();
    if(Average_Speed > 70)
            IsOverSpeed = 1;
            
        else
            IsOverSpeed = 0;
    AVR_SPEED_SEM.release();        
    Thread::wait(2000);
    }       
}
/*  To task in this function becuase boath are repeted every 0.5 Sec
    1- Update the ODOmeter
    2- Read the indecator swetches */
void CAR::Odo_Show_Indicator_Switch_Read(void const *args){
    while(true){
        LCD.locate(0,0);
        AVR_SPEED_SEM.wait();
        Odometer_Value = GET_ODO() + Average_Speed / 7200.0 ;
        SAVE_ODO(Odometer_Value);
        LCD.printf("Speed %3D MPH",Average_Speed);
        LCD.locate(1,0);
        LCD.printf("ODO %4.2f M",GET_ODO());
        AVR_SPEED_SEM.release();
        
        SWITCH_SEM.wait();
        LSide_Indicator_Value = LSide_Indicator_Switch;
        RSide_Indicator_Value = RSide_Indicator_Switch;
        SWITCH_SEM.release();
        
        Thread::wait(500);
    }
}

/*  Send the values of the Brake, Accelerometer, and Speed to
    an mail queue every 5 Sec. */
void CAR::SEND_CAR_VALUES (void const *args) {  
    while (true) {
        CAR_MAIL *mail = mail_box.alloc();
        CAR_MAIL_SEM.wait();
        
        AVR_SPEED_SEM.wait();
        mail->Mail_Average_Speed = Average_Speed; 
        AVR_SPEED_SEM.release();
        
        INPUT_SEM.wait();
        mail->Mail_Accelerometer_Value = Accelerometer_Value;
        mail->Mail_Brake_Value = Brake_Value;
        mail->Counter = Element_Counter_W ;
        mail_box.put(mail);
        Element_Counter_W++;
        CAR_MAIL_SEM.release();
        INPUT_SEM.release();
        
        Thread::wait(5000);              
    }
}

//Saving the memory pool content on the serial port
void CAR::DUMP_CAR_VALUES_En (void const *args) {
    while (true) {
        CAR_MAIL_SEM.wait();
        while (Element_Counter_W > Element_Counter_R)
            DUMP_CAR_VALUES();
            
        CAR_MAIL_SEM.release();
        Thread::wait(20000);
    }
}
void CAR::DUMP_CAR_VALUES () {
    osEvent evt = mail_box.get(10);
    CAR_MAIL *mail = (CAR_MAIL*)evt.value.p;
    if (evt.status == osEventMail) {            
            FILE *fp = fopen("/local/Car_Values.csv", "a");  // Open "out.txt" on the local file system for writing
            fprintf(fp,"%i ,"   , mail->Counter);
            fprintf(fp,"%i ,", mail->Mail_Average_Speed);
            fprintf(fp,"%.3f ,"     , mail->Mail_Accelerometer_Value);
            fprintf(fp,"%.3f ", mail->Mail_Brake_Value);
            fprintf(fp,"\r\n");
            fclose(fp); 
            mail_box.free(mail);
            Element_Counter_R++;        
    }
}

// Flashing the indecator light
void CAR::Side_Light_Flash(void const *args){
    while(true){
        SWITCH_SEM.wait();
        // If both side are enabled
        if((LSide_Indicator_Value == 1) && (RSide_Indicator_Value == 1) ){
            L_Side_Indicator = L_Side_Indicator ^ 1;
            R_Side_Indicator = L_Side_Indicator;
        }
        //If just one side enabled
        else if(RSide_Indicator_Value == 1){
            R_Side_Indicator = R_Side_Indicator ^ 1;
            L_Side_Indicator = 0;
        }
        else if(LSide_Indicator_Value == 1){
            L_Side_Indicator = L_Side_Indicator ^ 1;
            R_Side_Indicator = 0;
        }
        //Neither are enabled
        else{
            L_Side_Indicator = 0;
            R_Side_Indicator = 0 ;
        }
        SWITCH_SEM.release();
        Thread::wait(1000);
    }
}
// Check the side light swetches and turn on or off the light
void CAR::Side_Light(void const *args){
    while(true){
        if(LSide_Light_Switch){
            L_Side_Light = 1;
        }
        else{
            L_Side_Light = 0;
        }
        if(RSide_Light_Switch){
            R_Side_Light = 1;
        }
        else{
            R_Side_Light = 0;
        }
        Thread::wait(1000);
    }
}