All the commit done for assignment 3

Dependencies:   MCP23017 Servo WattBob_TextLCD mbed mbed-rtos

main.cpp

Committer:
xouf2114
Date:
2017-04-04
Revision:
5:72f209412e34
Parent:
4:9f5ebb8d85ba
Child:
6:b6053cb6355e

File content as of revision 5:72f209412e34:

/*****************************************************************************************************
Assigment 3 Embedded Software
                                                
                                                 
This Software is a Car Control Software as no Real Car can be connected it Simulates a car as well.
For the Display it uses an LCD Screen
For the Speedometer it uses a Servo
The Emulation and Synchronisation is implemented using TimerThreads and Semaphores
for the reason of existing thread limits, conventional timers are helping to slicing timeslots

@author Xavier Gouesnard
H00258183
******************************************************************************************************/
#include "mbed.h"
#include "MCP23017.h"                                               // include 16-bit parallel I/O header file
#include "WattBob_TextLCD.h"                                        // include 2*16 character display header file
#include "rtos.h"
#include "Servo.h"
#include <deque>

//#define OS_TIMERCBQS 20 // define a new number of timers we want +1 timer!
//#define OS_TASKCNT 20 // maximum threads

MCP23017            *par_port;                                      // pointer to 16-bit parallel I/O object
WattBob_TextLCD     *lcd;                                           // pointer to 2*16 chacater LCD object
Serial              serpc(USBTX, USBRX);                            // serial usb connection tx, rx
AnalogIn AinBreak(p18);                                             // Port for the Break Value
AnalogIn AinAccel(p19);                                             // Port for the Accelerator Value
DigitalIn DinSwitchEngine(p11);                                     // Port for the Engine Switch
DigitalIn DinSwitchLight(p12);                                      // Port for the Light Switch
DigitalIn DinSwitchRindic(p13);                                     // Port for the Right Indicator
DigitalIn DinSwitchLindic(p15);                                     // Port for the Left Indicator
Servo Odometer(p25); 
DigitalOut LEDSpeedWarning(p8);
DigitalOut DoutLEDLight(LED1);                                      // Output Port for LED1
DigitalOut DoutLEDLeft(LED2);                                       // Output Port for LED2
DigitalOut DoutLEDRight(LED3);                                      // Output Port for LED3
DigitalOut DoutLEDEngine(LED4);                                     // Output Port for LED4
void Timer1_void(void const *args);                                 // Timer 1
void Timer2_void(void const *args);                                 // Timer 2
void Timer3_void(void const *args);                                 // Timer 3


// Task Functions
void Task_1_break_accelerate();
void Task_2_read_show_engine_state();
void Task_3_show_odometer();
void Task_4_speed_warning();
void Task_5_update_odometer();
void Task_6_fill_mail_queue();
void Task_7_dump_mail_to_serial();
void Task_8_read_single_side_light();
void Task_9_read_indicators();
void Task_10_calc_avg_speed();
void Task_11_emulate_car();

// Init Variables
int Convert_Hz_to_Ms(double Hz);
float accerlator(0);
float speed(0);
float avgSpeed(0);
float brake(0);
float dist(0);
bool engine(0);
bool indicator_L(1);
bool indicator_R(1);
bool sw_timer1(0);
bool sw_timer11(0);
bool sw_timer2(0);
bool sw_timer21(0);
int sw_timer3(4);                                                   // sw_timer3 initalize with a first run

std::deque<float> AvgSpeedDB;                                       // used for storing the average speed
Semaphore SemAvgSpeedDB(1);                                         // declare used Semaphores
Semaphore SemAvgSpeed(1);
Semaphore SemSpeed(1);
Semaphore SemBreak_Accelerate(1);
Semaphore SemDistance(1);
Semaphore SemEngine(1);
Semaphore SemMailCnT(1);

typedef struct {
float    speed;
float    accel;
float brake;
} mail_t;
int mailcounter(0);                                                 // counts the mails in the queue
Mail<mail_t, 100> mail_box;                                         // the mail queue has a maximum size of 100 mails

