Test code to interface AOD UPAS with IoT provider.

Dependencies:   ESP8266_AT NCP5623BMUTBG mbed ADS1115 AOD_Calculation BME280 PMS5003 SunPosition CAM_M8

main.cpp

Committer:
eawendtjr
Date:
2018-04-24
Revision:
7:bd22b64acd45
Parent:
6:aeb0015d6632

File content as of revision 7:bd22b64acd45:

#include "mbed.h"
#include "NCP5623BMUTBG.h"
#include "ESP8266_AT.h"
#include "SunPosition.h"
#include "AOD_Calculation.h"
#include "Adafruit_ADS1015.h"
#include "BME280.h"
#include "CAM_M8.h"

/////////////////////////////////////////////
//LED colors
/////////////////////////////////////////////
#define M_SET_LED_OFF()     RGB_LED.set_led(0,0,0)
#define M_SET_LED_RED()     RGB_LED.set_led(1,0,0)
#define M_SET_LED_GREEN()   RGB_LED.set_led(0,1,0)
#define M_SET_LED_BLUE()    RGB_LED.set_led(0,0,1)
#define M_SET_LED_MAGENTA() RGB_LED.set_led(1,0,1)
#define M_SET_LED_YELLOW()  RGB_LED.set_led(1,1,0)
#define M_SET_LED_CYAN()    RGB_LED.set_led(0,1,1)
#define M_SET_LED_WHITE()   RGB_LED.set_led(1,1,1)

/////////////////////////////////////////////
//Define core buses and pin states.
/////////////////////////////////////////////
I2C             i2c(PB_9, PB_8);//(D14, D15); SDA,SCL
Serial          pc(USBTX, USBRX);
DigitalOut      pumps(PA_9, 0);//(D8, 0);
DigitalOut      pbKill(PC_12, 1); // Digital input pin that conncect to the LTC2950 battery charger used to shutdown the UPAS 
DigitalIn       nINT(PA_15); //Connected but currently unused is a digital ouput pin from LTC2950 battery charger. http://cds.linear.com/docs/en/datasheet/295012fd.pdf
NCP5623BMUTBG   RGB_LED(PB_9, PB_8);    //(D14, D15);

/////////////////////////////////////////////
//RN4677 BT/BLE Module
/////////////////////////////////////////////
Serial          ble(PB_10, PB_11);
DigitalOut      bleRTS(PB_14, 0);
DigitalOut      bleCTS(PB_13, 0);
DigitalOut      BT_IRST(PC_8, 0);
DigitalOut      BT_SW(PA_12, 0);

/////////////////////////////////////////////
//Analog to Digital Converter
/////////////////////////////////////////////
DigitalIn       ADS_ALRT(PA_10); //Connected but currently unused. (ADS1115) http://www.ti.com/lit/ds/symlink/ads1115.pdf

/////////////////////////////////////////////
//Battery, Charger, & Supply Monitoring
/////////////////////////////////////////////
DigitalIn       LTCALT(PB_2); //High for normal operation. Low when a threshold is exceeded for Voltage, gas gauge, or temp
DigitalIn       bcs1(PC_9); //Batt charging if High. (BQ24100)[U23]
DigitalIn       bcs2(PA_8); //Charge complete if High. (BQ24100)[U23]  
DigitalIn       bc_npg(PB_1); //Power to the charge controller. (BQ24100)[U23] 
DigitalIn       SW3flt(PC_4); //When EN = 0 pin is HIGH, When EN = 1, LOW can be current limit, thermal limit, or UVLO.

/////////////////////////////////////////////
//Sensirion SDP3X(s)
/////////////////////////////////////////////
DigitalIn       SDP3Xflt(PC_0);
DigitalIn       SDP3XAltflt(PB_7);

/////////////////////////////////////////////
//Accelerometer and Magnometer
/////////////////////////////////////////////
DigitalOut      iNemoEnable(PA_1, 0);
DigitalIn       iNemoReady(PB_0);
DigitalIn       iNemoInt1(PC_5);
DigitalIn       iNemoInt2(PC_6);
DigitalIn       iNemoInt3(PC_7);

