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

driver.cpp

Committer:
Gfolker
Date:
2017-03-15
Revision:
0:f70b1d60f794
Child:
1:8ab4a1e27785

File content as of revision 0:f70b1d60f794:

#include "mbed.h"
#include "pwm_tone.h"   /* Tone library for Buzzer Click */
#include "Hexi_OLED_SSD1351.h" /* Header file for OLED Display */
#include "string.h"
#include "Hexi_KW40Z.h"   /* Driver for button presses and BLE */
#include <math.h>       /* Used for ADC conversion algorithm */
#include <iostream>   /* Used for debugging */

/*****Function Prototypes*****/
void readSensors();
void ledColor();
void led_out();
void buzzer();
void CalculatePPM();

PwmOut Buzzer(PTA10);   /* Buzzer is attached to docking station port 1 */

AnalogIn AQSensor(PTB3);   /* Air Quality sensor is attached to docking station port 2 */
AnalogIn COSensor(PTB6);   /* Carbon Monoxide sensor is attached to docking station port 3 */

BusOut led(PTC8, PTD0, PTC9);   /* RGB Port Configurations */

const int green = 5,
          red = 6,          /* LED Colors */
          black = 7,
          yellow = 4;
          
bool is_sounding = false;       /* Set to high if the buzzer is going off */
          
int led_color;      /* Variable to hold the current LED color */

Ticker sensor_read,      /* Used for the read sensor subroutine call */
       buzzer_sound,     /* Used for the sound buzzer subroutine call */
       led_flash,        /* Used to determine the flash rate */
       ledcolor,        /* Used to determine the LED color */
       A2D_Convert;    /* Used to convert the analog signal to digital */

float B_4 = 1000000/Ti4,    /* Tones that will play on the buzzer click */
      B_5 = 1000000/Ti5;
      
char text[20];  /* Static Text Buffer for OLED Display */
char AQ_level[20]; /* Dynamic Text Buffer for AQ total */
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 */

/* Either unit16_t or float */
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 */ 
         avg;      /* Variable to store the average total */
         
uint16_t aq_total, /* Variable to store the AQ total */
         co_total; /* Variable to store the CO total */          
      
int main(){

    /* Instantiate the SSD1351 OLED Driver */ 
    SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15);
    
    /* Get OLED Class Default Text Properties */
    oled_text_properties_t textProperties = {0};
    oled.GetTextProperties(&textProperties);
    
    /* Turns on the OLED Display*/
    oled.PowerON();
    
    /* 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);
    
    /* Subroutine Calls */
    sensor_read.attach(&readSensors, 1);   /* Read the sensor on a time interval (Currently 3s) */
    A2D_Convert.attach(&CalculatePPM, 1);  /* Convert the values read from the sensors to 16 bit integers */
    ledcolor.attach(&ledColor, 0.5);       /* Determine the LED color */
    led_flash.attach(&led_out, 0.25);      /* Flash LED based on sensor data */
    buzzer_sound.attach(&buzzer, 0.25);    /* Sensor values are sent to buzzer function */
    
    while (1) { /* Loop to process and display data */
        
        /*                                       */
        /*                                       */
        /*                                       */
        /* Code to process sensor data goes here */
        /*                                       */
        /*                                       */
        /*                                       */
        
        sprintf(AQ_level,"%.2f",aq_ppm);    /* Print the AQ PPM to the screen */
        
        /* Display time reading in 35px by 15px textbox at(x=55, y=40) */
        oled.TextBox((uint8_t *)AQ_level,55,20,35,15); //Increase textbox for more digits
        
        sprintf(CO_level,"%.2f",co_ppm);    /* Print the CO PPM to the screen */
        
        oled.TextBox((uint8_t *)CO_level,55,40,35,15);
        
        sprintf(average, "%.2f", avg);      /* Print the average to the screen */
        
        oled.TextBox((uint8_t *)average,55,60,35,15);
        
        sprintf(total_total, "%.2f", total);   /* Print the total to the screen */
        
        oled.TextBox((uint8_t *)total_total,55,80,35,15);
        
    }
    
    return 0;
}

void readSensors(){  /* Function to read sensors */
    
    /* Grab the analog signal from the sensors as 16 bit unsigned integers */
    aq_total = AQSensor.read_u16();
    co_total = COSensor.read_u16();
    /* Grab the analog signal from the sensors as floats */
    //aq_total = AQSensor.read();
    //co_total = AQSensor.read();
  
}

void ledColor(){    /* Function to determine the LED color */
    
    if (total <= 10) {
        led = green;
        led_color = led;     /* Store the LED color for the flash function */
    }
    else if (total > 10 && total < 50) {
        led = yellow;
        led_color = led;     /* Store the LED color for the flash function */
    }
    else if (total >= 50) {
        led = red;
        led_color = led;     /* Store the LED color for the flash function */
    }
}

void led_out() { /* Function to flash LEDs */

    if (led == green) {return;}   /* If green, don't blink */
    else if (led == black) {led = led_color;}
    else {led = black;}
     
}

void buzzer() { /* Function to handle the buzzer sound */

    if (total <=25){            /* No buzzer sound if PPM is under 10 */
        Buzzer.period_us(0);
        is_sounding = false;  
    }

    else if (total > 25 and total < 50) {
        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 */
            is_sounding = true;         /* Signal that the buzzer is currently triggering */
        }
        else {   
            Buzzer.period_us(0);        /* Turn off the buzzer (Period = 0us)*/
            is_sounding = false;        /* Signal that the buzzer is no longer triggering */
        }        
    }
    
    else if (total >= 50){
        if (is_sounding == false){
            Buzzer.period_us(B_5);      /* Period of B5 */
            Buzzer.write(0.50f);        /* 50% Duty Cycle on the Tone */
            is_sounding = true;
        }
        else {   
            Buzzer.period_us(0);        /* Turn off the buzzer */
            is_sounding = false;
        }
    }   
}

void CalculatePPM(){ /* Function to convert the analog signals to digital based on 16 bit adc steps */
    
    const double AQ_Rl = 20000.0;               // AQ_Rl (20kOhm) - Load resistance for AQ sensor
    const double CO_Rl = 18500.0;               // CO_Rl (18.5kOhm) - Load resistance for CO sensor
    const double Vadc_33 = 0.0000503548;         // ADC step 3,3V/65535 0.00503mV (16bit ADC)
    //const double Vadc_5 = 5.0/65535;          // ADC step 5.0V/2^16 (65535, 16bit ADC)
    double Vrl;                                  // Output voltage
    double Rs;                                   // Rs (Ohm) - Sensor resistance
    double ratio;                                // Rs/Rl ratio
    double lgPPM;

    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;       // Calculate air quality ppm
    aq_ppm = 6* pow(10,lgPPM);                 // Calculate air quality ppm
    
    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;       // Calculate carbon monoxide ppm
    co_ppm = 6* pow(10,lgPPM);                 // Calculate carbon monoxide ppm
    
    /* Calculate the average and total */
    total = co_ppm + aq_ppm;    
    avg = (total)/2;  
}