
Embedded Software Assignment 3
Dependencies: MCP23017 Servo WattBob_TextLCD mbed-rtos mbed
Fork of ES_Assignment_3_Pub by
Revision 0:6b3496e7a954, committed 2016-05-27
- Comitter:
- usmb192
- Date:
- Fri May 27 15:56:36 2016 +0000
- Child:
- 1:15edb3b6763a
- Commit message:
- final pub
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MCP23017.lib Fri May 27 15:56:36 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/jimherd/code/MCP23017/#d57de266cf19
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Servo.lib Fri May 27 15:56:36 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/simon/code/Servo/#36b69a7ced07
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WattBob_TextLCD.lib Fri May 27 15:56:36 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/jimherd/code/WattBob_TextLCD/#3b26cd028e85
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri May 27 15:56:36 2016 +0000 @@ -0,0 +1,437 @@ +/***************************************************************************************************** + + Assigment 3 Embedded Software + Markus + + + + + 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 an Servo + The Emulation and Synchronisation is implemented using TimerThreads and Semaphores + +@version 1.4 +@updateDate 30.03.2016 +@author Markus + +******************************************************************************************************/ + +#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> + + +//Unfortunately the definition doesnt work, either here or anywhere else... +//#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 + + +// Task Functions +void task1_break_accelerate(); +void task2_read_show_engine_state(); +void task3_show_odometer(); +void task4_speed_warning(); +void task5_update_odometer(); +void task6_fill_mail_queue(); +void task7_dump_mail_to_serial(); +void task8_read_single_side_light(); +void task9_read_indicators(); +void task10_calc_avg_speed(); +void task11_emulate_car(); + +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); // initalize with a first run + +std::deque<float> AvgSpeedDB; // used for storing the average speed + +Semaphore SemAvgSpeedDB(1); +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() +{ + // 20.00 Hz = 00050 ms + // 10.00 Hz = 00100 ms + // 05.00 Hz = 00200 ms + // 02.00 Hz = 00500 ms + // 01.00 Hz = 01000 ms + // 00.50 Hz = 02000 ms + // 00.20 Hz = 05000 ms + // 00.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); + 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 20 Hz, but starts tasks at 20 Hz, 10 Hz, 5 Hz + task11_emulate_car(); + task1_break_accelerate(); + task10_calc_avg_speed(); +############################################################# +*/ + +void Timer1_void(void const *args) +{ + task11_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 + task1_break_accelerate(); + sw_timer11 = !sw_timer11; + if(sw_timer11) { // runs just every second time, so at 5 hz + task10_calc_avg_speed(); + } + } +} + + +/* +############################################################## +Timer 2 runs at 2 Hz, but starts tasks at 2 Hz, 1 Hz, 0.5 Hz + + task2_read_show_engine_state(); + task5_update_odometer(); + Updates Indicators + + task3_show_odometer(); + task8_read_single_side_light(); + + task4_speed_warning(); + task9_read_indicators(); +############################################################# +*/ +void Timer2_void(void const *args) // timer runs at 2 hz +{ + task2_read_show_engine_state(); + task5_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 + task3_show_odometer(); + task8_read_single_side_light(); + sw_timer21 = !sw_timer21; + + if (!indicator_R && indicator_L) { + 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 + task4_speed_warning(); + task9_read_indicators(); + } + } + +} + + +/* +############################################################## +Timer 3 runs at 0.2 Hz, but starts tasks at 0.2 Hz and 0.05 Hz + task6_fill_mail_queue(); + task7_dump_mail_to_serial(); +############################################################## +*/ +void Timer3_void(void const *args) // timer runs at 0.2 hz +{ + task6_fill_mail_queue(); + if((sw_timer3%4)==0) { // task runs at 0.05 Hz + task7_dump_mail_to_serial(); + sw_timer3=0; + } + sw_timer3++; +} + + +/* +Reads the brake / acceleration of the car +*/ +void task1_break_accelerate() +{ + SemBreak_Accelerate.wait(); + accerlator = AinAccel; + brake = AinBreak; + SemBreak_Accelerate.release(); +} + + +/* +Reads the Engine On/Off Switch and displays its state +*/ +void task2_read_show_engine_state() +{ + SemEngine.wait(); + engine = DinSwitchEngine; + DoutLEDEngine = engine; + SemEngine.release(); +} + + +/* +Updates the Odometer (Servo Motor) +*/ +void task3_show_odometer() +{ + SemAvgSpeed.wait(); + Odometer = avgSpeed/250.0; + SemAvgSpeed.release(); +} + + +/* +Indicates a Speed warning at 75 Mph +*/ +void task4_speed_warning() +{ + SemAvgSpeed.wait(); + if(avgSpeed>75.0) + LEDSpeedWarning = !LEDSpeedWarning; + else + LEDSpeedWarning = 0; + SemAvgSpeed.release(); +} + + +/* +Updates the LCD Display +*/ +void task5_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 task6_fill_mail_queue() +{ + // Let the Semaphores wait + SemMailCnT.wait(); + SemBreak_Accelerate.wait(); + SemSpeed.wait(); + + mail_t *mail = mail_box.alloc(); + mail->speed = speed; + mail->accel = accerlator; + mail->brake = brake; + mail_box.put(mail); + 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 task7_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 task8_read_single_side_light() +{ + DoutLEDLight = DinSwitchLight; +} + + +/* +Reads the Left and Right Inidcator +*/ +void task9_read_indicators() +{ + indicator_R = DinSwitchRindic; + indicator_L = DinSwitchLindic; +} + + +/* +Calculates the Average Speed +*/ +void task10_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 task11_emulate_car() +{ + // Let the Semaphores wait + SemAvgSpeed.wait(); + SemAvgSpeedDB.wait(); + SemDistance.wait(); + SemBreak_Accelerate.wait(); + SemSpeed.wait(); + SemEngine.wait(); + + if(accerlator<=brake || !engine) + 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; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Fri May 27 15:56:36 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#4c105b8d7cae
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri May 27 15:56:36 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/6c34061e7c34 \ No newline at end of file