Very advanced Click Air Quality example for Hexiwear featuring OLED Display, Bluetooth, Cloud and Touch

Dependencies:   Hexi_KW40Z Hexi_OLED_SSD1351

This project has been developed by mbed user daveyclk

This project demonstrates the use of the Mikroelektronika Click Air Quality module with hexiwear featuring the OLED display, the Bluetooth for Cloud connectivity and Touch buttons

Plug Hexiwear into the Docking Station and the Air Quality Click to the Click Socket 1
Connect the USB cable to your computer and to the micro-USB port of the Docking Station

Compile the project and copy the binary "Hexi_Click_AirQuality_Example_HEXIWEAR.bin" in the DAP-LINK drive from your computer file explorer
Press the K64F-RESET button on the docking station to start the program on your board

The OLED screen will display some graphics and the Air Quality measurement in ppm below
Blow gently on the sensor and see the value changing
Graphic displayed will move the Arrow from Green to Purple depending from the ppm value measured by the Air Quality sensor
Download the cell phone App Hexiwear from iOS or Android stores to connect your board to your phone
Type the pin displayed on the screen and give a name to your board to pair it via the App
Congratulation your data are now streamed directly to Wolkabout Cloud...
To visualize the data remotely (over cloud not bluetooth), you can go to Wolksense.com or download the Wolksense iOS/Android App and login with same account

