Code for the Hexiwear sensor system. Requires an Air Quality Click, Carbon Monoxide Click, and Buzzer Click for full functionality. Currently only reads values and displays to the OLED while testing and alerting the user of present threats. Future goals are to incorporate button presses with separate screens to display the data as well as using the KW40 drivers to transmit the data. Still in early stages of development, many unnecessary files will be removed and cleaned up once final product is completed within the next month. Driver.cpp is the main driver for the program and was written for purposes of this project. All other headers and functions were found on mbed.org from other developers repositories or provided by NXP Semiconductors for purposes of this project.

Dependencies:   Hexi_KW40Z images

Committer:
Gfolker
Date:
Tue Mar 28 21:41:06 2017 +0000
Revision:
2:aa8c291b3f9a
Parent:
1:8ab4a1e27785
Child:
3:24b332b8e41d
Application now supports data transmission via BLE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Gfolker 0:f70b1d60f794 1 #include "mbed.h"
Gfolker 0:f70b1d60f794 2 #include "pwm_tone.h" /* Tone library for Buzzer Click */
Gfolker 0:f70b1d60f794 3 #include "Hexi_OLED_SSD1351.h" /* Header file for OLED Display */
Gfolker 0:f70b1d60f794 4 #include "string.h"
Gfolker 0:f70b1d60f794 5 #include "Hexi_KW40Z.h" /* Driver for button presses and BLE */
Gfolker 0:f70b1d60f794 6 #include <math.h> /* Used for ADC conversion algorithm */
Gfolker 1:8ab4a1e27785 7 #include "images.h" /* BMPs of the images drawn to the OLED */
Gfolker 0:f70b1d60f794 8
Gfolker 0:f70b1d60f794 9 /*****Function Prototypes*****/
Gfolker 0:f70b1d60f794 10 void readSensors();
Gfolker 0:f70b1d60f794 11 void ledColor();
Gfolker 0:f70b1d60f794 12 void led_out();
Gfolker 0:f70b1d60f794 13 void buzzer();
Gfolker 0:f70b1d60f794 14 void CalculatePPM();
Gfolker 1:8ab4a1e27785 15 void dataQueue();
Gfolker 1:8ab4a1e27785 16 void initModules();
Gfolker 1:8ab4a1e27785 17 void StartHaptic(void);
Gfolker 1:8ab4a1e27785 18 void StopHaptic(void const *n);
Gfolker 2:aa8c291b3f9a 19 void txTask(void);
Gfolker 0:f70b1d60f794 20
Gfolker 0:f70b1d60f794 21 PwmOut Buzzer(PTA10); /* Buzzer is attached to docking station port 1 */
Gfolker 0:f70b1d60f794 22 AnalogIn AQSensor(PTB3); /* Air Quality sensor is attached to docking station port 2 */
Gfolker 0:f70b1d60f794 23 AnalogIn COSensor(PTB6); /* Carbon Monoxide sensor is attached to docking station port 3 */
Gfolker 0:f70b1d60f794 24
Gfolker 1:8ab4a1e27785 25 /* Instantiate the SSD1351 OLED Driver */
Gfolker 1:8ab4a1e27785 26 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15);
Gfolker 1:8ab4a1e27785 27
Gfolker 0:f70b1d60f794 28 BusOut led(PTC8, PTD0, PTC9); /* RGB Port Configurations */
Gfolker 1:8ab4a1e27785 29 DigitalOut haptic(PTB9); /* Port Configuration for vibrations */
Gfolker 1:8ab4a1e27785 30 /* Define timer for haptic feedback */
Gfolker 1:8ab4a1e27785 31 RtosTimer hapticTimer(StopHaptic, osTimerOnce);
Gfolker 1:8ab4a1e27785 32
Gfolker 1:8ab4a1e27785 33 int screen = 1; //detects which screen the user is currently on
Gfolker 1:8ab4a1e27785 34 bool is_drawn1 = 0; //detects if the screen is already drawn to the screen
Gfolker 1:8ab4a1e27785 35 bool is_drawn2 = 0;
Gfolker 1:8ab4a1e27785 36 bool is_drawn3 = 0;
Gfolker 2:aa8c291b3f9a 37 bool is_drawn4 = 0;
Gfolker 1:8ab4a1e27785 38
Gfolker 1:8ab4a1e27785 39 /* Screens */
Gfolker 2:aa8c291b3f9a 40 const uint8_t *image1; //homescreen
Gfolker 1:8ab4a1e27785 41
Gfolker 2:aa8c291b3f9a 42 const uint8_t *image2; //air quality screen
Gfolker 1:8ab4a1e27785 43
Gfolker 2:aa8c291b3f9a 44 const uint8_t *image3; //co screen
Gfolker 0:f70b1d60f794 45
Gfolker 0:f70b1d60f794 46 const int green = 5,
Gfolker 0:f70b1d60f794 47 red = 6, /* LED Colors */
Gfolker 0:f70b1d60f794 48 black = 7,
Gfolker 0:f70b1d60f794 49 yellow = 4;
Gfolker 0:f70b1d60f794 50
Gfolker 0:f70b1d60f794 51 bool is_sounding = false; /* Set to high if the buzzer is going off */
Gfolker 0:f70b1d60f794 52
Gfolker 0:f70b1d60f794 53 int led_color; /* Variable to hold the current LED color */
Gfolker 0:f70b1d60f794 54
Gfolker 0:f70b1d60f794 55 Ticker sensor_read, /* Used for the read sensor subroutine call */
Gfolker 0:f70b1d60f794 56 buzzer_sound, /* Used for the sound buzzer subroutine call */
Gfolker 0:f70b1d60f794 57 led_flash, /* Used to determine the flash rate */
Gfolker 0:f70b1d60f794 58 ledcolor, /* Used to determine the LED color */
Gfolker 1:8ab4a1e27785 59 A2D_Convert, /* Used to convert the analog signal to digital */
Gfolker 1:8ab4a1e27785 60 push; /* Used to push values into the data array */
Gfolker 0:f70b1d60f794 61
Gfolker 0:f70b1d60f794 62 float B_4 = 1000000/Ti4, /* Tones that will play on the buzzer click */
Gfolker 0:f70b1d60f794 63 B_5 = 1000000/Ti5;
Gfolker 0:f70b1d60f794 64
Gfolker 0:f70b1d60f794 65 char text[20]; /* Static Text Buffer for OLED Display */
Gfolker 0:f70b1d60f794 66 char AQ_level[20]; /* Dynamic Text Buffer for AQ total */
Gfolker 0:f70b1d60f794 67 char CO_level[20]; /* Dynamic Text Buffer for CO total */
Gfolker 0:f70b1d60f794 68 char average[20]; /* Dynamic Text Buffer for the Average total */
Gfolker 0:f70b1d60f794 69 char total_total[20]; /* Dynamic Text Buffer for the Total total */
Gfolker 0:f70b1d60f794 70
Gfolker 1:8ab4a1e27785 71 /* Either unit16_t or double */
Gfolker 1:8ab4a1e27785 72 double total, /* Variable to store the total total */
Gfolker 1:8ab4a1e27785 73 aq_ppm, /* Variable used to store the AQ PPM */
Gfolker 1:8ab4a1e27785 74 co_ppm; /* Variable used to store the CO PPM */
Gfolker 0:f70b1d60f794 75
Gfolker 0:f70b1d60f794 76 uint16_t aq_total, /* Variable to store the AQ total */
Gfolker 1:8ab4a1e27785 77 co_total; /* Variable to store the CO total */
Gfolker 1:8ab4a1e27785 78
Gfolker 2:aa8c291b3f9a 79 /*Create a Thread to handle sending BLE Sensor Data */
Gfolker 2:aa8c291b3f9a 80 Thread txThread;
Gfolker 2:aa8c291b3f9a 81
Gfolker 2:aa8c291b3f9a 82 /* Variables to handle the circular array algorithm */
Gfolker 1:8ab4a1e27785 83 const int SIZE = 500;
Gfolker 1:8ab4a1e27785 84 double dataSet [SIZE];
Gfolker 1:8ab4a1e27785 85 int pushIndex = 0;
Gfolker 1:8ab4a1e27785 86 bool calc = false;
Gfolker 1:8ab4a1e27785 87 double avg = 0, sum = 0;
Gfolker 1:8ab4a1e27785 88
Gfolker 1:8ab4a1e27785 89 /* Instantiate the Hexi KW40Z Driver (UART TX, UART RX) */
Gfolker 1:8ab4a1e27785 90 KW40Z kw40z_device(PTE24, PTE25);
Gfolker 1:8ab4a1e27785 91
Gfolker 1:8ab4a1e27785 92 /* Below are the functions to handle button presses and screens */
Gfolker 1:8ab4a1e27785 93 void ButtonRight(void)//CO screen button
Gfolker 1:8ab4a1e27785 94 {
Gfolker 1:8ab4a1e27785 95 screen = 3;
Gfolker 2:aa8c291b3f9a 96 StartHaptic();
Gfolker 1:8ab4a1e27785 97 }
Gfolker 1:8ab4a1e27785 98
Gfolker 1:8ab4a1e27785 99 void ButtonLeft(void)//AQ screen button
Gfolker 1:8ab4a1e27785 100 {
Gfolker 1:8ab4a1e27785 101 screen = 2;
Gfolker 2:aa8c291b3f9a 102 StartHaptic();
Gfolker 1:8ab4a1e27785 103 }
Gfolker 1:8ab4a1e27785 104
Gfolker 1:8ab4a1e27785 105 void ButtonDown(void)//home screen button
Gfolker 1:8ab4a1e27785 106 {
Gfolker 1:8ab4a1e27785 107 screen = 1;
Gfolker 2:aa8c291b3f9a 108 StartHaptic();
Gfolker 2:aa8c291b3f9a 109 }
Gfolker 2:aa8c291b3f9a 110
Gfolker 2:aa8c291b3f9a 111 void ButtonUp(void) {//toggles bluetooth mode
Gfolker 2:aa8c291b3f9a 112 kw40z_device.ToggleAdvertisementMode();
Gfolker 2:aa8c291b3f9a 113 StartHaptic();
Gfolker 2:aa8c291b3f9a 114 }
Gfolker 2:aa8c291b3f9a 115
Gfolker 2:aa8c291b3f9a 116 void PassKey(void)
Gfolker 2:aa8c291b3f9a 117 {
Gfolker 2:aa8c291b3f9a 118 screen = 4;
Gfolker 1:8ab4a1e27785 119 //StartHaptic();
Gfolker 2:aa8c291b3f9a 120 //strcpy((char *) text,"PAIR CODE");
Gfolker 2:aa8c291b3f9a 121 //oled.TextBox((uint8_t *)text,0,25,95,18);
Gfolker 2:aa8c291b3f9a 122
Gfolker 2:aa8c291b3f9a 123 /* Display Bond Pass Key in a 95px by 18px textbox at x=0,y=40 */
Gfolker 2:aa8c291b3f9a 124 //sprintf(text,"%d", kw40z_device.GetPassKey());
Gfolker 2:aa8c291b3f9a 125 //oled.TextBox((uint8_t *)text,0,40,95,18);
Gfolker 1:8ab4a1e27785 126 }
Gfolker 0:f70b1d60f794 127
Gfolker 0:f70b1d60f794 128 int main(){
Gfolker 0:f70b1d60f794 129
Gfolker 0:f70b1d60f794 130 /* Get OLED Class Default Text Properties */
Gfolker 1:8ab4a1e27785 131 //oled_text_properties_t textProperties = {0};
Gfolker 1:8ab4a1e27785 132 //oled.GetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 133
Gfolker 0:f70b1d60f794 134 /* Turns on the OLED Display*/
Gfolker 1:8ab4a1e27785 135 //oled.PowerON();
Gfolker 1:8ab4a1e27785 136
Gfolker 1:8ab4a1e27785 137 // const uint8_t *image1;
Gfolker 1:8ab4a1e27785 138 //image1 = homescreen_bmp;
Gfolker 1:8ab4a1e27785 139
Gfolker 1:8ab4a1e27785 140 // oled.DrawImage(image1,0,0);
Gfolker 0:f70b1d60f794 141
Gfolker 0:f70b1d60f794 142 /* Fills the screen with solid black */
Gfolker 1:8ab4a1e27785 143 //oled.FillScreen(COLOR_BLACK);
Gfolker 0:f70b1d60f794 144
Gfolker 0:f70b1d60f794 145 /* Display 'GAS LEVELS' at (x = 13,y = 0) */
Gfolker 1:8ab4a1e27785 146 //strcpy((char *) text,"GAS LEVELS");
Gfolker 1:8ab4a1e27785 147 //oled.Label((uint8_t *)text,13,0);
Gfolker 0:f70b1d60f794 148
Gfolker 0:f70b1d60f794 149 /* Change font color to green for Air Quality */
Gfolker 1:8ab4a1e27785 150 //textProperties.fontColor = COLOR_GREEN;
Gfolker 1:8ab4a1e27785 151 //oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 152
Gfolker 0:f70b1d60f794 153 /* Display 'Air Quality: ' at (x = 0, y = 20) */
Gfolker 1:8ab4a1e27785 154 //strcpy(text,"AQ: ");
Gfolker 1:8ab4a1e27785 155 //oled.Label((uint8_t *)text,0,20);
Gfolker 0:f70b1d60f794 156
Gfolker 0:f70b1d60f794 157 /* Change font color to red for Carbon Monoxide */
Gfolker 1:8ab4a1e27785 158 //textProperties.fontColor = COLOR_RED;
Gfolker 1:8ab4a1e27785 159 //oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 160
Gfolker 0:f70b1d60f794 161 /* Display 'CO: ' at (x = 0, y = 40) */
Gfolker 1:8ab4a1e27785 162 //strcpy(text, "CO: ");
Gfolker 1:8ab4a1e27785 163 //oled.Label((uint8_t *)text,0,40);
Gfolker 0:f70b1d60f794 164
Gfolker 0:f70b1d60f794 165 /* Change font color to blue for Average and Total total */
Gfolker 1:8ab4a1e27785 166 //textProperties.fontColor = COLOR_BLUE;
Gfolker 1:8ab4a1e27785 167 //oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 168
Gfolker 0:f70b1d60f794 169 /* Display 'Average: ' at (x = 0, y = 60) */
Gfolker 1:8ab4a1e27785 170 //strcpy(text, "Average: ");
Gfolker 1:8ab4a1e27785 171 //oled.Label((uint8_t *)text, 0, 60);
Gfolker 0:f70b1d60f794 172
Gfolker 0:f70b1d60f794 173 /* Display 'Total: ' at (x = 0, y = 80) */
Gfolker 1:8ab4a1e27785 174 //strcpy(text, "Total: ");
Gfolker 1:8ab4a1e27785 175 //oled.Label((uint8_t *)text,0,80);
Gfolker 0:f70b1d60f794 176
Gfolker 0:f70b1d60f794 177 /* Set text properties to white and right aligned for the dynamic text */
Gfolker 1:8ab4a1e27785 178 //textProperties.fontColor = COLOR_WHITE;
Gfolker 1:8ab4a1e27785 179 //textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
Gfolker 1:8ab4a1e27785 180 //oled.SetTextProperties(&textProperties);
Gfolker 1:8ab4a1e27785 181
Gfolker 1:8ab4a1e27785 182 initModules();
Gfolker 0:f70b1d60f794 183
Gfolker 0:f70b1d60f794 184 /* Subroutine Calls */
Gfolker 2:aa8c291b3f9a 185 sensor_read.attach(&readSensors, 1); /* Read the sensor on a time interval */
Gfolker 2:aa8c291b3f9a 186 A2D_Convert.attach(&CalculatePPM, 1); /* Convert the values read from the sensors to floating point ppm values */
Gfolker 2:aa8c291b3f9a 187 push.attach(&dataQueue, 1); /* Push the value into the set and compute the average */
Gfolker 0:f70b1d60f794 188 ledcolor.attach(&ledColor, 0.5); /* Determine the LED color */
Gfolker 0:f70b1d60f794 189 led_flash.attach(&led_out, 0.25); /* Flash LED based on sensor data */
Gfolker 0:f70b1d60f794 190 buzzer_sound.attach(&buzzer, 0.25); /* Sensor values are sent to buzzer function */
Gfolker 0:f70b1d60f794 191
Gfolker 1:8ab4a1e27785 192 /* Register callbacks to button presses */
Gfolker 1:8ab4a1e27785 193 kw40z_device.attach_buttonDown(&ButtonDown);
Gfolker 1:8ab4a1e27785 194 kw40z_device.attach_buttonLeft(&ButtonLeft);
Gfolker 1:8ab4a1e27785 195 kw40z_device.attach_buttonRight(&ButtonRight);
Gfolker 2:aa8c291b3f9a 196 kw40z_device.attach_buttonUp(&ButtonUp);
Gfolker 2:aa8c291b3f9a 197 kw40z_device.attach_passkey(&PassKey);
Gfolker 1:8ab4a1e27785 198
Gfolker 2:aa8c291b3f9a 199 txThread.start(txTask); /*Start transmitting Sensor Tag Data */
Gfolker 2:aa8c291b3f9a 200
Gfolker 2:aa8c291b3f9a 201 while (1) { /* Loop to process and display data to the OLED */
Gfolker 1:8ab4a1e27785 202
Gfolker 1:8ab4a1e27785 203 /* Get OLED Class Default Text Properties */
Gfolker 1:8ab4a1e27785 204 oled_text_properties_t textProperties = {0};
Gfolker 1:8ab4a1e27785 205 oled.GetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 206
Gfolker 1:8ab4a1e27785 207 /* Set text properties to white and right aligned for the dynamic text */
Gfolker 1:8ab4a1e27785 208 textProperties.fontColor = COLOR_WHITE;
Gfolker 1:8ab4a1e27785 209 textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
Gfolker 1:8ab4a1e27785 210 oled.SetTextProperties(&textProperties);
Gfolker 1:8ab4a1e27785 211
Gfolker 2:aa8c291b3f9a 212 //readSensors(); //read the sensors
Gfolker 2:aa8c291b3f9a 213 //CalculatePPM(); //convert to ppm
Gfolker 2:aa8c291b3f9a 214 //dataQueue(); //push the value into the circular array
Gfolker 1:8ab4a1e27785 215 if (screen == 2){ //Air Quality Screen
Gfolker 2:aa8c291b3f9a 216 //is_drawn1 = 0;
Gfolker 2:aa8c291b3f9a 217 //is_drawn3 = 0;
Gfolker 1:8ab4a1e27785 218 if(!is_drawn2){
Gfolker 2:aa8c291b3f9a 219 is_drawn1 = 0;
Gfolker 2:aa8c291b3f9a 220 is_drawn3 = 0;
Gfolker 2:aa8c291b3f9a 221 is_drawn4 = 0;
Gfolker 1:8ab4a1e27785 222 oled.DrawImage(image2,0,0);
Gfolker 1:8ab4a1e27785 223 is_drawn2 = 1;
Gfolker 1:8ab4a1e27785 224 }
Gfolker 1:8ab4a1e27785 225 sprintf(AQ_level,"%.2f",aq_ppm); /* Print the AQ PPM to the screen */
Gfolker 1:8ab4a1e27785 226 oled.TextBox((uint8_t *)AQ_level,35,76,35,15);
Gfolker 1:8ab4a1e27785 227 }
Gfolker 1:8ab4a1e27785 228 else if (screen == 3){ //Carbon Monoxide Screen
Gfolker 2:aa8c291b3f9a 229 //is_drawn2 = 0;
Gfolker 2:aa8c291b3f9a 230 //is_drawn1 = 0;
Gfolker 1:8ab4a1e27785 231 if (!is_drawn3){
Gfolker 2:aa8c291b3f9a 232 is_drawn2 = 0;
Gfolker 2:aa8c291b3f9a 233 is_drawn1 = 0;
Gfolker 2:aa8c291b3f9a 234 is_drawn4 = 0;
Gfolker 1:8ab4a1e27785 235 oled.DrawImage(image3,0,0);
Gfolker 1:8ab4a1e27785 236 is_drawn3 = 1;
Gfolker 1:8ab4a1e27785 237 }
Gfolker 1:8ab4a1e27785 238 sprintf(CO_level,"%.2f",co_ppm); /* Print the CO PPM to the screen */
Gfolker 1:8ab4a1e27785 239 oled.TextBox((uint8_t *)CO_level,35,76,35,15);
Gfolker 1:8ab4a1e27785 240 }
Gfolker 1:8ab4a1e27785 241 else if (screen == 1) { //Home Screen
Gfolker 2:aa8c291b3f9a 242 //is_drawn3 = 0;
Gfolker 2:aa8c291b3f9a 243 //is_drawn2 = 0;
Gfolker 1:8ab4a1e27785 244 if (!is_drawn1){
Gfolker 2:aa8c291b3f9a 245 is_drawn3 = 0;
Gfolker 2:aa8c291b3f9a 246 is_drawn2 = 0;
Gfolker 2:aa8c291b3f9a 247 is_drawn4 = 0;
Gfolker 1:8ab4a1e27785 248 oled.DrawImage(image1,0,0);
Gfolker 1:8ab4a1e27785 249 is_drawn1 = 1;
Gfolker 1:8ab4a1e27785 250 }
Gfolker 1:8ab4a1e27785 251 sprintf(average, "%.2f", avg); /* Print the average to the screen */
Gfolker 1:8ab4a1e27785 252 oled.TextBox((uint8_t *)average,55,20,35,15);
Gfolker 1:8ab4a1e27785 253 sprintf(total_total, "%.2f", total); /* Print the total to the screen */
Gfolker 1:8ab4a1e27785 254 oled.TextBox((uint8_t *)total_total,55,40,35,15);
Gfolker 1:8ab4a1e27785 255 }
Gfolker 2:aa8c291b3f9a 256
Gfolker 2:aa8c291b3f9a 257 else if (screen == 4){ //BLE Pairing Screen
Gfolker 2:aa8c291b3f9a 258 if (!is_drawn4){
Gfolker 2:aa8c291b3f9a 259 is_drawn3 = 0;
Gfolker 2:aa8c291b3f9a 260 is_drawn2 = 0;
Gfolker 2:aa8c291b3f9a 261 is_drawn1 = 0;
Gfolker 2:aa8c291b3f9a 262 oled.FillScreen(COLOR_BLACK);
Gfolker 2:aa8c291b3f9a 263 is_drawn4 = 1;
Gfolker 2:aa8c291b3f9a 264 }
Gfolker 2:aa8c291b3f9a 265 strcpy((char *) text,"PAIR CODE");
Gfolker 2:aa8c291b3f9a 266 oled.TextBox((uint8_t *)text,0,25,95,18);
Gfolker 2:aa8c291b3f9a 267 /* Display Bond Pass Key in a 95px by 18px textbox at x=0,y=40 */
Gfolker 2:aa8c291b3f9a 268 sprintf(text,"%d", kw40z_device.GetPassKey());
Gfolker 2:aa8c291b3f9a 269 oled.TextBox((uint8_t *)text,0,40,95,18);
Gfolker 2:aa8c291b3f9a 270 }
Gfolker 2:aa8c291b3f9a 271 Thread::wait(500);
Gfolker 1:8ab4a1e27785 272 }
Gfolker 1:8ab4a1e27785 273
Gfolker 1:8ab4a1e27785 274 return 0;
Gfolker 1:8ab4a1e27785 275 }
Gfolker 2:aa8c291b3f9a 276 void txTask(void){
Gfolker 2:aa8c291b3f9a 277 while (1){
Gfolker 2:aa8c291b3f9a 278 /*Notify Hexiwear App that it is running Sensor Tag mode*/
Gfolker 2:aa8c291b3f9a 279 kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG);
Gfolker 2:aa8c291b3f9a 280 kw40z_device.SendTemperature(100*aq_ppm); //send ppm Air Quality Click value
Gfolker 2:aa8c291b3f9a 281 kw40z_device.SendHumidity(100*co_ppm); //send ppm CO click value
Gfolker 2:aa8c291b3f9a 282 kw40z_device.SendPressure(100*total); //send average
Gfolker 2:aa8c291b3f9a 283 Thread::wait(1000);
Gfolker 2:aa8c291b3f9a 284 }
Gfolker 2:aa8c291b3f9a 285 }
Gfolker 1:8ab4a1e27785 286 void initModules() { /* Function to initialize the system */
Gfolker 1:8ab4a1e27785 287
Gfolker 1:8ab4a1e27785 288 /* Turns on the OLED Display*/
Gfolker 1:8ab4a1e27785 289 oled.PowerON();
Gfolker 1:8ab4a1e27785 290
Gfolker 1:8ab4a1e27785 291 image1 = homescreen_bmp;
Gfolker 1:8ab4a1e27785 292 image2 = airquality_bmp;
Gfolker 1:8ab4a1e27785 293 image3 = co_bmp;
Gfolker 1:8ab4a1e27785 294
Gfolker 1:8ab4a1e27785 295 /* Set text properties to white and right aligned for the dynamic text */
Gfolker 1:8ab4a1e27785 296 //textProperties.fontColor = COLOR_WHITE;
Gfolker 1:8ab4a1e27785 297 //textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
Gfolker 1:8ab4a1e27785 298 //oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 299 }
Gfolker 0:f70b1d60f794 300
Gfolker 0:f70b1d60f794 301 void readSensors(){ /* Function to read sensors */
Gfolker 0:f70b1d60f794 302
Gfolker 0:f70b1d60f794 303 /* Grab the analog signal from the sensors as 16 bit unsigned integers */
Gfolker 0:f70b1d60f794 304 aq_total = AQSensor.read_u16();
Gfolker 0:f70b1d60f794 305 co_total = COSensor.read_u16();
Gfolker 0:f70b1d60f794 306 /* Grab the analog signal from the sensors as floats */
Gfolker 0:f70b1d60f794 307 //aq_total = AQSensor.read();
Gfolker 0:f70b1d60f794 308 //co_total = AQSensor.read();
Gfolker 0:f70b1d60f794 309
Gfolker 0:f70b1d60f794 310 }
Gfolker 0:f70b1d60f794 311
Gfolker 0:f70b1d60f794 312 void ledColor(){ /* Function to determine the LED color */
Gfolker 0:f70b1d60f794 313
Gfolker 1:8ab4a1e27785 314 if ((total - avg) <= 10) {
Gfolker 0:f70b1d60f794 315 led = green;
Gfolker 0:f70b1d60f794 316 led_color = led; /* Store the LED color for the flash function */
Gfolker 0:f70b1d60f794 317 }
Gfolker 1:8ab4a1e27785 318 else if ((total - avg) > 10 && (total - avg) < 50) {
Gfolker 0:f70b1d60f794 319 led = yellow;
Gfolker 0:f70b1d60f794 320 led_color = led; /* Store the LED color for the flash function */
Gfolker 0:f70b1d60f794 321 }
Gfolker 1:8ab4a1e27785 322 else if ((total - avg >= 50) or total >= 100) {
Gfolker 0:f70b1d60f794 323 led = red;
Gfolker 0:f70b1d60f794 324 led_color = led; /* Store the LED color for the flash function */
Gfolker 0:f70b1d60f794 325 }
Gfolker 0:f70b1d60f794 326 }
Gfolker 0:f70b1d60f794 327
Gfolker 0:f70b1d60f794 328 void led_out() { /* Function to flash LEDs */
Gfolker 0:f70b1d60f794 329
Gfolker 0:f70b1d60f794 330 if (led == green) {return;} /* If green, don't blink */
Gfolker 0:f70b1d60f794 331 else if (led == black) {led = led_color;}
Gfolker 0:f70b1d60f794 332 else {led = black;}
Gfolker 0:f70b1d60f794 333
Gfolker 0:f70b1d60f794 334 }
Gfolker 0:f70b1d60f794 335
Gfolker 0:f70b1d60f794 336 void buzzer() { /* Function to handle the buzzer sound */
Gfolker 0:f70b1d60f794 337
Gfolker 1:8ab4a1e27785 338 if ((total - avg) <=25){ /* No buzzer sound if PPM is under 10 */
Gfolker 0:f70b1d60f794 339 Buzzer.period_us(0);
Gfolker 0:f70b1d60f794 340 is_sounding = false;
Gfolker 0:f70b1d60f794 341 }
Gfolker 0:f70b1d60f794 342
Gfolker 1:8ab4a1e27785 343 else if ((total - avg) > 25 and (total - avg) < 50) {
Gfolker 0:f70b1d60f794 344 if (is_sounding == false){ /* If the buzzer is not triggered, trigger */
Gfolker 0:f70b1d60f794 345 Buzzer.period_us(B_4); /* Period of B4 */
Gfolker 0:f70b1d60f794 346 Buzzer.write(0.50f); /* 50% Duty Cycle on the Tone */
Gfolker 0:f70b1d60f794 347 is_sounding = true; /* Signal that the buzzer is currently triggering */
Gfolker 0:f70b1d60f794 348 }
Gfolker 0:f70b1d60f794 349 else {
Gfolker 0:f70b1d60f794 350 Buzzer.period_us(0); /* Turn off the buzzer (Period = 0us)*/
Gfolker 0:f70b1d60f794 351 is_sounding = false; /* Signal that the buzzer is no longer triggering */
Gfolker 0:f70b1d60f794 352 }
Gfolker 0:f70b1d60f794 353 }
Gfolker 0:f70b1d60f794 354
Gfolker 1:8ab4a1e27785 355 else if ((total - avg) >= 50 or total >= 100){
Gfolker 0:f70b1d60f794 356 if (is_sounding == false){
Gfolker 0:f70b1d60f794 357 Buzzer.period_us(B_5); /* Period of B5 */
Gfolker 0:f70b1d60f794 358 Buzzer.write(0.50f); /* 50% Duty Cycle on the Tone */
Gfolker 0:f70b1d60f794 359 is_sounding = true;
Gfolker 0:f70b1d60f794 360 }
Gfolker 0:f70b1d60f794 361 else {
Gfolker 0:f70b1d60f794 362 Buzzer.period_us(0); /* Turn off the buzzer */
Gfolker 0:f70b1d60f794 363 is_sounding = false;
Gfolker 0:f70b1d60f794 364 }
Gfolker 0:f70b1d60f794 365 }
Gfolker 0:f70b1d60f794 366 }
Gfolker 0:f70b1d60f794 367
Gfolker 0:f70b1d60f794 368 void CalculatePPM(){ /* Function to convert the analog signals to digital based on 16 bit adc steps */
Gfolker 0:f70b1d60f794 369
Gfolker 0:f70b1d60f794 370 const double AQ_Rl = 20000.0; // AQ_Rl (20kOhm) - Load resistance for AQ sensor
Gfolker 0:f70b1d60f794 371 const double CO_Rl = 18500.0; // CO_Rl (18.5kOhm) - Load resistance for CO sensor
Gfolker 0:f70b1d60f794 372 const double Vadc_33 = 0.0000503548; // ADC step 3,3V/65535 0.00503mV (16bit ADC)
Gfolker 0:f70b1d60f794 373 //const double Vadc_5 = 5.0/65535; // ADC step 5.0V/2^16 (65535, 16bit ADC)
Gfolker 0:f70b1d60f794 374 double Vrl; // Output voltage
Gfolker 0:f70b1d60f794 375 double Rs; // Rs (Ohm) - Sensor resistance
Gfolker 0:f70b1d60f794 376 double ratio; // Rs/Rl ratio
Gfolker 0:f70b1d60f794 377 double lgPPM;
Gfolker 0:f70b1d60f794 378
Gfolker 0:f70b1d60f794 379 Vrl = (double)aq_total * Vadc_33; // For 3.3V Vcc use Vadc_33
Gfolker 0:f70b1d60f794 380 Rs = AQ_Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance
Gfolker 0:f70b1d60f794 381 ratio = Rs/AQ_Rl; // Calculate ratio
Gfolker 1:8ab4a1e27785 382 lgPPM = (log10(ratio) * -0.8) + 0.9;
Gfolker 1:8ab4a1e27785 383 aq_ppm = 6* pow(10,lgPPM) - 12; // Calculate air quality ppm
Gfolker 2:aa8c291b3f9a 384 //aq_ppm = 24.1; //used for BLE testing
Gfolker 0:f70b1d60f794 385
Gfolker 0:f70b1d60f794 386 Vrl = (double)co_total * Vadc_33; // For 3.3V Vcc use Vadc_33
Gfolker 0:f70b1d60f794 387 Rs = CO_Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance
Gfolker 0:f70b1d60f794 388 ratio = Rs/CO_Rl; // Calculate ratio
Gfolker 1:8ab4a1e27785 389 lgPPM = (log10(ratio) * -0.8) + 0.9;
Gfolker 1:8ab4a1e27785 390 co_ppm = 6* pow(10,lgPPM) - 12; // Calculate carbon monoxide ppm
Gfolker 2:aa8c291b3f9a 391 //co_ppm = 11.0; //used for BLE testing
Gfolker 1:8ab4a1e27785 392
Gfolker 1:8ab4a1e27785 393 if (aq_ppm < 0)
Gfolker 1:8ab4a1e27785 394 aq_ppm = 0; //prevents underflow
Gfolker 1:8ab4a1e27785 395 else if (aq_ppm >= 1000)
Gfolker 1:8ab4a1e27785 396 aq_ppm = 999.99; //prevents overflow
Gfolker 1:8ab4a1e27785 397
Gfolker 1:8ab4a1e27785 398 if (co_ppm <0)
Gfolker 1:8ab4a1e27785 399 co_ppm = 0;
Gfolker 1:8ab4a1e27785 400 else if (co_ppm >= 1000)
Gfolker 1:8ab4a1e27785 401 co_ppm = 999.99;
Gfolker 1:8ab4a1e27785 402
Gfolker 1:8ab4a1e27785 403 /* Calculate the total */
Gfolker 1:8ab4a1e27785 404 total = co_ppm + aq_ppm;
Gfolker 1:8ab4a1e27785 405 if (total < 0)
Gfolker 1:8ab4a1e27785 406 total = 0;
Gfolker 1:8ab4a1e27785 407 else if (total >= 1000)
Gfolker 1:8ab4a1e27785 408 total = 999.99;
Gfolker 1:8ab4a1e27785 409 }
Gfolker 1:8ab4a1e27785 410
Gfolker 1:8ab4a1e27785 411 void dataQueue()
Gfolker 1:8ab4a1e27785 412 { /* Beginning of function */
Gfolker 0:f70b1d60f794 413
Gfolker 1:8ab4a1e27785 414 if (pushIndex != SIZE and !calc){ /* Initially pushing values into the set */
Gfolker 1:8ab4a1e27785 415 dataSet[pushIndex] = total; //push value into the queue
Gfolker 1:8ab4a1e27785 416 sum += dataSet[pushIndex]; //add the value to the sum
Gfolker 1:8ab4a1e27785 417 pushIndex++; //increment the push index
Gfolker 1:8ab4a1e27785 418
Gfolker 1:8ab4a1e27785 419 if (pushIndex == SIZE){
Gfolker 1:8ab4a1e27785 420 avg = sum / SIZE; //compute the average once the queue is full
Gfolker 1:8ab4a1e27785 421 calc = true; //flag calc
Gfolker 1:8ab4a1e27785 422 pushIndex = 0; //reset the push index back to 0
Gfolker 1:8ab4a1e27785 423 }
Gfolker 1:8ab4a1e27785 424 }
Gfolker 1:8ab4a1e27785 425
Gfolker 1:8ab4a1e27785 426 else if (pushIndex != SIZE and calc){ /* Pushing values into the set once the set is full */
Gfolker 1:8ab4a1e27785 427 sum -= dataSet[pushIndex]; //subtract the value to be overriden from the sum
Gfolker 1:8ab4a1e27785 428 dataSet[pushIndex] = total; //push the value into the set
Gfolker 1:8ab4a1e27785 429 sum += dataSet[pushIndex]; //add the value to the sum
Gfolker 1:8ab4a1e27785 430 avg = sum / SIZE;
Gfolker 1:8ab4a1e27785 431 pushIndex++; //increment the push index
Gfolker 1:8ab4a1e27785 432
Gfolker 1:8ab4a1e27785 433 if (pushIndex == SIZE)
Gfolker 1:8ab4a1e27785 434 pushIndex = 0; //reset the push index back to 0
Gfolker 1:8ab4a1e27785 435 }
Gfolker 1:8ab4a1e27785 436
Gfolker 1:8ab4a1e27785 437 } /* End of function */
Gfolker 1:8ab4a1e27785 438
Gfolker 1:8ab4a1e27785 439 void StartHaptic(void)
Gfolker 1:8ab4a1e27785 440 {
Gfolker 2:aa8c291b3f9a 441 hapticTimer.start(75);
Gfolker 1:8ab4a1e27785 442 haptic = 1;
Gfolker 1:8ab4a1e27785 443 }
Gfolker 1:8ab4a1e27785 444
Gfolker 1:8ab4a1e27785 445 void StopHaptic(void const *n) {
Gfolker 1:8ab4a1e27785 446 haptic = 0;
Gfolker 1:8ab4a1e27785 447 hapticTimer.stop();
Gfolker 0:f70b1d60f794 448 }