![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
All the commit done for assignment 3
Dependencies: MCP23017 Servo WattBob_TextLCD mbed mbed-rtos
Diff: main.cpp
- Revision:
- 1:b1b14911f265
- Parent:
- 0:8bcf5bf1bbfb
- Child:
- 2:b9c8c2e5fc90
--- a/main.cpp Tue Mar 21 13:44:42 2017 +0000 +++ b/main.cpp Tue Apr 04 16:11:42 2017 +0000 @@ -1,12 +1,380 @@ +/***************************************************************************************************** +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(p15); // Port for the Break Value +AnalogIn AinAccel(p16); // 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(p14); // Port for the Left Indicator +Servo Odometer(p26); +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 + -DigitalOut myled(LED1); +// 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() { - while(1) { - myled = 1; - wait(0.2); - myled = 0; - wait(0.2); +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 20 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 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>75.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; +}