Barometer program : Data Logger function includes Barometer & temperature (BMP180), Humidity & temp. (RHT03), Sunshine (Cds), RTC(M41T62) data. : Logging data saves into EEPROM (AT24C1024) using ring buffer function.

Dependencies:   AT24C1024 RHT03 TextLCD BMP180 M41T62

Fork of mbed_blinky by Mbed

Please see https://mbed.org/users/kenjiArai/notebook/mbed-lpc1114fn28-barometer-with-data-logging/#

main.cpp

Committer:
kenjiArai
Date:
2020-08-08
Revision:
18:b3a27f681171
Parent:
16:f164f8912201

File content as of revision 18:b3a27f681171:

/*
 * mbed Application program for the mbed LPC1114FN28
 * Barometer program for only for LPC1114FN28
 *
 * Copyright (c) 2014,'20 Kenji Arai / JH1PJL
 *  http://www7b.biglobe.ne.jp/~kenjia/
 *  https://os.mbed.com/users/kenjiArai/
 *      Created: May       21st, 2014
 *      Revised: August     8th, 2020
 */
/*
 * Function
 *  measure atmospheric pressure and temprerature using Bosch BMP180 sensor
 *  show measured data on AQM0802A LCD and logging such data in EEPROM
 */

//  Include --------------------------------------------------------------------
#include "mbed.h"
#include "BMP180.h"             // Own lib. / Pressure sensor             
#include "RHT03.h"              // Std. lib./ Humidity sensor
#include "TextLCD.h"            // Std. lib./ LCD control
#include "m41t62_rtc.h"         // Own lib. / RTC control
#include "dt_log.h"

//  Definition -----------------------------------------------------------------
#define USE_MON                 1
#define USE_BARO                0

#define BOUND                   5       // chattering

// Define cyclic period
#define SHOW_LED                1       // Time for LED on x mS
#define CNV_WAIT_T              25      // Waiting time for temp. conversion
#define CNV_WAIT_P              50      // Waiting time for pressure conversion
#define LOOP_WAIT               (1000 - (SHOW_LED + CNV_WAIT_T +CNV_WAIT_P))

// ADC related definition
#define VREF_VOLT               2.482   // TA76431F Vref real measued data
#define R_FIX                   9930    // 10K ohm <- real measued data
#define VOL_OFFSET              3       // Offset data ,= real measured data
#define CDS_TBL_SIZE            13

// Waiting time
#define STATE_CHANGE_TIME       3000000 // 3sec
#define TIME_INTERVAL           600     // 10 minutes

typedef enum {CDS = 0, VREF, VOL} ADC_Select;

//  Object ---------------------------------------------------------------------
Timeout     to;                // wake-up from sleep()
I2C         i2c(dp5,dp27);      // SDA, SCL
DigitalOut  myled0(dp28);       // LED for Debug
DigitalOut  myled1(dp14);       // Indicate state transition
DigitalOut  analog_pwr(dp6);    // VCC for analog interface (vol, cds and vref)
DigitalOut  vref_pwr(dp4);      // VCC for Vref
DigitalIn   sw_chng(dp1,PullUp);// SW for select
DigitalIn   sw_mode(dp2,PullUp);// SW for Mode change
AnalogIn    cds(dp11);          // Input / CDS data
AnalogIn    vref(dp9);          // Input / Bandgap 2.5V
AnalogIn    vol(dp10);          // Input / contrast volume
RHT03       humtemp(dp26);      // RHT03 interface
BMP180      bmp180(i2c);        // Bosch sensor
M41T62      m41t62(i2c);        // STmicro RTC(M41T62)
TextLCD_I2C_N i2clcd(&i2c, 0x7c, TextLCD::LCD8x2);  // LCD(Akizuki AQM0802A)

//  Function prototypes --------------------------------------------------------
extern int mon( void);          // only use for debug purpose

//  RAM ------------------------------------------------------------------------
int flag;

//  ADC
float av_cds, av_vref, av_vol, cal_vcc;
float r_cds, lux;
uint32_t nor_vol;

//  Humidity Sensor
float humidity_temp, humidity;

//  EEPROM
uint8_t eep_buf[256 + 2];

// Barometer
float baro;
float baro_temp;

// EEPROM
//extern xEeprom_ptr log_inf;

//  ROM / Constant data --------------------------------------------------------
// Cds GL5528 (Dark Resistance 1 Mohm type) SENBA OPTICAL & ELECTRONIC CO.,LTD.
//      Table value referrence: http://homepage3.nifty.com/skomo/f35/hp35_20.htm
const float lux_cds[CDS_TBL_SIZE][2] = {
    {50,21194},{100,8356},{200,3294},{400,1299},{800,512},{1600,202},
    {3200,79.6},{6400,31.4},{12800,12.4},{25600,4.88},{51200,1.92},
    {102400,0.758},{409600,0.118}
};