int main()
{
// 10.0 Hz = 00100 ms
// 2.0  Hz = 00500 ms
// 5.0  Hz = 00200 ms
// 1.0  Hz = 01000 ms
// 0.5  Hz = 02000 ms
// 0.2  Hz = 05000 ms
// 0.05 Hz = 20000 ms




    serpc.baud(19200);                                              // setup the bautrate
    serpc.printf("Init Software\r\n");
    par_port = new MCP23017(p9, p10, 0x40);                         // initialise 16-bit I/O chip (0x40 = 64)
    lcd = new WattBob_TextLCD(par_port);                            // initialise 2*26 char display
    par_port->write_bit(1,BL_BIT);                                  // turn LCD backlight ON
    lcd->cls();                                                     // clear display
    lcd->locate(0,0);                                               // set cursor to location (0,0) - top left corner
    RtosTimer Timer1(Timer1_void,osTimerPeriodic,(void *)NULL);     // create the necesarry timers to overcome a thread issue (max threads)
    Timer1.start(Convert_Hz_to_Ms(20.0));
    RtosTimer Timer2(Timer2_void,osTimerPeriodic,(void *)NULL);
    Timer2.start(Convert_Hz_to_Ms(2.0));
    RtosTimer Timer3(Timer3_void,osTimerPeriodic,(void *)NULL);
    Timer3.start(Convert_Hz_to_Ms(0.2));
Thread::wait(osWaitForever);
}

/*
##############################################################
Timer 1 runs at 10 Hz
    Task_11_emulate_car();
    Task_1_break_accelerate();
    Task_10_calc_avg_speed();
#############################################################
*/

void Timer1_void(void const *args)
{
Task_11_emulate_car();                                           // runs every time, so at 10 Hz
    sw_timer1 = !sw_timer1;
if(sw_timer1) {                                                  // runs just every second time, so at 10 hz
Task_1_break_accelerate();
        sw_timer11 = !sw_timer11;
if(sw_timer11) {                                                 // runs just every fourth time, so at 0.5 hz
Task_10_calc_avg_speed();
        }
    }
}

/*
##############################################################
Timer 2 runs at 2 Hz, but starts tasks at 2 Hz, 1 Hz, 0.5 Hz
    Task_2_read_show_engine_state();
    Task_5_update_odometer();
    Updates Indicators
    Task_3_show_odometer();
    Task_8_read_single_side_light();
    Task_4_speed_warning();
    Task_9_read_indicators();
#############################################################
*/