/////////////////////////////////////////////
//UV and Visible Light Sensor
/////////////////////////////////////////////

/////////////////////////////////////////////
//GPS
/////////////////////////////////////////////
DigitalOut          gpsEN(PB_15, 0);
CAM_M8              gps(PB_9, PB_8,(0x84));   
uint8_t gpsBTState = 1;
uint8_t meState = 0;
DigitalIn           gpsENFault(PB_12); //When EN = 0 pin is HIGH, When EN = 1, LOW can be current limit, thermal limit, or UVLO.


/////////////////////////////////////////////
//SD Card
/////////////////////////////////////////////
DigitalIn       sdCD(PA_11);
DigitalOut      sdClk(PB_3,0 );
DigitalIn       sdMISO(PB_4);
DigitalOut      sdMOSI(PB_5, 0);
DigitalOut      sdCS(PB_6, 1);

DigitalIn       pbIso(PA_0);
DigitalOut      hFault1(PA_7, 0);
DigitalOut      hFault2(PA_6, 0);
DigitalOut      hFault3(PA_5, 0);
DigitalOut      hFault4(PA_4, 0);

DigitalOut      wifiNReset(PC_1, 0);
DigitalOut      wifiEnable(PC_2, 0);
DigitalOut      qdEnable(PC_3, 0);
DigitalIn       qdFault(PC_13);

/////////////////////////////////////////////
//AOD Objects
/////////////////////////////////////////////
SunPosition         sun;
AOD_Calculation     aod_440;
AOD_Calculation     aod_870;
AOD_Calculation     aod_680;
AOD_Calculation     aod_520;
Adafruit_ADS1115    ads_sun(&i2c, ADS1015_ADDRESS_VDD); //Adress pin connected to 3.3V
BME280              bme(PB_9, PB_8, 0xEC);  //(D14, D15);

ESP8266_AT      esp(PC_10, PC_11);

Timer t;

char ssid[] = "w212lab";
char password[] = "testarduino";
//char ssid[] = "VOLTAR";
//char password[] = "CedhCedh";

char server[] = "api.thingspeak.com";
char apiKey[] = "32QVSK5INPPAVIV0";
char conn_type[] = "TCP";

// For selecting the WiFi UART
const int addr = 0x3F << 1;
char aod_sel_5on[1];
char aod_sel_5off[1];
char plant_sel[1];

//GPS Variables
bool    gpsReady = 0;
uint8_t gpsquality = 0;
uint8_t gpssatellites = 0;
double  gpsspeed = 0.0;
//double  gpscourse = 0.0;
double  gpslatitude = 0.0;
double  gpslongitude = 0.0;
float   gpsaltitude = 0.0;
bool ledOn = 1;

//AOD Variables
//Globals for sun calulation input
long gpsTime;
long gpsDate;
int year;
int month;
int day;
int hour;
int minute;
double second;

double latitude = 40.5853;
double longitude = -105.0844;
double altitude = 1525;
double temperature; 
double pressure;
double humidity;

//Globals for sun calculation output
double zenith;
double azimuth;
double radius;

//Constants
const double time_zone = 0; //GPS gets Greenwich time
const double delta_t = 68;  //This parameter will be roughly constant this year
const double slope = 30;
const double azm_rotation = 10;

//AOD CALCULATION
//AOD Calculation Constants
const double lambda_440 = 0.440;
const double lambda_520 = 0.520;
const double lambda_680 = 0.680;
const double lambda_870 = 0.870;
const double CO2_ppv = 0.00036;
const double v0_440 = 0.975524;
const double v0_520 = 1.412519;
const double v0_680 = 1.659305;
const double v0_870 = 1.178819;
const double vd = 0.001225;
const double oz_coeff_440 = 0.0029;
const double oz_coeff_520 = 0.0481;
const double oz_coeff_680 = 0.0361;
const double oz_coeff_870 = 0.0013;