// LCD screen data
enum Screen {
    SCRN_Clear=0, SCRN_Opening, SCRN_Goto_mon, SCRN_Backto_normal
};
//                        Clear       Opening      Goto_mon     Backto_normal
char scrn_1st[4][10] = { "        ", "LPC1114F",  "GOTO MON",  "Back to"};
char scrn_2nd[4][10] = { "        ", " JH1PJL ",  " 9600BPS",  " Normal"};

// Disply on LCD
enum Disp_num {
    DSP_INIT=0, DSP_BARO, DSP_HUMD, DSP_LUX, DSP_TIME, DSP_LOG, DSP_RTURN
};

// loop time = STATE_CHANGE_TIME * 20 = 3 * 20 = 60 sec (current)
// rule 1) DSP_INIT is top position
//      2) DSP_RTURN is end position
//      3) Total number 20
const uint8_t lcd_disp_tbl[20]
//         1,        2,        3,        4,        5,
    = {DSP_INIT, DSP_BARO, DSP_BARO, DSP_BARO, DSP_TIME,
//         6,        7,        8,        9,       10,
       DSP_TIME, DSP_HUMD, DSP_HUMD,  DSP_LUX,  DSP_LUX,
//        11,       12,       13,       14,       15,
       DSP_BARO, DSP_BARO, DSP_TIME, DSP_TIME, DSP_HUMD,
//        16,      17,        18,       19,        20
       DSP_HUMD, DSP_LUX,   DSP_LUX,  DSP_LOG, DSP_RTURN
      };

//------------------------------------------------------------------------------
//  Control Program
//------------------------------------------------------------------------------
// Normalize ADC data
void adc_normalize (ADC_Select n)
{
    int i;
    float x1,y1,dx;

    switch (n) {
        case CDS:
            // v_adc = Rfix / (Rcds + Rfix) ->  Rcds = ( Rfix / v_adc ) - Rfix
            r_cds = (R_FIX / av_cds) - R_FIX;
            // CDS resistance to Lux conversion using convertion table(luc_cds)
            for (i =0; i < CDS_TBL_SIZE; i++) { // search table
                if ( r_cds <= lux_cds[i][0]) {
                    break;
                }
            }
            // Check table position
            if (i == 0) {
                lux = lux_cds[0][1];
                break;
            } else if ( i == CDS_TBL_SIZE ) {
                if ( r_cds <= lux_cds[i][0] ) {
                    lux = lux_cds[i-1][1];
                    break;
                }
            }
            //  Linear interpolation
            y1 = lux_cds[i-1][1] - lux_cds[i][1];
            x1 = lux_cds[i][0] - lux_cds[i-1][0];
            dx = r_cds - lux_cds[i-1][0];
            lux = lux_cds[i-1][1] - ((dx/x1) * y1);
            break;
        case VREF:  //  vref = VREF_VOLT / VCC -> VCC = VREF_VOLT / vref
            cal_vcc = VREF_VOLT / vref;
            break;
        case VOL:   // Vol center = 1.00 (actual 100)
            nor_vol = (uint32_t)(av_vol * 200) + VOL_OFFSET;
            break;
    }
}

//  Read adc data and averaging
void adc_all_read (void)
{
    if (av_cds == 0) {
        av_cds = cds.read();
    } else {
        av_cds = av_cds *0.5 + cds.read() * 0.5;
    }
    if (av_vref == 0) {
        av_vref = vref.read();
    } else {
        av_vref = av_vref *0.9 + vref.read() * 0.1;
    }
    if (av_vol == 0) {
        av_vol = vol.read();
    } else {
        av_vol = av_vol *0.2 + vol.read() * 0.8;
    }
}

// Read Humidity sensor data
void hum_RHT03_read (void)
{
    while (true) {  // wait data
        if ( humtemp.readData() == RHT_ERROR_NONE ) {
            break;
        }
    }
    if (humidity_temp == 0) {
        humidity_temp = humtemp.getTemperatureC();
    } else {
        humidity_temp = humidity_temp * 0.9 + humtemp.getTemperatureC() * 0.1;
    }
    if ( humidity == 0 ) {
        humidity = humtemp.getHumidity();
    } else {
        humidity = humidity * 0.9 + humtemp.getHumidity() * 0.1;
    }
}

void set_lcd_screen(int n)
{
    i2clcd.locate(0, 0);
    i2clcd.printf("%s", scrn_1st[n]);
    i2clcd.locate(0, 1);
    i2clcd.printf("%s", scrn_2nd[n]);
}

//------------------------------------------------------------------------------
// Application program
//------------------------------------------------------------------------------
// Nothing is done but just wake-up from sleep condition
void wakeup()
{
    flag = 1;
    myled1 = !myled1;
}

