'Sensor-Matic!' ELEC2645 Jack Berriman - 200836573
Dependencies: N5110-JDB SRF02 SoftPWM-JDB TMP102 mbed
main.cpp
- Committer:
- ll13jdb
- Date:
- 2016-05-05
- Revision:
- 0:e8ca5d36a1e7
File content as of revision 0:e8ca5d36a1e7:
/* ELEC2645 - Embedded Systems Project - "Sensor-matic!" Distance and Temperature Sensors Displayed on Nokia 5110 Screen Week 19 - Testing SRF02 Distance Sensor Week 20 - Creating Splash Screens Week 21 - Diagrams for Temperature and Distance Easter - Navigation Between Menus Week 22 - Piezo/LEDs Interfaced Week 23 - DOxygen Commenting Week 24 - Cleaning Up & Submission (c) Jack Berriman, University of Leeds, Summer 2016 */ /** @file main.cpp @brief Program Implementation */ #include "main.h" // ------------------------- MAIN FUNCTION ------------------------- // int main() // Main Function { init_K64F(); // Initialise FRDM K64F Micrcontroller init_buzzer(); // Initialise Piezo Buzzer init_program(); // Initialise Other Program Requirements (Screen/Ticker/Baud Rate) welcomeScreen(); // Display Welcome Screen screen.clear(); // Clear Screen while (1) { // Infinite Program While Loop if (screenNumber == 0) { // Main Menu = 0 mainMenu(); } else if (screenNumber == 1) { // Sensor Menu = 1 sensorMenu(); } else if (screenNumber == 2) { // Options Menu = 2 optionsMenu(); } else if (screenNumber == 3) { // Distance Display = 3 distanceDisplay(); } else { // Temperature Display = 4 temperatureDisplay(); } screen.refresh(); // Refresh Screen AFTER Each Iteration sleep(); // Put Peripherals To Sleep (Due to InterruptIn) } } // ------------------------- INITIALISE FUNCTIONS ------------------------- // void clearAll() // Clears Current Buffer (Text/Pixels) -- ADAPTED FROM ELEC1620 (GAME OF LIFE PROJECT) { for (int xPixel = 0; xPixel < 84; xPixel++) { // Loops Through X-Pixels for (int yPixel = 0; yPixel < 48; yPixel++) { // Loops Through Y-Pixels screen.clearPixel(xPixel,yPixel); // Clears } } screen.refresh(); // Refreshes Screen AFTER Clearing } void init_K64F() // Initialise K64F Function { // On-Board LEDs are Active-Low r_led = 1; g_led = 1; // Set to 1 (High) to Turn OFF b_led = 1; allLEDOff(); // Turn off All LEDs forward.rise(&forward_isr); // Interrupts Fire on Rising Clock Edge backward.rise(&backward_isr); forward.mode(PullDown); // Push Buttons are Connected to +3V3 - Pull-Down to Ground when Pressed backward.mode(PullDown); } void init_buzzer() // Initialise Piezo Buzzer Function { piezo.period(1.0/2000.0); // Set Frequency to 2 kHz piezo.write(0.0); // Turn OFF (Duty Cycle = 0) } void init_program() // Initialise Other Program Requirements { screen.init(); // Initialise Screen screen.clear(); // Clear Buffer systemTicker.attach(&system_isr,0.5); // Attach Ticker pc.baud(115200); // Set Serial Port Baud Rate to 115200 Hz } void welcomeScreen() // Prints Welcome Screen on Start-Up { // printString is a function from N5110.h screen.printString("ELEC2645", 20, 0); // Format: screen.printString("Text", Number of Pixels 'in' (X-Position), Bank Number (Y-Position)) screen.printString("Sensor-matic!", 5, 2); // Project Title screen.printString("By", 35, 4); screen.printString("Jack Berriman", 3, 5); wait(2); // Delay (To Read Text) } // ------------------------- STRUCTS ------------------------- // AverageValues getAverageValues() // Struct for Calculating Average Values of Distance and Temperature { AverageValues values; // Access Struct int temporaryDistanceSum = 0; int temporaryTemperatureSum = 0; // Initialise Temporary 'Sum' Variables Equal to Zero for (int i = 0; i <= 10; i++) { // Loop Through 10 Samples int distanceRead = srf02.getDistanceCm(); // Each Iteration: Get Distance and Write to Variable 'distanceRead' temporaryDistanceSum += distanceRead; // Add to Sum int temperatureRead = tmp102.get_temperature(); // Each Iteration: Get Temperature and Write to Variable 'distanceRead' temporaryTemperatureSum += temperatureRead; // Add to Sum } values.averageDistance = temporaryDistanceSum/10; // Divide by Number of Samples (10) values.averageTemperature = temporaryTemperatureSum/10; return values; // Return 'values' to Struct } // ------------------------- CURSOR POSITION (POTENTIOMETER) FUNCTIONS ------------------------- // int getCursorPosition() // Read Potentiometer Value & Convert to Bank Value { int bank = floor(controller * 5) + 1; // Read Potentioementer & Multiply by 5 // 'Floor' = Rounds Down if (bank == 6) { // If Bank value us greater that 5... bank = 5; // A value of 5 is returned } return bank; // Return Bank Value } void printCursorPositionMain(int cursor) // Print Cursor as Rectangle Next to Option in Main/Sensor Menu (Used with 'getCursorPosition') { // Prevents Cursor Position From Being Unselectable if (cursor != 1 && cursor != 3 && cursor != 5) { // If Cursor in Banks 2 or 4 - Print Rectangle y_axis_rect_main = (cursor * 8) + 3; // Multiply Cursor by 8 to Return Y-Position & Add 3 to Align in Bank screen.drawRect(75,y_axis_rect_main,2,2,0); // Print Rectangle (Depending on Potentiometer/Cursor) } else { screen.drawRect(75,y_axis_rect_main,2,2,0); // If Bank is 1, 3 or 5 - Still Print Rectangle } } void printCursorPositionOptions(int cursor, int stateOfLED, int stateOfSound) // Print Cursor as Rectangle Next to Option in Options Menu (Used with 'getCursorPosition') { // stateOfLed & stateOfSound Return 1 or 0 // 1 or 0 Passed into 'drawRect' - Fills or Unfills Rectangle y_axis_rect_options = (cursor * 8) + 3; // Multiply Cursor by 8 to Return Y-Position & Add 3 to Align in Bank cursor == 1 ? screen.drawRect(81,y_axis_rect_options,2,2,stateOfLED):screen.drawRect(81,y_axis_rect_options,2,2,stateOfSound); // If Cursor is 1 = Draw Rectangle OR If Cursor is 3 = Draw Rectangle } // ------------------------- MENU FUNCTIONS (MAIN/SENSORS/OPTIONS ------------------------- // void mainMenu() // Function for Main Menu { y_axis_rect_main = 19; // Set Initial Y-Position to 19th Pixel while (screenNumber == 0) { // While Main Menu Screen On... int cursor = getCursorPosition(); // Read Position of Cursor if (g_system_flag) { g_system_flag = 0; // Reset System Flag to 0 clearAll(); // Clears Previous Text String (Welcome Screen) screen.printString("MAIN MENU", 16, 0); // Print String 'Main Menu' screen.drawLine(5,11,79,11,1); // Draw Line Above Sensors String screen.printString("Sensors", 3, 2); // Print String 'Sensors' screen.printString("Options", 3, 4); // Print String 'Options' screen.drawLine(5,44,79,44,1); // Draw Line Underneath Options String // Used to Ensure Cursor is Set in Bank if (cursor <= 2) { // If Position of Cursor is 2 or Less cursor = 2; // Set Cursor to Equal 2 } if (cursor >= 3) { // If Position of Cursor is 3 or Greater cursor = 4; // Set Cursor to Equal 4 } printCursorPositionMain(cursor); // Print Cursor to Screen pc.printf("Controller = %d \n",cursor); // Debug in 'CoolTerm.exe' // Check Flag IF 'forward' Button Interrupt Pressed if (g_forward_flag == 1) { g_forward_flag = 0; // Clear Flag // Determine Next Screen if (cursor == 2) { screenNumber = 1; // Go to Sensor Menu } if (cursor == 4) { screenNumber = 2; // Go to Options Menu } } } returnToMenu(); // Back Button Function screen.refresh(); // Refresh Screen } } void sensorMenu() // Function for Sensor Menu { while (screenNumber == 1) { // While Sensor Menu is On... int cursor = getCursorPosition(); // Read Position of Cursor if (g_system_flag) { g_system_flag = 0; // Reset System Flag to 0 clearAll(); // Clears Previous Text String (Main Menu Screen) screen.printString("SENSOR MENU", 10, 0); // Prints String 'SensorMenu' screen.drawLine(5,11,79,11,1); // Draw Line Above Dist Sensor screen.printString("Dist Sensor", 3, 2); // Prints String 'Dist Sensor' screen.printString("Temp Sensor", 3, 4); // Prints String 'Temper Sensor' screen.drawLine(5,44,79,44,1); // Draw Line Below Temp Sensor // Used to Ensure Cursor is Set in Bank if (cursor <= 2) { // If Position of Cursor is 2 or Less cursor = 2; // Set Cursor to Equal 2 } if (cursor >= 3) { // If Position of Cursor is 3 or Greater cursor = 4; // Set Cursor to Equal 4 } printCursorPositionMain(cursor); // Print Cursor to Screen pc.printf("Controller = %d \n",cursor); // Debug in 'CoolTerm.exe' // Check Flag IF 'forward' Button Interrupt Pressed if (g_forward_flag == 1) { g_forward_flag = 0; // Clear Flag // Determine Next Screen if (cursor == 2) { screenNumber = 3; // Go to Distance Display } if (cursor == 4) { screenNumber = 4; // Go to Temperature Display } } } returnToMenu(); // Back Button Function screen.refresh(); // Refresh Screen } } void optionsMenu() // Function for Options Menu { y_axis_rect_options = 27; // Set Initial Y-Position to 27th Pixel while (screenNumber == 2) { // While Options Menu is On... int cursor = getCursorPosition(); // Read Position of Cursor if (g_system_flag) { g_system_flag = 0; // Reset System Flag to 0 clearAll(); // Clears Previous Text String (Main Menu Screen) screen.printString("Toggle LEDs", 1, 1); // Print String 'Toggle LEDs' screen.printString("Toggle Sound", 1, 3); // Print String 'Toggle Sound' screen.printString("Toggle Colour", 1, 5); // Print String 'Toggle Colour' // Used to Ensure Cursor is Set in Bank if (cursor <= 2) { // If Position of Cursor is 2 or Less cursor = 1; // Set Cursor to Equal 1 } if (cursor > 2 && cursor <= 4) { // If Position of Cursor is Between 2 or 4 cursor = 3; // Set Cursor to Equal 3 } if (cursor > 4) { // If Position of Cursor is Greater than 4 cursor = 5; // Set Cursor to Equal 5 } if (triggerLEDs == 1) { // Read Trigger of LED allLEDOn(); // If Trigger = 1, Turn ON LEDs } printCursorPositionOptions(cursor, stateOfLED, stateOfSound); // Print Position of Cursor // Check Flag IF 'forward' Button Interrupt Pressed if (g_forward_flag == 1) { g_forward_flag = 0; // Clear Flag // Determine Options to Edit if (cursor == 1) { stateOfLED = toggleLEDs(); // Toggle LEDs & Write 1 or 0 to 'stateOfLED' } if (cursor == 3) { stateOfSound = toggleSound(); // Toggle Sound & Write 1 or 0 to 'stateOfLED' } if (cursor == 5) { toggleColour(); // Toggle Colour } } } returnToMenu(); // Back Button Function screen.refresh(); // Refresh Screen } } void distanceDisplay() // Function to Display Distance { AverageValues values; // Call Struct For Average Values while(screenNumber == 3) { // While Temperature Display is On... values = getAverageValues(); int Distance = values.averageDistance; // Access Struct Value if (g_system_flag) { g_system_flag = 0; // Reset System Flag to 0 clearAll(); if (triggerLEDs == 1) { LEDs_Distance(Distance); // Call Distance LED Function } char buffer[14]; // Each Character = 6 pixels wide & Screen = 84 pixels (84/6 = 14) int length = sprintf(buffer,"Dist = %d CM",Distance); // Print Distance Value to Buffer pc.printf("DistAv = %f \n DistNorm = %f \n", Distance, srf02.getDistanceCm()); // Debug in 'CoolTerm.exe' if (length <= 14) // If String Fits on Display screen.printString(buffer,3,2); // Display on Screen if (Distance <= 14 || Distance >= 250) { // If Sensor is Out of Range clearAll(); // Clear Buffer screen.drawLine(4,2,80,2,2); // Draw Dotted Line Above Text screen.printString("DISTANCE OUT", 6, 1); screen.printString("OF RANGE", 18, 2); screen.drawLine(4,27,80,27,2); // Draw Dotted Line Below Text screen.printString("MIN = 15 CM", 10, 4); screen.printString("MAX = 250 CM", 7, 5); if (triggerSound == 1) { // Play Continuous Buzz When Out of Range buzzerOn(); } } else { // If Sensor is In Range screen.printString("DIST SENSOR", 10, 0); // Print String 'Distance Sensor' (Title) screen.drawRect(5,26,74,12,0); // Draw Rectangle Outline int fillLength = floor(PIXEL_PER_CM * Distance); // Update Fill Length Depending on Distance Value screen.drawRect(6,27,fillLength,11,1); // Fill the Distance Bar (Left to Right) screen.drawRect(17,26,2,12,0); // Puts in Dividers at 50 cm Intervals screen.drawRect(33,26,2,12,0); screen.drawRect(48,26,2,12,0); screen.drawRect(63,26,2,12,0); screen.printString("15",0,5); // Prints Lower Bound Marker (15 cm) screen.printString("250",67,5); // Prints Upper Bound Marker (250 cm) if (Distance <= 50) { if (triggerSound == 1) { // Check Trigger Value of Buzzer buzzerClose(); // Play Highly Freuquent Buzz } } else if (Distance <= 100) { if (triggerSound == 1) { // Check Trigger Value of Buzzer buzzerNormal(); // Play Moderately Freuquent Buzz } } else if (Distance <= 200) { if (triggerSound == 1) { // Check Trigger Value of Buzzer buzzerFar(); // Play Lowly Freuquent Buzz } } } returnToMenu(); // Function for Back Button screen.refresh(); // Refreshes Screen } } } void temperatureDisplay() // Function to Display Temperature { AverageValues values; // Call Struct For Average Values while(screenNumber == 4) { // While Temperature Display is On... values = getAverageValues(); int Temperature = values.averageTemperature; // Access Struct Value if (g_system_flag) { g_system_flag = 0; // Reset System Flag to 0 clearAll(); // Clears Previous Text String (Sensor Menu Screen) screen.printString("TEMP SENSOR", 10, 0); // Print String 'Temp Sensor' (Title) LEDs_Temperature(Temperature); // Call Temperature LED Function char buffer[14]; // Each Character = 6 pixels wide & Screen = 84 pixels (84/6 = 14) int length = sprintf(buffer,"Temp = %d -C",Temperature); // Print Temperature Value to Buffer pc.printf("TempAv = %f \n TempNorm = %f \n", Temperature, tmp102.get_temperature()); // Debug in 'CoolTerm.exe' if (length <= 14) // If String Fits on Display screen.printString(buffer,6,2); // Display on Screen screen.drawCircle(15,36,7,1); // Circular End of Thermometer screen.drawRect(22,32,6,8,1); // Start of Thermometer screen.drawRect(26,32,48,8,0); // Outline of the Thermometer int fillLength = floor(PIXEL_PER_DEGREE * Temperature); // Update Fill Length Depending on Thermometer Value screen.drawRect(27,33,fillLength,6,1); // Fill the Thermometer (Left to Right) screen.refresh(); // Refresh Screen } returnToMenu(); // Function for Back Button } } // ------------------------- OPTIONS MENU (TOGGLE) FUNCTIONS ------------------------- // bool toggleLEDs() // Toggles LED (Enable/Disable) { if (triggerLEDs == 0) { allLEDOn(); // Turn ON LEDs (While on Options Screen) triggerLEDs = 1; // 'Flip' Trigger } else { allLEDOff(); // Turn OFF LEDs (While on Options Screen triggerLEDs = 0; // 'Flip' Trigger } bool stateOfLED = triggerLEDs; // Set Trigger Value (1 or 0) into Bool return stateOfLED; // Return Bool (Used in Printing Rectangle) } bool toggleSound() // Toggles Sound (Enable/Disable) { if (triggerSound == 0) { piezo.write(0.5); // Play Bleep Noise wait(0.1); piezo.write(0.0); triggerSound = 1; // 'Flip' Trigger } else { triggerSound = 0; // 'Flip' Trigger } bool stateOfSound = triggerSound; // Set Trigger Value (1 or 0) into Bool return stateOfSound; // Return Bool (Used in Printing Rectangle) } void toggleColour() // Toggles Colour (Black-on-White/White-on-Black) { if (triggerColour == 0) { screen.inverseMode(); // Set Colour to Inverse Mode (White-on-Black) triggerColour = 1; // 'Flip' Trigger } else { screen.normalMode(); // Set Colour to Normal Mode (Black-on-White) triggerColour = 0; // 'Flip' Trigger } } // ------------------------- LED & SOFT-PWM FUNCTIONS ------------------------- // void allLEDOn() // Function to Turn ON All LEDs { red_led = 0; yellow_led = 0; green_led = 0; } void allLEDOff() // Function to Turn OFF All LEDs { red_led = 1; yellow_led = 1; green_led = 1; } void LEDs_Flashing() { redPWM = 0.5; // Turn ON Soft PWM LEDs yellowPWM = 0.5; greenPWM = 0.5; redPWM.period(0.25); // Set Period = 0.25 seconds yellowPWM.period(0.25); greenPWM.period(0.25); } void cancel_LEDs_Flashing() { redPWM = 0; // Turn OFF Soft PWM LEDs yellowPWM = 0; greenPWM = 0; redPWM.stop(); // Stop Soft PWM yellowPWM.stop(); greenPWM.stop(); } void LEDs_Distance(int d) // LEDs Illuminate (Depending on Distance) { if (d < 15 || d > 250) { // All ON LEDs_Flashing(); // Enable Soft PWM Flashing LEDs } else if (d >= 15 && d < 50) { // Red ON cancel_LEDs_Flashing(); // Prevent Soft PWM Overwritting Digital LEDs red_led = 0; yellow_led = 1; green_led = 1; } else if (d >= 50 && d < 100) { // Red & Yellow ON cancel_LEDs_Flashing(); red_led = 0; yellow_led = 0; green_led = 1; } else if (d >= 100 && d < 150) { // Yellow ON cancel_LEDs_Flashing(); red_led = 1; yellow_led = 0; green_led = 1; } else if (d >= 150 && d < 200) { // Yellow & Green ON cancel_LEDs_Flashing(); red_led = 1; yellow_led = 0; green_led = 0; } else if (d >= 200 && d < 250) { // Green ON cancel_LEDs_Flashing(); red_led = 1; yellow_led = 1; green_led = 0; } } void LEDs_Temperature(int t) // LEDs Illuminate (Depending on Temperature) { if (t < 10 || t >= 40) { // All ON allLEDOn(); } else if (t >= 10 && t < 15) { // Red ON red_led = 0; yellow_led = 1; green_led = 1; } else if (t >= 15 && t < 20) { // Red & Yellow ON red_led = 0; yellow_led = 0; green_led = 1; } else if (t >= 20 && t < 25) { // Green ON red_led = 0; yellow_led = 0; green_led = 1; } else if (t >= 25 && t < 30) { // Red & Yellow ON red_led = 0; yellow_led = 0; green_led = 1; } else if (t >= 30 && t < 40) { // Red ON red_led = 0; yellow_led = 1; green_led = 1; } } // ------------------------- BUZZER FUNCTIONS ------------------------- // void buzzerOn() // Buzz Continuously { piezo.write(0.5); // Set Duty Cycle - 50% wait_ms(10); // Wait 10 Milli-Seconds } void buzzerClose() // Buzz Every 0.1 Seconds { piezo.write(0.5); wait(0.1); // Wait 0.1 Seconds piezo.write(0.0); } void buzzerNormal() // Buzz Every 0.3 Seconds { piezo.write(0.5); wait(0.3); piezo.write(0.0); } void buzzerFar() // Buzz Every 0.5 Seconds { piezo.write(0.5); wait(0.5); piezo.write(0.0); } // ------------------------- ISR & INTERRUPT FUNCTIONS ------------------------- // void returnToMenu() // Function for Returning to Main Menu (if 'backward' Button Pressed) { // Check Flag IF 'forward' Button Interrupt Pressed if (g_backward_flag) { g_backward_flag = 0; // Clear Flag screenNumber = 0; // Go to Screen Number = 0 (Main Menu) cancel_LEDs_Flashing(); allLEDOff(); // Turn OFF LEDs piezo.write(0.0); // Write 0% Duty Cycle to Piezo (Turn OFF) } } void system_isr() // ISR For 'systemTicker' { g_system_flag = 1; // Set 'systemTicker' Flag } void forward_isr() // ISR For 'forward' Buttom { g_forward_flag = 1; // Set 'forward' Button Flag } void backward_isr() // ISR For 'backward' Button { g_backward_flag = 1; // Set 'backward' Button Flag }