//Voltage from light detector
double v870;     //Voltage read from 870nm photodiode
double v_raw870; //Raw analog output from 870nm photodiode
double v680;     //Voltage read from 680nm photodiode
double v_raw680; //Raw analog output from 680nm photodiode
double v520;     //Voltage read from 520nm photodiode
double v_raw520; //Raw analog output from 520nm photodiode
double v440;     //Voltage read from 440nm photodiode
double v_raw440; //Raw analog output from 440nm photodiode
double AOD_870;
double AOD_680;
double AOD_520;
double AOD_440;

//AOD functions
void getAODs();

//////////////////////////////////////////////////////////////
//Main Function
//////////////////////////////////////////////////////////////
int main()
{
    pc.baud(115200);
    RGB_LED.set_led(1, 0, 1);
    wait(1); 
    
    gpsEN = 1; // Enable the GPS
    wait(1);
    
    // Get the GPS time
    gps.read_gps();
    gpsTime = (long)gps.utc;
    gpsDate = (long)gps.date;
    pc.printf("Date: %d, Time: %d\r\n", gpsTime, gpsDate);
    int gpsfixWait = 0;
    // Wait until gps time is set
    if(gpsTime==0&&gpsDate==0){
        //gasG.resetMax();
        gps.resetGPS();
        wait(1);
        while(gpsquality == 0){
            gps.read_gps();
            gpsTime = (long)gps.utc;
            gpsDate = (long)gps.date;
            gpsquality =  gps.quality;
            
            if(ledOn == 1) {
                M_SET_LED_OFF();
                ledOn = 0;
            }
            else{
                if(gpsquality==0){
                    M_SET_LED_MAGENTA();
                }else{
                    M_SET_LED_YELLOW();
                }
                ledOn = 1;
            }
            
            wait(1);
            if(gpsquality==1){
                gpsfixWait++;
            }else{
                gpsfixWait = 0;
            }
        }
    }                            
    
    aod_sel_5on[0] = 0xCB;
    aod_sel_5off[0] = 0xC9;
    plant_sel[0] = 0xCF;
         
    RGB_LED.set_led(1, 1, 1); 
    i2c.write(addr, aod_sel_5on, 1);
    pc.printf("Plantower off\r\n");
    wait(1);
    
    //Enable the WiFi chip              
    RGB_LED.set_led(0, 1, 1);                   // Light LED so we know something is happening
    wifiEnable = 1;                             // Enable power to the WiFi while in reset, and wait a short while
    wait_ms(100);
    wifiNReset = 1;                             // Now de-assert the reset signal
    RGB_LED.set_led(1, 1, 0);                   // Color change of LED to indicate something is happening.
    wait(3);
    
    RGB_LED.set_led(0, 1, 0); 
    esp.check_esp();
    esp.version_info();
    esp.software_reset();
    
    esp.command_echo_mode(ESP_ECHO_ON);
    esp.set_wifi_mode(ESP_DUAL_CONFIG);
    esp.enable_multiple_connections();
    
    esp.create_tcp_server(80);
    
    //esp.set_server_timeout(5);
    
    esp.list_access_points();
    esp.wifi_connect(ssid, password);
    esp.check_ap();
    esp.get_ip();
    
    char someArray[160];
    
    t.start();
    while(1)
    {
        RGB_LED.set_led(0, 0, 1); 
        if(t.read()>15)//if 15 seconds passed
        {
            t.reset();//reset timer
            
            RGB_LED.set_led(1, 1, 1); 
            
            //get the AOD
            getAODs();

            //send data to thingspeak
            sprintf(someArray,"GET https://api.thingspeak.com/update?api_key=32QVSK5INPPAVIV0&field1=%.2f&field2=%.2f&field3=%.2f&field4=%.2f&field5=%.2f&field6=%.2f&field7=%.2f\r\n\r\n",AOD_440,AOD_520,AOD_680,AOD_870,temperature,pressure,humidity);
            
            esp.delete_tcp_server();
            esp.establish_connection(0, conn_type, server, 80);
            esp.send_data_tcp(0, someArray);
            esp.close_connection(0);
            esp.create_tcp_server(80);
            pc.printf("%s\r\n", someArray);
        }
    }
}

