Embedded Software Assignment 3

Dependencies:   MCP23017 Servo WattBob_TextLCD mbed-rtos mbed

Fork of ES_Assignment_3_Pub by M L

Files at this revision

API Documentation at this revision

Comitter:
usmb192
Date:
Fri May 27 15:56:36 2016 +0000
Child:
1:15edb3b6763a
Commit message:
final pub

Changed in this revision

MCP23017.lib Show annotated file Show diff for this revision Revisions of this file
Servo.lib Show annotated file Show diff for this revision Revisions of this file
WattBob_TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /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