// Measure pressure and show it on LCD
void conv_and_disp(void)
{
    tm t;
    time_t seconds = 0;
    time_t old_seconds = 0;
    uint32_t step = 0, dt;
    uint8_t num;

    while (true) {          // infinit loop for measure and display
        // Call wakeup()function after specific time
        // this is for wake-up
        to.attach(callback(&wakeup), chrono::milliseconds(STATE_CHANGE_TIME));
        //---- State Control ----
        num = lcd_disp_tbl[step++];
        switch (num) {
            //  ---------- Initialize data -------------------------------------
            case DSP_INIT:
                av_cds = 0;
                av_vref = 0;
                av_vol = 0;
                humidity_temp = 0;
                humidity = 0;
                // RTC
                m41t62.set_sq_wave(RTC_SQW_NONE);
                m41t62.read_rtc_std(&t);
                old_seconds = mktime(&t);
                break;
            //  ---------- Cds Sensor, Vref, Volume ----------------------------
            case DSP_LUX:
                // Power on / Analog sensor
                analog_pwr = 1;
                vref_pwr = 1;
                ThisThread::sleep_for(200ms);
                adc_all_read();
                // Power off / Analog sensor
                analog_pwr = 0;
                // Normalize
                adc_normalize(CDS);
                adc_normalize(VREF);
                adc_normalize(VOL);
                set_lcd_screen(SCRN_Clear);
                i2clcd.locate(0, 0);    // 1st line top
                //             12345678
                i2clcd.printf("L:%.1f", lux);
                i2clcd.locate(0, 1);    // 2nd line top
                i2clcd.printf("V:%.3f", cal_vcc);
                break;
            //  ---------- Barometer Sensor / BMP180 ---------------------------
            case DSP_BARO:
                bmp180.normalize();
                baro = bmp180.read_pressure();
                baro_temp = bmp180.read_temperature();
                set_lcd_screen(SCRN_Clear);
                i2clcd.locate(0, 0);    // 1st line top
                i2clcd.printf("P:%.1f", baro);
                i2clcd.locate(0, 1);    // 2nd line top
                i2clcd.printf("T:%+6.1f", baro_temp);
                break;
            //  ---------- Humidity Sensor / RHT03 -----------------------------
            case DSP_HUMD:
                hum_RHT03_read();       // Read Humidity data then avaraging
                set_lcd_screen(SCRN_Clear);
                i2clcd.locate(0, 0);    // 1st line top
                i2clcd.printf("H:%.1f", humidity);
                i2clcd.locate(0, 1);    // 2nd line top
                i2clcd.printf("T:%+6.1f", humidity_temp);
                break;
            //  ---------- RTC -------------------------------------------------
            case DSP_TIME:
                m41t62.read_rtc_std(&t);
                seconds = mktime(&t);
                set_lcd_screen(SCRN_Clear);
                i2clcd.locate(0, 0);    // 1st line top
                i2clcd.printf("%02d/%02d/%02d",
                              t.tm_year % 100, t.tm_mon + 1, t.tm_mday);
                i2clcd.locate(0, 1);    // 2nd line top
                i2clcd.printf("%02d:%02d:%02d", t.tm_hour, t.tm_min, t.tm_sec);
                break;
            //  ---------- EEPROM Logging --------------------------------------
            case DSP_LOG:
                if (seconds >= old_seconds + TIME_INTERVAL) {
                    // Data Logging action
                    old_seconds += TIME_INTERVAL;
                    dtlog_data_pack();  // Get EEPROM resource
                    dtlog_one_write();  // Write data to EEPROM
                    dt = (uint32_t)dtlog_buf_occupation();
                    dt = (dt * 1000)/ BLK_NO;
                }
                set_lcd_screen(SCRN_Clear);
                i2clcd.locate(0, 0);    // 1st line top
                i2clcd.printf("Logging");
                i2clcd.locate(0, 1);    // 2nd line top
                i2clcd.printf("%d.%01d%%", dt / 10, dt % 10);
                break;
            //  ---------- return (loop) ---------------------------------------
            case DSP_RTURN:
            default:
                //  <State> State change
                step = 1;   // if something wrong, go to reset condition
        }
        //  ---------- back to top ---------------------------------------------
        myled0 = !myled0;
        while (flag == 0) {
            ThisThread::sleep_for(10ms);
        }
        ThisThread::sleep_for(100ms);
        myled1 = !myled1;
        flag = 0;
    }
}

// Application program starts here
int main()
{
    flag = 0;
    i2clcd.setContrast(25);
    set_lcd_screen(SCRN_Opening);
    if (sw_chng == 0) { // SW ON
        //--  Enter Monitor Mode  --
        myled1 = 1;
        ThisThread::sleep_for(500ms);
        myled1 = 0;
        ThisThread::sleep_for(500ms);
        myled1 = 1;
        ThisThread::sleep_for(500ms);
        if (sw_chng == 0) { // Still SW ON
            myled1 = 0;
            ThisThread::sleep_for(500ms);
            myled1 = 1;
            ThisThread::sleep_for(500ms);
            if (sw_mode == 0) { // SW ON
                set_lcd_screen(SCRN_Clear);
                set_lcd_screen(SCRN_Goto_mon);
                myled1 = 0;
                mon();          // mon.cpp
            }
            set_lcd_screen(SCRN_Clear);
            set_lcd_screen(SCRN_Backto_normal);
        }
    }
    //--  Enter Normal Mode  --
    myled0 = 1;
    myled1 = 0;
    while (true) {  // Start main program
        conv_and_disp();
    }
}