Committer:
daveyclk
Date:
Mon Oct 24 15:14:39 2016 +0000
Revision:
2:8e7d89c2cbde
Parent:
1:7b9c19276087
Child:
3:97bc87323258
Updated the GUI, now has an Air Quality Meter that uses an arrow to point to it. PPM values still show. The Air Quality Click needs to be modified to run at 3V3 levels. Set test = true to see the images

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daveyclk 2:8e7d89c2cbde 1
daveyclk 2:8e7d89c2cbde 2
GregC 0:4cf89612afab 3 /******************************************************************************
GregC 0:4cf89612afab 4 * Includes
GregC 0:4cf89612afab 5 *******************************************************************************/
GregC 0:4cf89612afab 6
GregC 0:4cf89612afab 7 #include "mbed.h"
GregC 0:4cf89612afab 8 #include "Hexi_OLED_SSD1351.h"
GregC 0:4cf89612afab 9 #include "images.h"
daveyclk 2:8e7d89c2cbde 10 #include "new_images.h"
GregC 0:4cf89612afab 11 #include "string.h"
daveyclk 2:8e7d89c2cbde 12 #include "stdbool.h"
GregC 0:4cf89612afab 13
GregC 0:4cf89612afab 14 /******************************************************************************
GregC 0:4cf89612afab 15 * Input and Output Pinout
GregC 0:4cf89612afab 16 *******************************************************************************/
GregC 0:4cf89612afab 17
GregC 0:4cf89612afab 18 AnalogIn ain(PTB2);
GregC 0:4cf89612afab 19 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); // SSD1351 OLED Driver (MOSI,SCLK,POWER,CS,RST,DC)
GregC 0:4cf89612afab 20 DigitalOut led1(LED_GREEN);
GregC 0:4cf89612afab 21 Serial pc(USBTX, USBRX);
GregC 0:4cf89612afab 22
GregC 0:4cf89612afab 23 /******************************************************************************
GregC 0:4cf89612afab 24 * Module Variable Definitions
GregC 0:4cf89612afab 25 *******************************************************************************/
GregC 0:4cf89612afab 26
GregC 0:4cf89612afab 27 double ppm; // ppm
GregC 0:4cf89612afab 28
GregC 0:4cf89612afab 29 int value = 0;
GregC 0:4cf89612afab 30 int value_old = 0;
GregC 0:4cf89612afab 31 uint16_t adc_rd;
GregC 0:4cf89612afab 32
daveyclk 2:8e7d89c2cbde 33 //const uint8_t *image1; // old cover image
daveyclk 2:8e7d89c2cbde 34 const uint8_t *green_arrow; // Pointer for the image to be displayed
daveyclk 2:8e7d89c2cbde 35 const uint8_t *yellow_arrow; // Pointer for the image to be displayed
daveyclk 2:8e7d89c2cbde 36 const uint8_t *orange_arrow; // Pointer for the image to be displayed
daveyclk 2:8e7d89c2cbde 37 const uint8_t *red_arrow; // Pointer for the image to be displayed
daveyclk 2:8e7d89c2cbde 38 const uint8_t *purple_arrow; // Pointer for the image to be displayed
daveyclk 2:8e7d89c2cbde 39
daveyclk 2:8e7d89c2cbde 40 char text[20]; // Text Buffer for dynamic value displayed
daveyclk 2:8e7d89c2cbde 41
daveyclk 2:8e7d89c2cbde 42 bool test = false; // used to put the program in text mode to check images
GregC 0:4cf89612afab 43
GregC 0:4cf89612afab 44
GregC 0:4cf89612afab 45 /**************************************************************************************************
GregC 0:4cf89612afab 46 * Function InitModules()
GregC 0:4cf89612afab 47 * -------------------------------------------------------------------------------------------------
GregC 0:4cf89612afab 48 * Overview:
GregC 0:4cf89612afab 49 * Input: None
GregC 0:4cf89612afab 50 * Output: None
GregC 0:4cf89612afab 51 **************************************************************************************************/
GregC 0:4cf89612afab 52
GregC 0:4cf89612afab 53 void InitModules()
GregC 0:4cf89612afab 54 {
daveyclk 2:8e7d89c2cbde 55 //image1 = AirQuality; // Setting pointer location of the 96 by 96 pixel bitmap
daveyclk 2:8e7d89c2cbde 56 //oled.DrawImage(image1,0,0); // Fill 96px by 96px Screen with 96px by 96px NXP Image starting at x=0,y=0
daveyclk 2:8e7d89c2cbde 57
daveyclk 2:8e7d89c2cbde 58 green_arrow = Green_arrow_bmp; // Setting pointer location of the 96 by 96 pixel bitmap Arrow Point to Green To begin
daveyclk 2:8e7d89c2cbde 59 yellow_arrow = Yellow_arrow_bmp; // Setting pointer location of the 96 by 96 pixel bitmap
daveyclk 2:8e7d89c2cbde 60 orange_arrow = Orange_arrow_bmp; // Setting pointer location of the 96 by 96 pixel bitmap
daveyclk 2:8e7d89c2cbde 61 red_arrow = Red_arrow_bmp; // Setting pointer location of the 96 by 96 pixel bitmap
daveyclk 2:8e7d89c2cbde 62 purple_arrow = Purple_arrow_bmp; // Setting pointer location of the 96 by 96 pixel bitmap
daveyclk 2:8e7d89c2cbde 63
daveyclk 2:8e7d89c2cbde 64 oled.DrawImage(green_arrow,0,0); // Fill 96px by 96px Screen with 96px by 96px NXP Image starting at x=0,y=0
GregC 0:4cf89612afab 65
GregC 0:4cf89612afab 66 oled_text_properties_t textProperties = {0}; // Get OLED Class Default Text Properties
GregC 0:4cf89612afab 67 oled.GetTextProperties(&textProperties);
GregC 0:4cf89612afab 68
daveyclk 2:8e7d89c2cbde 69 //PPM text now in the Bitmap
daveyclk 2:8e7d89c2cbde 70
daveyclk 2:8e7d89c2cbde 71 //textProperties.fontColor = COLOR_BLUE; // Set text properties to white and right aligned for the dynamic text
daveyclk 2:8e7d89c2cbde 72 //textProperties.alignParam = OLED_TEXT_ALIGN_LEFT;
daveyclk 2:8e7d89c2cbde 73 //oled.SetTextProperties(&textProperties);
GregC 0:4cf89612afab 74
daveyclk 2:8e7d89c2cbde 75 //strcpy((char *) text,"ppm:"); // Display Legends
daveyclk 2:8e7d89c2cbde 76 // oled.Label((uint8_t *)text,15,75);
GregC 0:4cf89612afab 77
daveyclk 2:8e7d89c2cbde 78 textProperties.fontColor = COLOR_WHITE; // Set text properties to white and right aligned for the dynamic text
GregC 0:4cf89612afab 79 textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
GregC 0:4cf89612afab 80 oled.SetTextProperties(&textProperties);
GregC 0:4cf89612afab 81
GregC 0:4cf89612afab 82 sprintf(text,"%i",value); // Format the value
daveyclk 2:8e7d89c2cbde 83 oled.TextBox((uint8_t *)text,55,76,20,15); //Increase textbox for more digits
GregC 0:4cf89612afab 84
GregC 0:4cf89612afab 85
GregC 0:4cf89612afab 86 }
GregC 0:4cf89612afab 87
GregC 0:4cf89612afab 88
GregC 0:4cf89612afab 89 /**************************************************************************************************
GregC 0:4cf89612afab 90 * Function ReadSensor()
GregC 0:4cf89612afab 91 * -------------------------------------------------------------------------------------------------
GregC 0:4cf89612afab 92 * Overview: Read sensor.
GregC 0:4cf89612afab 93 * Input: None
GregC 0:4cf89612afab 94 * Output: None
GregC 0:4cf89612afab 95 **************************************************************************************************/
GregC 0:4cf89612afab 96
GregC 0:4cf89612afab 97 void ReadSensor()
GregC 0:4cf89612afab 98 {
GregC 0:4cf89612afab 99 adc_rd = ain.read_u16();
GregC 0:4cf89612afab 100 wait_ms(10);
GregC 0:4cf89612afab 101 }
GregC 0:4cf89612afab 102
GregC 0:4cf89612afab 103
GregC 0:4cf89612afab 104 /**************************************************************************************************
GregC 0:4cf89612afab 105 * Function CalculatePPM()
GregC 0:4cf89612afab 106 * -------------------------------------------------------------------------------------------------
GregC 0:4cf89612afab 107 * Overview: Calculation of PPM.
GregC 0:4cf89612afab 108 * Input: None
GregC 0:4cf89612afab 109 * Output: None
GregC 0:4cf89612afab 110 **************************************************************************************************/
GregC 0:4cf89612afab 111
GregC 0:4cf89612afab 112 void CalculatePPM()
GregC 0:4cf89612afab 113 {
GregC 0:4cf89612afab 114 const double Rl = 5000.0; // Rl (Ohm) - Load resistance
daveyclk 1:7b9c19276087 115 const double Vadc_33 = 0.0000503548; // ADC step 3,3V/65535 0.00503mV (16bit ADC)
GregC 0:4cf89612afab 116 double Vrl; // Output voltage
GregC 0:4cf89612afab 117 double Rs; // Rs (Ohm) - Sensor resistance
GregC 0:4cf89612afab 118 double ratio; // Rs/Rl ratio
GregC 0:4cf89612afab 119 double lgPPM;
GregC 0:4cf89612afab 120
GregC 0:4cf89612afab 121 Vrl = (double)adc_rd * Vadc_33; // For 3.3V Vcc use Vadc_33
daveyclk 1:7b9c19276087 122 Rs = Rl * (3.3 - Vrl)/Vrl; // Calculate sensor resistance
GregC 0:4cf89612afab 123 ratio = Rs/Rl; // Calculate ratio
GregC 0:4cf89612afab 124 lgPPM = (log10(ratio) * -0.8) + 0.9; // Calculate ppm
GregC 0:4cf89612afab 125 ppm = pow(10,lgPPM); // Calculate ppm
GregC 0:4cf89612afab 126 }
GregC 0:4cf89612afab 127
GregC 0:4cf89612afab 128
GregC 0:4cf89612afab 129
GregC 0:4cf89612afab 130 /**************************************************************************************************
GregC 0:4cf89612afab 131 * Function DisplayAirQValue()
GregC 0:4cf89612afab 132 * -------------------------------------------------------------------------------------------------
GregC 0:4cf89612afab 133 * Overview:
GregC 0:4cf89612afab 134 * Input: None
GregC 0:4cf89612afab 135 * Output: None
GregC 0:4cf89612afab 136 **************************************************************************************************/
GregC 0:4cf89612afab 137
GregC 0:4cf89612afab 138 void DisplayAirQValue( uint16_t value )
GregC 0:4cf89612afab 139 {
GregC 0:4cf89612afab 140 if (value_old != value)
GregC 0:4cf89612afab 141 {
GregC 0:4cf89612afab 142
daveyclk 2:8e7d89c2cbde 143 if( value > 200)
daveyclk 2:8e7d89c2cbde 144 oled.DrawImage(purple_arrow,0,0); // Fill 96px by 96px Screen with 96px by 96px NXP Image starting at x=0,y=0
daveyclk 2:8e7d89c2cbde 145 else if (value < 200 && value > 150)
daveyclk 2:8e7d89c2cbde 146 oled.DrawImage(red_arrow,0,0);
daveyclk 2:8e7d89c2cbde 147 else if (value < 150 && value > 100)
daveyclk 2:8e7d89c2cbde 148 oled.DrawImage(orange_arrow,0,0);
daveyclk 2:8e7d89c2cbde 149 else if (value < 100 && value > 50)
daveyclk 2:8e7d89c2cbde 150 oled.DrawImage(yellow_arrow,0,0);
daveyclk 2:8e7d89c2cbde 151 else
daveyclk 2:8e7d89c2cbde 152 oled.DrawImage(green_arrow,0,0);
daveyclk 2:8e7d89c2cbde 153
GregC 0:4cf89612afab 154 oled_text_properties_t textProperties = {0}; // Get OLED Class Default Text Properties
GregC 0:4cf89612afab 155 oled.GetTextProperties(&textProperties);
GregC 0:4cf89612afab 156
GregC 0:4cf89612afab 157 // clear the previous value
GregC 0:4cf89612afab 158 textProperties.fontColor = COLOR_WHITE; // Set text properties to white and right aligned for the dynamic text
GregC 0:4cf89612afab 159 textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
GregC 0:4cf89612afab 160 oled.SetTextProperties(&textProperties);
GregC 0:4cf89612afab 161
GregC 0:4cf89612afab 162 sprintf(text,"%i",value_old); // Format the value
daveyclk 2:8e7d89c2cbde 163 oled.TextBox((uint8_t *)text,55,76,20,15); //Increase textbox for more digits
GregC 0:4cf89612afab 164
GregC 0:4cf89612afab 165 // display the new value
GregC 0:4cf89612afab 166 textProperties.fontColor = COLOR_WHITE; // Set text properties to white and right aligned for the dynamic text
GregC 0:4cf89612afab 167 textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
GregC 0:4cf89612afab 168 oled.SetTextProperties(&textProperties);
GregC 0:4cf89612afab 169
GregC 0:4cf89612afab 170 sprintf(text,"%i",value); // Format the value
daveyclk 2:8e7d89c2cbde 171 oled.TextBox((uint8_t *)text,55,76,20,15); //Increase textbox for more digits
GregC 0:4cf89612afab 172 }
GregC 0:4cf89612afab 173 value_old = value;
GregC 0:4cf89612afab 174 }
GregC 0:4cf89612afab 175
GregC 0:4cf89612afab 176
GregC 0:4cf89612afab 177 /**************************************************************************************************
GregC 0:4cf89612afab 178 * Function Main()
GregC 0:4cf89612afab 179 * -------------------------------------------------------------------------------------------------
GregC 0:4cf89612afab 180 * Overview:
GregC 0:4cf89612afab 181 * Input: None
GregC 0:4cf89612afab 182 * Output: None
GregC 0:4cf89612afab 183 **************************************************************************************************/
GregC 0:4cf89612afab 184
GregC 0:4cf89612afab 185 int main()
GregC 0:4cf89612afab 186 {
GregC 0:4cf89612afab 187
GregC 0:4cf89612afab 188 InitModules();
daveyclk 2:8e7d89c2cbde 189 test = false; // use this to test the BMPS
daveyclk 2:8e7d89c2cbde 190
daveyclk 2:8e7d89c2cbde 191
GregC 0:4cf89612afab 192 while (true)
GregC 0:4cf89612afab 193 {
GregC 0:4cf89612afab 194
GregC 0:4cf89612afab 195 ReadSensor();
GregC 0:4cf89612afab 196 pc.printf("Sensor Value 0x%04X\n\r",ain.read_u16());
daveyclk 2:8e7d89c2cbde 197
daveyclk 2:8e7d89c2cbde 198 // added a test to toggle through the images
daveyclk 2:8e7d89c2cbde 199 if (test == true)
daveyclk 2:8e7d89c2cbde 200 {
daveyclk 2:8e7d89c2cbde 201 int test_ppm = 10;
daveyclk 2:8e7d89c2cbde 202 for( int i = 0; i < 5; i++)
daveyclk 2:8e7d89c2cbde 203 {
daveyclk 2:8e7d89c2cbde 204 DisplayAirQValue(test_ppm);
daveyclk 2:8e7d89c2cbde 205 test_ppm += 50;
daveyclk 2:8e7d89c2cbde 206 led1 = !led1;
daveyclk 2:8e7d89c2cbde 207 Thread::wait(1000);
daveyclk 2:8e7d89c2cbde 208 }
daveyclk 2:8e7d89c2cbde 209 }
daveyclk 2:8e7d89c2cbde 210 else
daveyclk 2:8e7d89c2cbde 211 {
GregC 0:4cf89612afab 212
daveyclk 2:8e7d89c2cbde 213 CalculatePPM();
daveyclk 2:8e7d89c2cbde 214 DisplayAirQValue(ppm);
daveyclk 2:8e7d89c2cbde 215
daveyclk 2:8e7d89c2cbde 216 led1 = !led1;
daveyclk 2:8e7d89c2cbde 217 Thread::wait(500);
daveyclk 2:8e7d89c2cbde 218 }
GregC 0:4cf89612afab 219
GregC 0:4cf89612afab 220 }
GregC 0:4cf89612afab 221 }