
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
Revision 3:24b332b8e41d, committed 2017-04-28
- Comitter:
- Gfolker
- Date:
- Fri Apr 28 07:26:16 2017 +0000
- Parent:
- 2:aa8c291b3f9a
- Commit message:
- 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
Changed in this revision
driver.cpp | Show annotated file Show diff for this revision Revisions of this file |
pwm_tone.cpp | Show diff for this revision Revisions of this file |
diff -r aa8c291b3f9a -r 24b332b8e41d driver.cpp --- a/driver.cpp Tue Mar 28 21:41:06 2017 +0000 +++ b/driver.cpp Fri Apr 28 07:26:16 2017 +0000 @@ -35,6 +35,7 @@ bool is_drawn2 = 0; bool is_drawn3 = 0; bool is_drawn4 = 0; +bool is_ble = 0; //detects if the device is currently running BLE mode /* Screens */ const uint8_t *image1; //homescreen @@ -67,11 +68,14 @@ char CO_level[20]; /* Dynamic Text Buffer for CO total */ char average[20]; /* Dynamic Text Buffer for the Average total */ char total_total[20]; /* Dynamic Text Buffer for the Total total */ +char ble_status[20]; /* Informs the user if BLE is activated or disabled */ /* Either unit16_t or double */ double total, /* Variable to store the total total */ aq_ppm, /* Variable used to store the AQ PPM */ - co_ppm; /* Variable used to store the CO PPM */ + co_ppm, /* Variable used to store the CO PPM */ + prev_value; /* Used for ARC Calculation */ +double ARC; uint16_t aq_total, /* Variable to store the AQ total */ co_total; /* Variable to store the CO total */ @@ -92,93 +96,42 @@ /* Below are the functions to handle button presses and screens */ void ButtonRight(void)//CO screen button { + StartHaptic(); screen = 3; - StartHaptic(); } void ButtonLeft(void)//AQ screen button { + StartHaptic(); screen = 2; - StartHaptic(); } void ButtonDown(void)//home screen button { + StartHaptic(); screen = 1; - StartHaptic(); } void ButtonUp(void) {//toggles bluetooth mode + StartHaptic(); + screen = 4; kw40z_device.ToggleAdvertisementMode(); - StartHaptic(); + is_ble = !is_ble; } void PassKey(void) { - screen = 4; - //StartHaptic(); - //strcpy((char *) text,"PAIR CODE"); - //oled.TextBox((uint8_t *)text,0,25,95,18); + StartHaptic(); + strcpy((char *) text,"PAIR CODE"); + oled.TextBox((uint8_t *)text,0,25,95,18); /* Display Bond Pass Key in a 95px by 18px textbox at x=0,y=40 */ - //sprintf(text,"%d", kw40z_device.GetPassKey()); - //oled.TextBox((uint8_t *)text,0,40,95,18); + sprintf(text,"%d", kw40z_device.GetPassKey()); + oled.TextBox((uint8_t *)text,0,40,95,18); } int main(){ - /* Get OLED Class Default Text Properties */ - //oled_text_properties_t textProperties = {0}; - //oled.GetTextProperties(&textProperties); - - /* Turns on the OLED Display*/ - //oled.PowerON(); - - // const uint8_t *image1; - //image1 = homescreen_bmp; - - // oled.DrawImage(image1,0,0); - - /* Fills the screen with solid black */ - //oled.FillScreen(COLOR_BLACK); - - /* Display 'GAS LEVELS' at (x = 13,y = 0) */ - //strcpy((char *) text,"GAS LEVELS"); - //oled.Label((uint8_t *)text,13,0); - - /* Change font color to green for Air Quality */ - //textProperties.fontColor = COLOR_GREEN; - //oled.SetTextProperties(&textProperties); - - /* Display 'Air Quality: ' at (x = 0, y = 20) */ - //strcpy(text,"AQ: "); - //oled.Label((uint8_t *)text,0,20); - - /* Change font color to red for Carbon Monoxide */ - //textProperties.fontColor = COLOR_RED; - //oled.SetTextProperties(&textProperties); - - /* Display 'CO: ' at (x = 0, y = 40) */ - //strcpy(text, "CO: "); - //oled.Label((uint8_t *)text,0,40); - - /* Change font color to blue for Average and Total total */ - //textProperties.fontColor = COLOR_BLUE; - //oled.SetTextProperties(&textProperties); - - /* Display 'Average: ' at (x = 0, y = 60) */ - //strcpy(text, "Average: "); - //oled.Label((uint8_t *)text, 0, 60); - - /* Display 'Total: ' at (x = 0, y = 80) */ - //strcpy(text, "Total: "); - //oled.Label((uint8_t *)text,0,80); - - /* Set text properties to white and right aligned for the dynamic text */ - //textProperties.fontColor = COLOR_WHITE; - //textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT; - //oled.SetTextProperties(&textProperties); - initModules(); /* Subroutine Calls */ @@ -204,17 +157,12 @@ oled_text_properties_t textProperties = {0}; oled.GetTextProperties(&textProperties); - /* Set text properties to white and right aligned for the dynamic text */ - textProperties.fontColor = COLOR_WHITE; + /* Set text properties to green and right aligned for the dynamic text */ + textProperties.fontColor = COLOR_GREEN; textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT; oled.SetTextProperties(&textProperties); - - //readSensors(); //read the sensors - //CalculatePPM(); //convert to ppm - //dataQueue(); //push the value into the circular array + if (screen == 2){ //Air Quality Screen - //is_drawn1 = 0; - //is_drawn3 = 0; if(!is_drawn2){ is_drawn1 = 0; is_drawn3 = 0; @@ -222,12 +170,18 @@ oled.DrawImage(image2,0,0); is_drawn2 = 1; } + if (aq_ppm >= 50 and aq_ppm < 100){ + textProperties.fontColor = COLOR_YELLOW; //color the font yellow + oled.SetTextProperties(&textProperties); + } + else if (aq_ppm >= 100){ + textProperties.fontColor = COLOR_RED; //color the font red + oled.SetTextProperties(&textProperties); + } sprintf(AQ_level,"%.2f",aq_ppm); /* Print the AQ PPM to the screen */ oled.TextBox((uint8_t *)AQ_level,35,76,35,15); } else if (screen == 3){ //Carbon Monoxide Screen - //is_drawn2 = 0; - //is_drawn1 = 0; if (!is_drawn3){ is_drawn2 = 0; is_drawn1 = 0; @@ -235,12 +189,20 @@ oled.DrawImage(image3,0,0); is_drawn3 = 1; } + if (co_ppm >= 50 and co_ppm < 100){ + textProperties.fontColor = COLOR_YELLOW; //color the font yellow + oled.SetTextProperties(&textProperties); + } + + else if (co_ppm >= 100) { + textProperties.fontColor = COLOR_RED; //color the font red + oled.SetTextProperties(&textProperties); + } sprintf(CO_level,"%.2f",co_ppm); /* Print the CO PPM to the screen */ oled.TextBox((uint8_t *)CO_level,35,76,35,15); + } else if (screen == 1) { //Home Screen - //is_drawn3 = 0; - //is_drawn2 = 0; if (!is_drawn1){ is_drawn3 = 0; is_drawn2 = 0; @@ -248,10 +210,32 @@ oled.DrawImage(image1,0,0); is_drawn1 = 1; } - sprintf(average, "%.2f", avg); /* Print the average to the screen */ - oled.TextBox((uint8_t *)average,55,20,35,15); + if (avg >= 50 and avg <100) { + textProperties.fontColor = COLOR_YELLOW; //color the font yellow + oled.SetTextProperties(&textProperties); + } + else if (avg >=100){ + textProperties.fontColor = COLOR_RED; //color the font red + oled.SetTextProperties(&textProperties); + } + + sprintf(average, "%.2f", avg); + oled.TextBox((uint8_t *)average,53,23,35,15); + + if (total >=50 and total < 100){ + textProperties.fontColor = COLOR_YELLOW; //color the font yellow + oled.SetTextProperties(&textProperties); + } + else if (total >= 100) { + textProperties.fontColor = COLOR_RED; //color the font red + oled.SetTextProperties(&textProperties); + } + else { + textProperties.fontColor = COLOR_GREEN; //color the font green + oled.SetTextProperties(&textProperties); + } sprintf(total_total, "%.2f", total); /* Print the total to the screen */ - oled.TextBox((uint8_t *)total_total,55,40,35,15); + oled.TextBox((uint8_t *)total_total,53,39,35,15); } else if (screen == 4){ //BLE Pairing Screen @@ -262,11 +246,23 @@ oled.FillScreen(COLOR_BLACK); is_drawn4 = 1; } - strcpy((char *) text,"PAIR CODE"); + textProperties.alignParam = OLED_TEXT_ALIGN_CENTER; + textProperties.fontColor = COLOR_BLUE; + oled.SetTextProperties(&textProperties); + strcpy((char *) text,"BLUETOOTH"); oled.TextBox((uint8_t *)text,0,25,95,18); - /* Display Bond Pass Key in a 95px by 18px textbox at x=0,y=40 */ - sprintf(text,"%d", kw40z_device.GetPassKey()); - oled.TextBox((uint8_t *)text,0,40,95,18); + if (is_ble) { + textProperties.fontColor = COLOR_GREEN; + oled.SetTextProperties(&textProperties); + strcpy((char *) ble_status, "On"); + oled.TextBox((uint8_t *)ble_status,0,55,95,18); + } + else { + textProperties.fontColor = COLOR_RED; + oled.SetTextProperties(&textProperties); + strcpy((char *) ble_status, "Off"); + oled.TextBox((uint8_t *)ble_status,0,55,95,18); + } } Thread::wait(500); } @@ -279,7 +275,7 @@ kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG); kw40z_device.SendTemperature(100*aq_ppm); //send ppm Air Quality Click value kw40z_device.SendHumidity(100*co_ppm); //send ppm CO click value - kw40z_device.SendPressure(100*total); //send average + kw40z_device.SendPressure(100*total); //send total Thread::wait(1000); } } @@ -288,14 +284,10 @@ /* Turns on the OLED Display*/ oled.PowerON(); + /* Sets the pointers to their respective images */ image1 = homescreen_bmp; image2 = airquality_bmp; image3 = co_bmp; - - /* Set text properties to white and right aligned for the dynamic text */ - //textProperties.fontColor = COLOR_WHITE; - //textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT; - //oled.SetTextProperties(&textProperties); } void readSensors(){ /* Function to read sensors */ @@ -311,15 +303,15 @@ void ledColor(){ /* Function to determine the LED color */ - if ((total - avg) <= 10) { + if ((total - avg) <= 10 and total < 50 and ARC < 10 ) { led = green; led_color = led; /* Store the LED color for the flash function */ } - else if ((total - avg) > 10 && (total - avg) < 50) { + else if ((total - avg) > 10 and (total - avg) < 50 and total < 100 or (ARC >= 10 and ARC < 20)) { led = yellow; led_color = led; /* Store the LED color for the flash function */ } - else if ((total - avg >= 50) or total >= 100) { + else if ((total - avg >= 50) or total >= 100 or avg >= 100 or ARC >= 20) { led = red; led_color = led; /* Store the LED color for the flash function */ } @@ -335,12 +327,12 @@ void buzzer() { /* Function to handle the buzzer sound */ - if ((total - avg) <=25){ /* No buzzer sound if PPM is under 10 */ + if ((total - avg) <=25 and ARC < 10){ /* No buzzer sound if PPM is under 10 */ Buzzer.period_us(0); is_sounding = false; } - else if ((total - avg) > 25 and (total - avg) < 50) { + else if ((total - avg) > 25 and (total - avg) < 50 and total < 100 or (ARC >=10 and ARC < 20)) { if (is_sounding == false){ /* If the buzzer is not triggered, trigger */ Buzzer.period_us(B_4); /* Period of B4 */ Buzzer.write(0.50f); /* 50% Duty Cycle on the Tone */ @@ -352,7 +344,7 @@ } } - else if ((total - avg) >= 50 or total >= 100){ + else if ((total - avg) >= 50 or total >= 100 or avg >= 100 or ARC >= 20){ if (is_sounding == false){ Buzzer.period_us(B_5); /* Period of B5 */ Buzzer.write(0.50f); /* 50% Duty Cycle on the Tone */ @@ -376,21 +368,23 @@ double ratio; // Rs/Rl ratio double lgPPM; + if (aq_total > 65533) //prevents NAN error from overflow of 16 bits + aq_total = 65530; Vrl = (double)aq_total * Vadc_33; // For 3.3V Vcc use Vadc_33 Rs = AQ_Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance ratio = Rs/AQ_Rl; // Calculate ratio lgPPM = (log10(ratio) * -0.8) + 0.9; aq_ppm = 6* pow(10,lgPPM) - 12; // Calculate air quality ppm - //aq_ppm = 24.1; //used for BLE testing + if (co_total > 65533) //prevents NAN error from overflow of 16 bits + co_total = 65530; Vrl = (double)co_total * Vadc_33; // For 3.3V Vcc use Vadc_33 Rs = CO_Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance ratio = Rs/CO_Rl; // Calculate ratio lgPPM = (log10(ratio) * -0.8) + 0.9; co_ppm = 6* pow(10,lgPPM) - 12; // Calculate carbon monoxide ppm - //co_ppm = 11.0; //used for BLE testing - if (aq_ppm < 0) + if (aq_ppm < 0) aq_ppm = 0; //prevents underflow else if (aq_ppm >= 1000) aq_ppm = 999.99; //prevents overflow @@ -401,7 +395,7 @@ co_ppm = 999.99; /* Calculate the total */ - total = co_ppm + aq_ppm; + total = co_ppm + aq_ppm; if (total < 0) total = 0; else if (total >= 1000) @@ -410,7 +404,6 @@ void dataQueue() { /* Beginning of function */ - if (pushIndex != SIZE and !calc){ /* Initially pushing values into the set */ dataSet[pushIndex] = total; //push value into the queue sum += dataSet[pushIndex]; //add the value to the sum @@ -419,6 +412,7 @@ if (pushIndex == SIZE){ avg = sum / SIZE; //compute the average once the queue is full calc = true; //flag calc + ARC = dataSet[SIZE - 1] - dataSet[SIZE - 2]; pushIndex = 0; //reset the push index back to 0 } } @@ -427,7 +421,15 @@ sum -= dataSet[pushIndex]; //subtract the value to be overriden from the sum dataSet[pushIndex] = total; //push the value into the set sum += dataSet[pushIndex]; //add the value to the sum - avg = sum / SIZE; + avg = sum / SIZE; //compute average + if (pushIndex == 0){ + prev_value = dataSet[SIZE - 1]; + ARC = dataSet[pushIndex] - prev_value; + } + else { + prev_value = dataSet[pushIndex - 1]; + ARC = dataSet[pushIndex] - prev_value; + } pushIndex++; //increment the push index if (pushIndex == SIZE) @@ -438,7 +440,7 @@ void StartHaptic(void) { - hapticTimer.start(75); + hapticTimer.start(50); haptic = 1; }
diff -r aa8c291b3f9a -r 24b332b8e41d pwm_tone.cpp --- a/pwm_tone.cpp Tue Mar 28 21:41:06 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* Includes ------------------------------------------------------------------*/ -#include "pwm_tone.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/** - * @brief Tune Function - * @param name : Choose the PwmOut - period : this param is tune value. (C_3...B_5) - beat : this param is beat value. (1..16) 1 means 1/16 beat - * @retval None - */ -void Tune(PwmOut name, int period, int beat) -{ - int delay; - - delay = beat*63; - name.period_us(period); - name.write(0.50f); // 50% duty cycle - wait_ms(delay); // 1 beat - name.period_us(0); // Sound off -} - -/** - * @brief Auto tunes Function - * @param name : Choose the PwmOut - period : this param is tune value. (C_3...B_5) - beat : this param is beat value. (1..16) 1 means 1/16 beat - * @retval None - */ -void Auto_tunes(PwmOut name, int period, int beat) -{ - int delay; - - delay = beat*63; - name.period_us(period); - name.write(0.50f); // 50% duty cycle - wait_ms(delay); -} - -/** - * @brief Stop tunes Function - * @param name : Choose the PwmOut - * @retval None - */ -void Stop_tunes(PwmOut name) -{ - name.period_us(0); -} - -//void buzzer(PwmOut Buzzer, int ppm, float B_4, float B_5) -//{ - //int counter = 0; /* Break condition to take another measurement */ - //if (ppm >=10 and ppm <=25) { - //while (1) { - - // if (led_green == 0 && led_red == 1 && led_blue == 1){ - // led_green = 0; - // led_red = 0; /* Yellow LED */ - // led_blue = 1; - //} - - //else if (led_green == 0 && led_red == 0 && led_blue == 1) { - // led_green = 1; - // led_red = 1; /* Blink LED off */ - // led_blue = 1; - //} - //else { - // led_green = 0; - // led_red = 0; /* Blink LED on */ - // led_blue = 1; - //} - //counter++; - //wait_ms(400); - //if (counter >= 5) - //return; /* After 20 iterations of the alarm, break */ - //} - //} - //else if (ppm > 25 and ppm < 100) { - // while (1) { - - //if (led_green == 0 && led_red == 1 && led_blue == 1){ - // led_green = 0; - // led_red = 0; /* Yellow LED */ - // led_blue = 1; - //} - - // else if (led_green == 0 && led_red == 0 && led_blue == 1) { - // led_green = 1; - // led_red = 1; /* Blink LED off */ - // led_blue = 1; - //} - //else { - // led_green = 0; - // led_red = 0; /* Blink LED on */ - // led_blue = 1; - //} - // Tune(Buzzer, B_4, 10); - //counter++; - // wait_ms(250); - //if (counter >= 5) - //return; /* After 20 iterations of the alarm, break */ - // } - //} - - //else if (ppm >= 100) { - //while (1) { - - //if (led_green == 0 && led_red == 1 && led_blue ==1){ - //led_green = 1; - //led_red = 0; /* Red LED */ - //led_blue = 1; - //} - - //else if (led_green == 1 && led_red == 0 && led_blue == 1) { - // led_green = 1; - // led_red = 1; /* Blink LED off */ - // led_blue = 1; - //} - //else { - // led_green = 1; - // led_red = 0; /* Blink LED on */ - // led_blue = 1; - //} - // Tune(Buzzer, B_5, 5); - //counter++; - // wait_ms(100); - //if (counter >= 5) - //return; /* After 20 iterations of the alarm, break */ - // } - // } -//}