Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MCP23017 WattBob_TextLCD mbed-rtos mbed
Revision 20:aeb7b7044c31, committed 2018-03-26
- Comitter:
- f_legge
- Date:
- Mon Mar 26 10:42:42 2018 +0000
- Parent:
- 19:1fecb6fa14a2
- Commit message:
- chad;
Changed in this revision
--- a/SDFileSystem.lib Tue Apr 04 13:47:53 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://developer.mbed.org/teams/mbed/code/SDFileSystem/#8db0d3b02cec
--- a/Servo.lib Tue Apr 04 13:47:53 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://developer.mbed.org/users/simon/code/Servo/#36b69a7ced07
--- a/main.cpp Tue Apr 04 13:47:53 2017 +0000
+++ b/main.cpp Mon Mar 26 10:42:42 2018 +0000
@@ -1,16 +1,41 @@
-// Paramater Allocation
+// Frazer Legge - H001262392
+// Embedded Software - Assignment 3
//
+// This program operates a simulation of a car control system.
+// THe simulation is completed through the use of external controls,
+// ignition, sidelights switch, idicator switches, accelerator and
+// brake pedals.
+// The simulation calculates Average speed and total distance travelled.
+// The simulation outputs are onboard LEDs to show ignition, sidelights,
+// indicators and overspeed indicator. The system shows the distance
+// traveled and average speed of the car on the LCD. A USB dump is also
+// done showing the average speed, accelerator and brake positions.
+
-#include "main.h"
+#include "mbed.h"
+#include "rtos.h"
+#include "MCP23017.h"
+#include "WattBob_TextLCD.h"
+
-// Pointers to LCD Screen
-MCP23017 *par_port; // pointer to 16-bit parallel I/O chip
-WattBob_TextLCD *lcd; // pointer to 2*16 character LCD object
+// LCD Definition
+#define BACK_LIGHT_ON(INTERFACE) INTERFACE->write_bit(1,BL_BIT)
+#define BACK_LIGHT_OFF(INTERFACE) INTERFACE->write_bit(0,BL_BIT)
+
+// Car Sim Max/Min speed (mph)
+#define MAX_SPEED 100
+#define MIN_SPEED 0
// Serial Connection
-
Serial pc(USBTX, USBRX,115200);
+// ============================================================================
+// MBED Pin Assignments
+// ============================================================================
+//
+
+// System Inputs
+// ----------------------------------------------------------------------------
// Analogue Input
AnalogIn Accel(p15); // Accelerator Pedal Input
AnalogIn Brake(p16); // Brake Pedal Input
@@ -21,35 +46,487 @@
DigitalIn Indi_L(p13); // Left indicator switch
DigitalIn Indi_R(p14); // Right idicator switch
-// Analogue Output
-Servo SpeedIndicator(p21); // Speed Indicator Servo
+// System Outputs
+// ----------------------------------------------------------------------------
+// PWM Output
+PwmOut SpeedIndicator(p21); // Speed Indicator Servo
+PwmOut Indi_L_LED(LED3); // Left Indicator LED
+PwmOut Indi_R_LED(LED4); // Right Indicator LED
// Digital Output
DigitalOut Ignit_LED(LED1); // Ignition LED Indicator
DigitalOut SideL_LED(LED2); // Side Light Indicator
-DigitalOut Indi_L_LED(LED3); // Left Indicator LED
-DigitalOut Indi_R_LED(LED4); // Right Indicator LED
+DigitalOut OverS_LED(p17); // Overspeed LED (REDBOX)
+
+// Pointers to LCD Screen
+MCP23017 *par_port; // pointer to 16-bit parallel I/O chip
+WattBob_TextLCD *lcd; // pointer to 2*16 character LCD object
+
+// ============================================================================
+// Data Structure
+// ============================================================================
+//
+
+// Raw Data Structure
+// ----------------------------------------------------------------------------
+
+// RawData is a global memory section that contains an instance of the raw input
+// data from speedControl.
+
+typedef struct
+{
+ bool EngineState;
+ float RawAccel;
+ float RawBrake;
+} RawData;
+
+// Create MUTEX to contol access to RawData
+Mutex RawDataMutex;
+
+// Create instance of RawData
+RawData rawData;
+
+// Speed Data Structure
+// ----------------------------------------------------------------------------
+
+// Speed data is a global memory section that contains an instance of the
+// calculated car speed.
-DigitalOut O_S_LED(p18); // Overspeed LED (REDBOX)
+typedef struct
+{
+ float rawSpeed[3];
+ int counter;
+} CarSpeedData;
+
+// Create MUTEX to control access to CarSpeedData
+
+Mutex SpeedDataMutex;
+
+// Create insance of CarSpeedData
+CarSpeedData speedData;
-/*typedef struct {
+// Filtered Data Structure
+// ----------------------------------------------------------------------------
+typedef struct
+{
+ float AvgSpeed;
+ float TotalDist;
+} FilteredData;
+
+// Create MUTEX to control access to FilterData
+Mutex filteredDataMutex;
+
+// Create instance of FilteredData
+FilteredData filteredData;
+
+// Mail Queue Structure
+// ----------------------------------------------------------------------------
+
+// PCDump is a global memory section that is populated in Mail_queue. The data
+// is coppied from the current state of the control system every 5 seconds.
+
+typedef struct
+{
float speed;
float accelerator;
float brake;
-} mail_t;
+} PCDump;
+
+// Create 100 element Mail Queue
+Mail<PCDump, 100> Memory_dump;
+
+// Counter to track number of elements in mail
+int MailCounter;
+
+// Create MUTEX to control access to MailQueueCounter
+Mutex MailMutex;
+
+// ============================================================================
+// Car Simulation
+// ============================================================================
+
+// The CarSim task updates the rawSpeed float at freq of 20Hz
-Mail<mail_t, 100> mail_box;*/
+void CarSim(void const *arg)
+{
+ float NewSpeed;
+
+ // Deposit global variables to local variables
+ RawDataMutex.lock();
+ bool currentEngineState = rawData.EngineState;
+ float currentAccel = rawData.RawAccel;
+ float currentBrake = rawData.RawBrake;
+ RawDataMutex.unlock();
+
+ // Calulate current speed as an fraction of the MAX_SPEED based on the
+ // percentage of accelerator and brake.
+ // Speed is set to 0 if Engine State is changed to 0;
+ NewSpeed = currentAccel*MAX_SPEED*(1-currentBrake)*currentEngineState;
+
+ // Check Counter. If outside array set to 0
+ // Data within shared resource therefore MUTEX is used.
+ SpeedDataMutex.lock();
+
+ if (speedData.counter > 2)
+ {
+ speedData.counter = 0;
+ }
+
+ // Output rawSpeed value to next index of rawSpeed.
+ // Increment counter
+ speedData.rawSpeed[speedData.counter] = NewSpeed;
+ speedData.counter++;
+ SpeedDataMutex.unlock();
+}
+
+// ============================================================================
+// Controller Tasks
+// ============================================================================
+
+// Speed Control (Task 1) reads external analog inputs and updates rawData.
+// Operating freq of 10Hz
+
+void SpeedControl(void const *arg)
+{
+ // Deposit global variables to local variables
+ RawDataMutex.lock();
+ rawData.RawAccel = Accel.read();
+ rawData.RawBrake = Brake.read();
+ RawDataMutex.unlock();
+}
+
+// Ignition(Task 2) reads the state of an "ignition switch".
+// Updates to rawData.
+// Operating freq of 2Hz.
+
+void Ignition(void const *arg)
+{
+ // Get Switch state and store locally
+ bool currentEngineState = Ignit.read();
+
+ // Deposit Local data to global under locked state
+ RawDataMutex.lock();
+ rawData.EngineState = currentEngineState;
+ RawDataMutex.unlock();
+
+ // Logic check on Engine state
+ if (currentEngineState == 1)
+ {
+ Ignit_LED = 1;
+ }
+ else
+ {
+ Ignit_LED = 0;
+ }
+}
+
+// Speed_Avg (Task 3) Calculates the average speed of the car over 3 speed
+// samples.
+// Operation freq of 5Hz
+void Speed_Avg(void const *arg)
+{
+ // Init local float as 0
+ float speed_T = 0.0;
+
+ // Deposit gloabal data to local data under locked state
+ SpeedDataMutex.lock();
+ for (int i = 0; i < 3; i++)
+ {
+ speed_T = speed_T + speedData.rawSpeed[i];
+ }
+ SpeedDataMutex.unlock();
+
+ // Deposit local data to global data under locked state
+ filteredDataMutex.lock();
+ filteredData.AvgSpeed = (speed_T/3);
+ filteredDataMutex.unlock();
+}
+
+// Speed_Indi (Task 4) shows a representation of the car speed through a servo
+// Operation freq of 1Hz
+
+void Speed_Indi(void const *arg)
+{
+ // Deposit gloabal data to local data under locked state
+ filteredDataMutex.lock();
+ float currentAvgSpeed = filteredData.AvgSpeed;
+ filteredDataMutex.unlock();
+
+ // Update Servo
+ // Operates between 1000us and 2000us pwm
+ // ie -> 10 * 50(mph) will give middle positioning
+ SpeedIndicator.pulsewidth_us(1000+(10*currentAvgSpeed));
+}
-float Accel_Reg;
-float Brake_Reg;
+// OverSpeed (Task 5) illuminates an LED indicator to show that the car is above
+// 70mph.
+// Opperation freq of 0.5Hz
+
+void OverSpeed(void const *arg)
+{
+ // Deposit gloabal data to local data under locked state
+ SpeedDataMutex.lock();
+ float currentSpeed = speedData.rawSpeed[1];
+ SpeedDataMutex.unlock();
+
+ // Use locally stored current speed to show if car is travelling over 70mph
+ if (currentSpeed > 70.0)
+ {
+ OverS_LED = 1;
+ }
+ else
+ {
+ OverS_LED = 0;
+ }
+}
+
+// Display (Taks 6) shows the total distance traveled and the average speed on
+// the LCD.
+// Operation freq of 2Hz
+
+void Display(void const *arg)
+{
+ // Local distance variable
+ float currentTotalDist;
+
+ // Deposit gloabal data to local data under locked state
+ filteredDataMutex.lock();
+ float currentAvgSpeed = filteredData.AvgSpeed;
+ float current_TotalDist = filteredData.TotalDist;
+ filteredDataMutex.unlock();
+
+ // Update distance traveled
+ // Polling every 0.5 seconds therefore convereted from 0.5s to hours
+ // MUTEX not protected as TotalDist is only used for this function
+ currentTotalDist = current_TotalDist + (currentAvgSpeed*(0.5/3600));
+
+ filteredDataMutex.lock();
+ filteredData.TotalDist = currentTotalDist;
+ filteredDataMutex.unlock();
+
+ // Output on LCD
+ lcd->locate(0,0);
+ lcd->printf("D: %f",currentTotalDist);
+ lcd->locate(1,0);
+ lcd->printf("S: %f",currentAvgSpeed);
+}
+
+// Mail_Queue (Task 7) sends gloabal variable to a MAIL structure.
+// A counter is incremented to track the variables.
+// Operation freq of 0.2Hz.
+
+void Mail_Queue(void const *arg)
+{
+ // Deposit gloabal data to local data under locked state
+ RawDataMutex.lock();
+ float currentAccel = rawData.RawAccel;
+ float currentBrake = rawData.RawBrake;
+ RawDataMutex.unlock();
+
+ filteredDataMutex.lock();
+ float currentAvgSpeed = filteredData.AvgSpeed;
+ filteredDataMutex.lock();
-float p;
+ // Allocate and populate PCDump Struct
+ PCDump *currentPCDump = Memory_dump.alloc();
+
+ currentPCDump->brake = currentBrake;
+ currentPCDump->accelerator = currentAccel;
+ currentPCDump->speed = currentAvgSpeed;
+
+ // PCDump struct pushed to mail queue
+ Memory_dump.put(currentPCDump);
+
+ // Lock mail MUTEX and increment counter
+ MailMutex.lock();
+ MailCounter++;
+ MailMutex.unlock();
+}
+
+// Mail_Print (Task 8) sends the MAIL queue to a terminal over USB serial.
+// When finished MAIL counter is reset.
+// Operation freq of 0.05Hz.
+
+void Mail_Print(void const *arg)
+{
+ // Deposit gloabal data to local data under locked state
+ MailMutex.lock();
+ int currentMCount = MailCounter;
+ MailMutex.unlock();
+
+ // Terminal header notifying dump
+ pc.printf("Mail Dump\n\r");
+
+ // Print each record in MAIL queue. MAIL queue is deposited locally then
+ // values are printed and elements freed in MAIL queue.
+ for (int i = 0; i < currentMCount; i++)
+ {
+ osEvent evnt = Memory_dump.get();
+ if (evnt.status == osEventMail)
+ {
+ PCDump *currentPCDump = (PCDump*)evnt.value.p;
+
+ pc.printf("AvgSpeed: %f\n\rAccel: %f\n\rBrake: %f\n\rCounter: %i\n\n\r",currentPCDump->speed,currentPCDump->accelerator,currentPCDump->brake,i);
+
+ Memory_dump.free(currentPCDump);
+ }
+ }
+
+ // Reset counter under locked state
+ MailMutex.lock();
+ MailCounter = 0;
+ MailMutex.unlock();
+}
+
+// Side_Light (Task 9) checks the state of the side light and sets the LED
+// indicator
+// Operation freq of 1Hz
+
+void Side_Light(void const *arg)
+{
+ if(SideL == 1)
+ {
+ SideL_LED = 1;
+ }
+ else
+ {
+ SideL_LED = 0;
+ }
+}
+
+// Indicator (Task 10) checks the left and right indicator switches.
+// Illuminates either left or right LED accordingly.
+// If both high then LEDs flash in hazard mode.
-float Avg_Speed;
-float Speed_In;
-float Speed_0;
-float Speed_1;
-float Speed_2;
+void Indicator(void const *arg)
+{
+ // If Left switch is high then flash left LED at 1Hz
+ if (Indi_L == 1 && Indi_R == 0)
+ {
+ Indi_L_LED.period(1.0);
+ Indi_L_LED.pulsewidth(0.5);
+
+ Indi_R_LED.period(1.0);
+ Indi_R_LED.pulsewidth(0.0);
+ }
+
+ // If Right switch is high then flash right LED at 1Hz
+ else if (Indi_L == 0 && Indi_R == 1)
+ {
+ Indi_L_LED.period(1.0);
+ Indi_L_LED.pulsewidth(0.0);
+
+ Indi_R_LED.period(1.0);
+ Indi_R_LED.pulsewidth(0.5);
+ }
+
+ // If Left & Right switch is high then flash both LEDs at 2Hz
+ else if (Indi_L == 1 && Indi_R == 1)
+ {
+ Indi_L_LED.period(0.5);
+ Indi_R_LED.period(0.5);
+ Indi_L_LED.pulsewidth(0.25);
+ Indi_R_LED.pulsewidth(0.25);
+ }
+
+ // If Left & Right switch is low then no flash
+ else if (Indi_L == 0 && Indi_R == 0)
+ {
+ Indi_L_LED.period(1.0);
+ Indi_L_LED.pulsewidth(0.0);
+
+ Indi_R_LED.period(1.0);
+ Indi_R_LED.pulsewidth(0.0);
+ }
+}
+
+void ledFlasher(void const *arg)
+{
+ Ignit_LED =! Ignit_LED;
+}
+
-float dist;
+// ============================================================================
+// Init System
+// ============================================================================
+
+void Init()
+{
+ // Servo freq set
+ SpeedIndicator.period_ms(50);
+ // Global Variables zeroed
+ rawData.EngineState = 0;
+ rawData.RawAccel = 0.0;
+ rawData.RawBrake = 0.0;
+ speedData.rawSpeed[0] = 0.0;
+ speedData.rawSpeed[1] = 0.0;
+ speedData.rawSpeed[2] = 0.0;
+ speedData.counter = 0;
+ filteredData.AvgSpeed = 0.0;
+ filteredData.TotalDist = 0.0;
+ MailCounter = 0;
+}
+
+// ============================================================================
+// Main Thread
+// ============================================================================
+
+int main()
+{
+ par_port = new MCP23017(p9, p10, 0x40); // initialise 16-bit I/O chip
+ par_port->config(0x0F00, 0x0F00, 0x0F00);
+
+ 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
+
+ Init(); // Run init void
+
+ Ignit_LED = 0;
+
+
+ //while(1)
+ //{
+ // Ignit_LED =! Ignit_LED;
+ // wait(1);
+ //Ignit_LED = 0;
+ //wait(1);
+
+ //}
+
+ //SideL_LED = 1;
+
+ RtosTimer ledFlash(ledFlasher, osTimerPeriodic);
+ ledFlash.start(1000);
+ // Timer Objects
+ //RtosTimer Car_Sim(CarSim,osTimerPeriodic);
+ //RtosTimer Task1(SpeedControl,osTimerPeriodic);
+ //RtosTimer Task2(Ignition,osTimerPeriodic);
+ //RtosTimer Task3(Speed_Avg,osTimerPeriodic);
+ //RtosTimer Task4(Speed_Indi,osTimerPeriodic);
+ //RtosTimer Task5(OverSpeed,osTimerPeriodic);
+ //RtosTimer Task6(Display,osTimerPeriodic);
+ //RtosTimer Task7(Mail_Queue,osTimerPeriodic);
+ //RtosTimer Task8(Mail_Print,osTimerPeriodic);
+ //RtosTimer Task9(Side_Light,osTimerPeriodic);
+ //RtosTimer Task10(Indicator,osTimerPeriodic);
+
+ // Start RTOS Timer objects
+
+ //Car_Sim.start(50); // 20Hz
+ //Task1.start(100); // 10Hz
+ //Task2.start(500); // 2Hz
+ //Task3.start(200); // 5Hz
+ //Task4.start(1000); // 1Hz
+ //Task5.start(2000); // 0.5Hz
+ //Task6.start(500); // 2Hz
+ //Task7.start(5000); // 0.2Hz
+ //Task8.start(20000); // 0.05Hz
+ //Task9.start(1000); // 1Hz
+ //Task10.start(2000); // 2Hz
+
+ Thread::wait(osWaitForever); // Forever loop
+
+}
\ No newline at end of file
--- a/main.h Tue Apr 04 13:47:53 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -#include "mbed.h" -#include "MCP23017.h" -#include "WattBob_TextLCD.h" -#include "rtos.h" -#include "Servo.h" - -#define BACK_LIGHT_ON(INTERFACE) INTERFACE->write_bit(1,BL_BIT) -#define BACK_LIGHT_OFF(INTERFACE) INTERFACE->write_bit(0,BL_BIT) - -extern MCP23017 *par_port; // pointer to 16-bit parallel I/O chip -extern WattBob_TextLCD *lcd; // pointer to 2*16 character LCD object - -extern Serial pc; - -// Analogue Input -extern AnalogIn Accel; // Accelerator Pedal Input -extern AnalogIn Brake; // Brake Pedal Input - -// Digital Input -extern DigitalIn Ignit; // Engine On/Off -extern DigitalIn SideL; // Side Light On/Off -extern DigitalIn Indi_L; // Left indicator switch -extern DigitalIn Indi_R; // Right idicator switch - -// Analogue Output -extern Servo SpeedIndicator; // Speed Indicator Servo - -// Digital Output -extern DigitalOut Ignit_LED; // Ignition LED Indicator -extern DigitalOut SideL_LED; // Side Light Indicator -extern DigitalOut Indi_L_LED; // Left Indicator LED -extern DigitalOut Indi_R_LED; // Right Indicator LED - -extern DigitalOut O_S_LED; // Overspeed LED (REDBOX) - -extern float Accel_Reg; -extern float Brake_Reg; - -extern float p; - -extern float Avg_Speed; -extern float Speed_In; -extern float Speed_0; -extern float Speed_1; -extern float Speed_2; - -extern float Dist; - - -
--- a/mbed-rtos.lib Tue Apr 04 13:47:53 2017 +0000 +++ b/mbed-rtos.lib Mon Mar 26 10:42:42 2018 +0000 @@ -1,1 +1,1 @@ -https://mbed.org/users/mbed_official/code/mbed-rtos/#58563e6cba1e +https://os.mbed.com/users/f_legge/code/mbed-rtos/#b63b65f13991
--- a/tasks.cpp Tue Apr 04 13:47:53 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-#include "main.h"
-
-void speedControl(void)
-{
- Accel_Reg = (Accel * 100);
- Brake_Reg = (Brake * 100);
-}
-
-
-void ignition(void)
-{
- Ignit_LED = Ignit;
-}
-
-void Speed_avg(void)
-{
- Speed_2 = Speed_1;
- Speed_1 = Speed_0;
- Speed_0 = Speed_In;
-
- Avg_Speed = ((Speed_2 + Speed_1 + Speed_0)/3);
-}
-
-void Speed_Indi(void)
-{
- p = (Avg_Speed/100);
- SpeedIndicator = p;
-}
-
-void OverSpeed(void)
-{
- if (Avg_Speed >= 70)
- O_S_LED = 1;
- else
- O_S_LED = 0;
-}
-
-void Display(void)
-{
- lcd->locate(0,0);
- lcd->printf(".2%fmi, .2%fmph", Dist, Avg_Speed);
-}
-
-void Mail_queue(void)
-{
- mail_t *mail = mail_box.alloc()
- mail->speed = Avg_Speed;
- mail->accelerator = Accel_Reg;
- mail->brake = Brake_Reg;
-}
-
-void Mail_print(void)
-{
- pc.printf("Speed: %f\r",mail->speed);
- pc.printf("Accelerator: %f\r",mail->accelerator);
- pc.printf("Brake: %f\r",mail->brake);
- mail_box.free(mail);
-}
-
-void side_light(void)
-{
- SideL_LED = SideL;
-}
-
-void indicator(void)
-{
- if (Indi_L == 1 && Indi_R == 1)
- {
- Indi_L_LED = 1;
- Indi_R_LED = 1;
- wait(0.25);
- Indi_L_LED = 0;
- Indi_R_LED = 0;
- wait(0.25);
- }
- else if (Indi_L == 1)
- {
- Indi_L_LED != Indi_L_LED;
- wait(0.5);
- }
- else if (Indi_R == 1)
- {
- Indi_R_LED != Indi_R_LED;
- wait(0.5);
- }
-}
-
-void car_sim(void)
-{
- Speed_In = Speed_In + ((Accel_Reg - Brake_Reg)*?);
-}
-
-
-
-