void getAODs()
{
    gps.read_gps();
   
    gpsTime = (long)gps.utc;
    gpsDate = (long)gps.date;
                        
    minute = (int)(floor((float)(gpsTime - (uint8_t)(floor((float)gpsTime/10000))*10000)/100));    // 0-59
    second = (double)(floor(((float)gpsTime - 100*(floor((float)gpsTime/100)))));//0; //(uint8_t)(floor(((float)gpsTime - 100*(floor((float)gpsTime/100)))));    // 0-59
    hour =  (int)(floor((float)gpsTime/10000));  // 0-23
    day = (int)(floor((float)gpsDate/10000));   // 1-31
    month = (uint8_t)(floor((float)(gpsDate - day*10000)/100));     // 0-11
    year = 1900 + (uint8_t)(100+floor(((float)gpsDate - 100*(floor((float)gpsDate/100))))); // year since 1900 (116 = 2016)//100+16
   
    temperature = bme.getTemperature();    
    pressure = bme.getPressure(temperature);
    humidity = bme.getHumidity();
    
    sun.setValues(year, month, day, hour, minute, second, time_zone, delta_t, latitude, longitude, altitude, temperature, pressure, slope, azm_rotation);
    sun.findSun();
    zenith = sun.getZenith();
    radius = sun.getRadius();
        
    //Read the light detectors
    v_raw870 = (double)ads_sun.readADC_SingleEnded(A3_GAIN_TWO); //Channel A3 | 1x gain | +/-4.096V | 1 bit = 2mV | 0.125mV
    v870 = (v_raw870*0.0625)/(1000); //Converts to a voltage
        
    v_raw680 = (double)ads_sun.readADC_SingleEnded(A2_GAIN_TWO); //Channel A2 | 1x gain | +/-4.096V | 1 bit = 2mV | 0.125mV
    v680 = (v_raw680*0.0625)/(1000); //Converts to a voltage
        
    v_raw520 = (double)ads_sun.readADC_SingleEnded(A1_GAIN_TWO); //Channel A1 | 1x gain | +/-4.096V | 1 bit = 2mV | 0.125mV
    v520 = (v_raw520*0.0625)/(1000); //Converts to a voltage
    
    v_raw440 = (double)ads_sun.readADC_SingleEnded(A0_GAIN_TWO); //Channel A1 | 1x gain | +/-4.096V | 1 bit = 2mV | 0.125mV
    v440 = (v_raw520*0.0625)/(1000); //Converts to a voltage
    
    //Calculate the AOD for all channels
    aod_870.setAODInputs(longitude, latitude, altitude, lambda_870, CO2_ppv, pressure, month, day, oz_coeff_870, v0_870, vd, v870, radius, zenith);
    aod_870.opticalDepth();
    AOD_870 = aod_870.getAOD();
        
    aod_680.setAODInputs(longitude, latitude, altitude, lambda_680, CO2_ppv, pressure, month, day, oz_coeff_680, v0_680, vd, v680, radius, zenith);
    aod_680.opticalDepth();
    AOD_680 = aod_680.getAOD();
        
    aod_520.setAODInputs(longitude, latitude, altitude, lambda_520, CO2_ppv, pressure, month, day, oz_coeff_520, v0_520, vd, v520, radius, zenith);
    aod_520.opticalDepth();
    AOD_520 = aod_520.getAOD();
    
    aod_440.setAODInputs(longitude, latitude, altitude, lambda_440, CO2_ppv, pressure, month, day, oz_coeff_440, v0_440, vd, v440, radius, zenith);
    aod_440.opticalDepth();
    AOD_440 = aod_440.getAOD();
}