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:
Fri Apr 28 07:26:16 2017 +0000
Revision:
3:24b332b8e41d
Parent:
2:aa8c291b3f9a
Final version of the project - BLE integrated, code cleaned up, ARC calculation implemented, all user interface screens/button presses implemented, alert states tested and verified

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