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:
Wed Mar 15 19:14:55 2017 +0000
Revision:
0:f70b1d60f794
Child:
1:8ab4a1e27785
v1.0 of Hexiwear Sensor system. Currently able to detect air quality and carbon monoxide and display to the screen with alerts on the PWM buzzer click module and RGB LED.

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 0:f70b1d60f794 7 #include <iostream> /* Used for debugging */
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 0:f70b1d60f794 15
Gfolker 0:f70b1d60f794 16 PwmOut Buzzer(PTA10); /* Buzzer is attached to docking station port 1 */
Gfolker 0:f70b1d60f794 17
Gfolker 0:f70b1d60f794 18 AnalogIn AQSensor(PTB3); /* Air Quality sensor is attached to docking station port 2 */
Gfolker 0:f70b1d60f794 19 AnalogIn COSensor(PTB6); /* Carbon Monoxide sensor is attached to docking station port 3 */
Gfolker 0:f70b1d60f794 20
Gfolker 0:f70b1d60f794 21 BusOut led(PTC8, PTD0, PTC9); /* RGB Port Configurations */
Gfolker 0:f70b1d60f794 22
Gfolker 0:f70b1d60f794 23 const int green = 5,
Gfolker 0:f70b1d60f794 24 red = 6, /* LED Colors */
Gfolker 0:f70b1d60f794 25 black = 7,
Gfolker 0:f70b1d60f794 26 yellow = 4;
Gfolker 0:f70b1d60f794 27
Gfolker 0:f70b1d60f794 28 bool is_sounding = false; /* Set to high if the buzzer is going off */
Gfolker 0:f70b1d60f794 29
Gfolker 0:f70b1d60f794 30 int led_color; /* Variable to hold the current LED color */
Gfolker 0:f70b1d60f794 31
Gfolker 0:f70b1d60f794 32 Ticker sensor_read, /* Used for the read sensor subroutine call */
Gfolker 0:f70b1d60f794 33 buzzer_sound, /* Used for the sound buzzer subroutine call */
Gfolker 0:f70b1d60f794 34 led_flash, /* Used to determine the flash rate */
Gfolker 0:f70b1d60f794 35 ledcolor, /* Used to determine the LED color */
Gfolker 0:f70b1d60f794 36 A2D_Convert; /* Used to convert the analog signal to digital */
Gfolker 0:f70b1d60f794 37
Gfolker 0:f70b1d60f794 38 float B_4 = 1000000/Ti4, /* Tones that will play on the buzzer click */
Gfolker 0:f70b1d60f794 39 B_5 = 1000000/Ti5;
Gfolker 0:f70b1d60f794 40
Gfolker 0:f70b1d60f794 41 char text[20]; /* Static Text Buffer for OLED Display */
Gfolker 0:f70b1d60f794 42 char AQ_level[20]; /* Dynamic Text Buffer for AQ total */
Gfolker 0:f70b1d60f794 43 char CO_level[20]; /* Dynamic Text Buffer for CO total */
Gfolker 0:f70b1d60f794 44 char average[20]; /* Dynamic Text Buffer for the Average total */
Gfolker 0:f70b1d60f794 45 char total_total[20]; /* Dynamic Text Buffer for the Total total */
Gfolker 0:f70b1d60f794 46
Gfolker 0:f70b1d60f794 47 /* Either unit16_t or float */
Gfolker 0:f70b1d60f794 48 double total, /* Variable to store the total total */
Gfolker 0:f70b1d60f794 49 aq_ppm, /* Variable used to store the AQ PPM */
Gfolker 0:f70b1d60f794 50 co_ppm, /* Variable used to store the CO PPM */
Gfolker 0:f70b1d60f794 51 avg; /* Variable to store the average total */
Gfolker 0:f70b1d60f794 52
Gfolker 0:f70b1d60f794 53 uint16_t aq_total, /* Variable to store the AQ total */
Gfolker 0:f70b1d60f794 54 co_total; /* Variable to store the CO total */
Gfolker 0:f70b1d60f794 55
Gfolker 0:f70b1d60f794 56 int main(){
Gfolker 0:f70b1d60f794 57
Gfolker 0:f70b1d60f794 58 /* Instantiate the SSD1351 OLED Driver */
Gfolker 0:f70b1d60f794 59 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15);
Gfolker 0:f70b1d60f794 60
Gfolker 0:f70b1d60f794 61 /* Get OLED Class Default Text Properties */
Gfolker 0:f70b1d60f794 62 oled_text_properties_t textProperties = {0};
Gfolker 0:f70b1d60f794 63 oled.GetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 64
Gfolker 0:f70b1d60f794 65 /* Turns on the OLED Display*/
Gfolker 0:f70b1d60f794 66 oled.PowerON();
Gfolker 0:f70b1d60f794 67
Gfolker 0:f70b1d60f794 68 /* Fills the screen with solid black */
Gfolker 0:f70b1d60f794 69 oled.FillScreen(COLOR_BLACK);
Gfolker 0:f70b1d60f794 70
Gfolker 0:f70b1d60f794 71 /* Display 'GAS LEVELS' at (x = 13,y = 0) */
Gfolker 0:f70b1d60f794 72 strcpy((char *) text,"GAS LEVELS");
Gfolker 0:f70b1d60f794 73 oled.Label((uint8_t *)text,13,0);
Gfolker 0:f70b1d60f794 74
Gfolker 0:f70b1d60f794 75 /* Change font color to green for Air Quality */
Gfolker 0:f70b1d60f794 76 textProperties.fontColor = COLOR_GREEN;
Gfolker 0:f70b1d60f794 77 oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 78
Gfolker 0:f70b1d60f794 79 /* Display 'Air Quality: ' at (x = 0, y = 20) */
Gfolker 0:f70b1d60f794 80 strcpy(text,"AQ: ");
Gfolker 0:f70b1d60f794 81 oled.Label((uint8_t *)text,0,20);
Gfolker 0:f70b1d60f794 82
Gfolker 0:f70b1d60f794 83 /* Change font color to red for Carbon Monoxide */
Gfolker 0:f70b1d60f794 84 textProperties.fontColor = COLOR_RED;
Gfolker 0:f70b1d60f794 85 oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 86
Gfolker 0:f70b1d60f794 87 /* Display 'CO: ' at (x = 0, y = 40) */
Gfolker 0:f70b1d60f794 88 strcpy(text, "CO: ");
Gfolker 0:f70b1d60f794 89 oled.Label((uint8_t *)text,0,40);
Gfolker 0:f70b1d60f794 90
Gfolker 0:f70b1d60f794 91 /* Change font color to blue for Average and Total total */
Gfolker 0:f70b1d60f794 92 textProperties.fontColor = COLOR_BLUE;
Gfolker 0:f70b1d60f794 93 oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 94
Gfolker 0:f70b1d60f794 95 /* Display 'Average: ' at (x = 0, y = 60) */
Gfolker 0:f70b1d60f794 96 strcpy(text, "Average: ");
Gfolker 0:f70b1d60f794 97 oled.Label((uint8_t *)text, 0, 60);
Gfolker 0:f70b1d60f794 98
Gfolker 0:f70b1d60f794 99 /* Display 'Total: ' at (x = 0, y = 80) */
Gfolker 0:f70b1d60f794 100 strcpy(text, "Total: ");
Gfolker 0:f70b1d60f794 101 oled.Label((uint8_t *)text,0,80);
Gfolker 0:f70b1d60f794 102
Gfolker 0:f70b1d60f794 103 /* Set text properties to white and right aligned for the dynamic text */
Gfolker 0:f70b1d60f794 104 textProperties.fontColor = COLOR_WHITE;
Gfolker 0:f70b1d60f794 105 textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
Gfolker 0:f70b1d60f794 106 oled.SetTextProperties(&textProperties);
Gfolker 0:f70b1d60f794 107
Gfolker 0:f70b1d60f794 108 /* Subroutine Calls */
Gfolker 0:f70b1d60f794 109 sensor_read.attach(&readSensors, 1); /* Read the sensor on a time interval (Currently 3s) */
Gfolker 0:f70b1d60f794 110 A2D_Convert.attach(&CalculatePPM, 1); /* Convert the values read from the sensors to 16 bit integers */
Gfolker 0:f70b1d60f794 111 ledcolor.attach(&ledColor, 0.5); /* Determine the LED color */
Gfolker 0:f70b1d60f794 112 led_flash.attach(&led_out, 0.25); /* Flash LED based on sensor data */
Gfolker 0:f70b1d60f794 113 buzzer_sound.attach(&buzzer, 0.25); /* Sensor values are sent to buzzer function */
Gfolker 0:f70b1d60f794 114
Gfolker 0:f70b1d60f794 115 while (1) { /* Loop to process and display data */
Gfolker 0:f70b1d60f794 116
Gfolker 0:f70b1d60f794 117 /* */
Gfolker 0:f70b1d60f794 118 /* */
Gfolker 0:f70b1d60f794 119 /* */
Gfolker 0:f70b1d60f794 120 /* Code to process sensor data goes here */
Gfolker 0:f70b1d60f794 121 /* */
Gfolker 0:f70b1d60f794 122 /* */
Gfolker 0:f70b1d60f794 123 /* */
Gfolker 0:f70b1d60f794 124
Gfolker 0:f70b1d60f794 125 sprintf(AQ_level,"%.2f",aq_ppm); /* Print the AQ PPM to the screen */
Gfolker 0:f70b1d60f794 126
Gfolker 0:f70b1d60f794 127 /* Display time reading in 35px by 15px textbox at(x=55, y=40) */
Gfolker 0:f70b1d60f794 128 oled.TextBox((uint8_t *)AQ_level,55,20,35,15); //Increase textbox for more digits
Gfolker 0:f70b1d60f794 129
Gfolker 0:f70b1d60f794 130 sprintf(CO_level,"%.2f",co_ppm); /* Print the CO PPM to the screen */
Gfolker 0:f70b1d60f794 131
Gfolker 0:f70b1d60f794 132 oled.TextBox((uint8_t *)CO_level,55,40,35,15);
Gfolker 0:f70b1d60f794 133
Gfolker 0:f70b1d60f794 134 sprintf(average, "%.2f", avg); /* Print the average to the screen */
Gfolker 0:f70b1d60f794 135
Gfolker 0:f70b1d60f794 136 oled.TextBox((uint8_t *)average,55,60,35,15);
Gfolker 0:f70b1d60f794 137
Gfolker 0:f70b1d60f794 138 sprintf(total_total, "%.2f", total); /* Print the total to the screen */
Gfolker 0:f70b1d60f794 139
Gfolker 0:f70b1d60f794 140 oled.TextBox((uint8_t *)total_total,55,80,35,15);
Gfolker 0:f70b1d60f794 141
Gfolker 0:f70b1d60f794 142 }
Gfolker 0:f70b1d60f794 143
Gfolker 0:f70b1d60f794 144 return 0;
Gfolker 0:f70b1d60f794 145 }
Gfolker 0:f70b1d60f794 146
Gfolker 0:f70b1d60f794 147 void readSensors(){ /* Function to read sensors */
Gfolker 0:f70b1d60f794 148
Gfolker 0:f70b1d60f794 149 /* Grab the analog signal from the sensors as 16 bit unsigned integers */
Gfolker 0:f70b1d60f794 150 aq_total = AQSensor.read_u16();
Gfolker 0:f70b1d60f794 151 co_total = COSensor.read_u16();
Gfolker 0:f70b1d60f794 152 /* Grab the analog signal from the sensors as floats */
Gfolker 0:f70b1d60f794 153 //aq_total = AQSensor.read();
Gfolker 0:f70b1d60f794 154 //co_total = AQSensor.read();
Gfolker 0:f70b1d60f794 155
Gfolker 0:f70b1d60f794 156 }
Gfolker 0:f70b1d60f794 157
Gfolker 0:f70b1d60f794 158 void ledColor(){ /* Function to determine the LED color */
Gfolker 0:f70b1d60f794 159
Gfolker 0:f70b1d60f794 160 if (total <= 10) {
Gfolker 0:f70b1d60f794 161 led = green;
Gfolker 0:f70b1d60f794 162 led_color = led; /* Store the LED color for the flash function */
Gfolker 0:f70b1d60f794 163 }
Gfolker 0:f70b1d60f794 164 else if (total > 10 && total < 50) {
Gfolker 0:f70b1d60f794 165 led = yellow;
Gfolker 0:f70b1d60f794 166 led_color = led; /* Store the LED color for the flash function */
Gfolker 0:f70b1d60f794 167 }
Gfolker 0:f70b1d60f794 168 else if (total >= 50) {
Gfolker 0:f70b1d60f794 169 led = red;
Gfolker 0:f70b1d60f794 170 led_color = led; /* Store the LED color for the flash function */
Gfolker 0:f70b1d60f794 171 }
Gfolker 0:f70b1d60f794 172 }
Gfolker 0:f70b1d60f794 173
Gfolker 0:f70b1d60f794 174 void led_out() { /* Function to flash LEDs */
Gfolker 0:f70b1d60f794 175
Gfolker 0:f70b1d60f794 176 if (led == green) {return;} /* If green, don't blink */
Gfolker 0:f70b1d60f794 177 else if (led == black) {led = led_color;}
Gfolker 0:f70b1d60f794 178 else {led = black;}
Gfolker 0:f70b1d60f794 179
Gfolker 0:f70b1d60f794 180 }
Gfolker 0:f70b1d60f794 181
Gfolker 0:f70b1d60f794 182 void buzzer() { /* Function to handle the buzzer sound */
Gfolker 0:f70b1d60f794 183
Gfolker 0:f70b1d60f794 184 if (total <=25){ /* No buzzer sound if PPM is under 10 */
Gfolker 0:f70b1d60f794 185 Buzzer.period_us(0);
Gfolker 0:f70b1d60f794 186 is_sounding = false;
Gfolker 0:f70b1d60f794 187 }
Gfolker 0:f70b1d60f794 188
Gfolker 0:f70b1d60f794 189 else if (total > 25 and total < 50) {
Gfolker 0:f70b1d60f794 190 if (is_sounding == false){ /* If the buzzer is not triggered, trigger */
Gfolker 0:f70b1d60f794 191 Buzzer.period_us(B_4); /* Period of B4 */
Gfolker 0:f70b1d60f794 192 Buzzer.write(0.50f); /* 50% Duty Cycle on the Tone */
Gfolker 0:f70b1d60f794 193 is_sounding = true; /* Signal that the buzzer is currently triggering */
Gfolker 0:f70b1d60f794 194 }
Gfolker 0:f70b1d60f794 195 else {
Gfolker 0:f70b1d60f794 196 Buzzer.period_us(0); /* Turn off the buzzer (Period = 0us)*/
Gfolker 0:f70b1d60f794 197 is_sounding = false; /* Signal that the buzzer is no longer triggering */
Gfolker 0:f70b1d60f794 198 }
Gfolker 0:f70b1d60f794 199 }
Gfolker 0:f70b1d60f794 200
Gfolker 0:f70b1d60f794 201 else if (total >= 50){
Gfolker 0:f70b1d60f794 202 if (is_sounding == false){
Gfolker 0:f70b1d60f794 203 Buzzer.period_us(B_5); /* Period of B5 */
Gfolker 0:f70b1d60f794 204 Buzzer.write(0.50f); /* 50% Duty Cycle on the Tone */
Gfolker 0:f70b1d60f794 205 is_sounding = true;
Gfolker 0:f70b1d60f794 206 }
Gfolker 0:f70b1d60f794 207 else {
Gfolker 0:f70b1d60f794 208 Buzzer.period_us(0); /* Turn off the buzzer */
Gfolker 0:f70b1d60f794 209 is_sounding = false;
Gfolker 0:f70b1d60f794 210 }
Gfolker 0:f70b1d60f794 211 }
Gfolker 0:f70b1d60f794 212 }
Gfolker 0:f70b1d60f794 213
Gfolker 0:f70b1d60f794 214 void CalculatePPM(){ /* Function to convert the analog signals to digital based on 16 bit adc steps */
Gfolker 0:f70b1d60f794 215
Gfolker 0:f70b1d60f794 216 const double AQ_Rl = 20000.0; // AQ_Rl (20kOhm) - Load resistance for AQ sensor
Gfolker 0:f70b1d60f794 217 const double CO_Rl = 18500.0; // CO_Rl (18.5kOhm) - Load resistance for CO sensor
Gfolker 0:f70b1d60f794 218 const double Vadc_33 = 0.0000503548; // ADC step 3,3V/65535 0.00503mV (16bit ADC)
Gfolker 0:f70b1d60f794 219 //const double Vadc_5 = 5.0/65535; // ADC step 5.0V/2^16 (65535, 16bit ADC)
Gfolker 0:f70b1d60f794 220 double Vrl; // Output voltage
Gfolker 0:f70b1d60f794 221 double Rs; // Rs (Ohm) - Sensor resistance
Gfolker 0:f70b1d60f794 222 double ratio; // Rs/Rl ratio
Gfolker 0:f70b1d60f794 223 double lgPPM;
Gfolker 0:f70b1d60f794 224
Gfolker 0:f70b1d60f794 225 Vrl = (double)aq_total * Vadc_33; // For 3.3V Vcc use Vadc_33
Gfolker 0:f70b1d60f794 226 Rs = AQ_Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance
Gfolker 0:f70b1d60f794 227 ratio = Rs/AQ_Rl; // Calculate ratio
Gfolker 0:f70b1d60f794 228 lgPPM = (log10(ratio) * -0.8) + 0.9; // Calculate air quality ppm
Gfolker 0:f70b1d60f794 229 aq_ppm = 6* pow(10,lgPPM); // Calculate air quality ppm
Gfolker 0:f70b1d60f794 230
Gfolker 0:f70b1d60f794 231 Vrl = (double)co_total * Vadc_33; // For 3.3V Vcc use Vadc_33
Gfolker 0:f70b1d60f794 232 Rs = CO_Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance
Gfolker 0:f70b1d60f794 233 ratio = Rs/CO_Rl; // Calculate ratio
Gfolker 0:f70b1d60f794 234 lgPPM = (log10(ratio) * -0.8) + 0.9; // Calculate carbon monoxide ppm
Gfolker 0:f70b1d60f794 235 co_ppm = 6* pow(10,lgPPM); // Calculate carbon monoxide ppm
Gfolker 0:f70b1d60f794 236
Gfolker 0:f70b1d60f794 237 /* Calculate the average and total */
Gfolker 0:f70b1d60f794 238 total = co_ppm + aq_ppm;
Gfolker 0:f70b1d60f794 239 avg = (total)/2;
Gfolker 0:f70b1d60f794 240 }