![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
chad
Dependencies: MCP23017 WattBob_TextLCD mbed-rtos mbed
main.cpp
- Committer:
- f_legge
- Date:
- 2018-03-26
- Revision:
- 20:aeb7b7044c31
- Parent:
- 19:1fecb6fa14a2
File content as of revision 20:aeb7b7044c31:
// 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 "mbed.h" #include "rtos.h" #include "MCP23017.h" #include "WattBob_TextLCD.h" // 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 // Digital Input DigitalIn Ignit(p11); // Engine On/Off DigitalIn SideL(p12); // Side Light On/Off DigitalIn Indi_L(p13); // Left indicator switch DigitalIn Indi_R(p14); // Right idicator switch // 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 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. typedef struct { float rawSpeed[3]; int counter; } CarSpeedData; // Create MUTEX to control access to CarSpeedData Mutex SpeedDataMutex; // Create insance of CarSpeedData CarSpeedData speedData; // 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; } 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 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)); } // 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(); // 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. 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; } // ============================================================================ // 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 }