![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
chad
Dependencies: MCP23017 WattBob_TextLCD mbed-rtos mbed
Diff: main.cpp
- Revision:
- 20:aeb7b7044c31
- Parent:
- 19:1fecb6fa14a2
--- 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