void Timer2_void(void const *args) // timer runs at 2 hz
{
    
Task_2_read_show_engine_state();
Task_5_update_odometer();
    sw_timer2 = !sw_timer2;
    
if(indicator_L && indicator_R ) {                               // Sets the Left and Right Inidcators
        DoutLEDLeft=!DoutLEDRight;                              // needs to get the inverted status of led1 before led1 is changed
        DoutLEDRight=!DoutLEDRight;
        
    } else if (!indicator_R && !indicator_L) {
        DoutLEDLeft=0;
        DoutLEDRight=0;
    }
    
if(sw_timer2) 
{                                                               // runs just every second time, so at 1 hz
Task_3_show_odometer();
Task_8_read_single_side_light();
        sw_timer21 = !sw_timer21;
        
if (!indicator_R && indicator_L) 
{                                                               // switch the left / right indicator
            DoutLEDRight=0;
            DoutLEDLeft=!DoutLEDLeft;
        } else if(indicator_R && !indicator_L) {
            DoutLEDRight=!DoutLEDRight;
            DoutLEDLeft=0;
        }
if(sw_timer21) {                                            // runs just every second time, so at 0.5 hz
Task_4_speed_warning();
Task_9_read_indicators();
        }
    }
}
/*
##############################################################
Timer 3 runs at 0.2 Hz, but starts tasks at 0.2 Hz and 0.05 Hz
    Task_6_fill_mail_queue();
    Task_7_dump_mail_to_serial();
##############################################################
*/
void Timer3_void(void const *args)                                  // timer runs at 0.2 hz
{
Task_6_fill_mail_queue();
if((sw_timer3%4)==0) {                                          // task runs at 0.05 Hz
Task_7_dump_mail_to_serial();                                // dump the queue to serial
        sw_timer3=0;                                                // reset the timer
    }
    sw_timer3++;
}
/*
Reads the brake / acceleration of the car
*/
void Task_1_break_accelerate()
{
// Let the Semaphores wait
    SemBreak_Accelerate.wait();
    accerlator = AinAccel;                                              // save the accerlator value
    brake = AinBreak;                                                   // save the brake value
    
// Let the Semaphores release
    SemBreak_Accelerate.release();
}
/*
Reads the Engine On/Off Switch and displays its state
*/
void Task_2_read_show_engine_state()
{
// Let the Semaphores wait
    SemEngine.wait();
    engine = DinSwitchEngine;                                           // read the engine state
    DoutLEDEngine = engine;                                             // write the engine state
// Let the Semaphores release
    SemEngine.release();
}
/*
Updates the Odometer (Servo Motor)
*/
void Task_3_show_odometer()
{
// Let the Semaphores wait
    SemAvgSpeed.wait();                                                 
    Odometer = avgSpeed/250.0;                                          // Calculate the odometer
// Let the Semaphores release
    SemAvgSpeed.release();
}
/*
Indicates a Speed warning at 75 Mph
*/
void Task_4_speed_warning()
{
// Let the Semaphores wait
    SemAvgSpeed.wait();
if(avgSpeed>70.0)                                                   // check our speed
        LEDSpeedWarning = !LEDSpeedWarning;                             // and switch the Warning on/off
else
        LEDSpeedWarning = 0;
// Let the Semaphores release
    SemAvgSpeed.release();
}
/*
Updates the LCD Display
*/
void Task_5_update_odometer()
{
// Let the Semaphores wait
    SemDistance.wait();
    SemAvgSpeed.wait();
    lcd->locate(0,0);                                               // set cursor to location (0,0) - top left corner
    lcd->printf("s: %5.0f",avgSpeed);
    lcd->locate(1,0);
    lcd->printf("d: %5.0f",dist);
// Let the Semaphores release
    SemDistance.release();
    SemAvgSpeed.release();
}
/*
Reads the Left and Right Inidcator
*/
void Task_6_fill_mail_queue()
{
// Let the Semaphores wait
    SemMailCnT.wait();
    SemBreak_Accelerate.wait();
    SemSpeed.wait();
mail_t *mail = mail_box.alloc();                                            // reserve the space for our new message
    mail->speed = speed;                                                        // fill with values
    mail->accel = accerlator;
    mail->brake = brake;
    mail_box.put(mail);                                                         // put the new message into the mail queue
    mailcounter++;
// Let the Semaphores release
    SemBreak_Accelerate.release();
    SemSpeed.release();
    SemMailCnT.release();
}
/*
Reads the Mail Queue and Sends the Content to the Serial Port
*/
void Task_7_dump_mail_to_serial()
{
// Let the Semaphores wait
    SemMailCnT.wait();
while(mailcounter) {                                                        // as long as we got mail
        osEvent evt = mail_box.get();                                           // we are getting them
if (evt.status == osEventMail) {
mail_t *mail = (mail_t*)evt.value.p;                                // print the mail to serial
            serpc.printf("\nspeed: %.0f \n\r"   , mail->speed);
            serpc.printf("accerlator: %.2f\n\r"     , mail->accel);
            serpc.printf("brake: %.2f\n\r", mail->brake);
            mail_box.free(mail);                                                // clear up the mailbox
        }
        mailcounter--;
    }
// Release the Semaphores
    SemMailCnT.release();
}
/*
Single Side Light
*/
void Task_8_read_single_side_light()
{
    DoutLEDLight = DinSwitchLight;                                             // Reading the value
}
/*
Reads the Left and Right Inidcator
*/
void Task_9_read_indicators()
{
    indicator_R = DinSwitchRindic;                                            // Reading the value
    indicator_L = DinSwitchLindic;                                            // Reading the value
}
/*
Calculates the Average Speed
*/
void Task_10_calc_avg_speed()
{
// Let the Semaphores wait
    SemAvgSpeed.wait();
    SemAvgSpeedDB.wait();
float sum(0);
for(deque<float>::const_iterator i = AvgSpeedDB.begin(); i != AvgSpeedDB.end(); ++i)
        sum+= *i;                                                             // calculate the average by iterating over the queue
    avgSpeed = sum/AvgSpeedDB.size();
// Release the Semaphores
    SemAvgSpeedDB.release();
    SemAvgSpeed.release();
}
/*
Emulates the car
*/
void Task_11_emulate_car()
{
// Let the Semaphores wait
    SemAvgSpeed.wait();
    SemAvgSpeedDB.wait();
    SemDistance.wait();
    SemBreak_Accelerate.wait();
    SemSpeed.wait();
    SemEngine.wait();
if(accerlator<=brake || !engine)                                        // are we braking more than accelerating? is the engine on?
        speed = 0;
else
        speed = (accerlator-brake) *0.5 +speed;
if(speed>250)
        speed=250;                                                           // maximum speed
if(AvgSpeedDB.size()>=4)                                                 // if we already got 4 values, we have to
        AvgSpeedDB.pop_front();                                              // make space by deleting the oldest value
    AvgSpeedDB.push_back(speed);                                             // safe a new reading
    dist += speed * 1.0/20.0;                                                // runs at 20 Hz so we have to take this into account
// Release the Semaphores
    SemDistance.release();
    SemAvgSpeed.release();
    SemAvgSpeedDB.release();
    SemBreak_Accelerate.release();
    SemSpeed.release();
    SemEngine.release();
}
/*
Function used for converting Hz to Ms for a Steps
*/
int Convert_Hz_to_Ms(double Hz)
{
return 1000.0 / Hz;
}