mbed Weather Platform firmware http://mbed.org/users/okini3939/notebook/mbed-weather-platform-firmware/

Dependencies:   EthernetNetIf SDHCFileSystem I2CLEDDisp Agentbed NTPClient_NetServices mbed BMP085 HTTPClient ConfigFile I2CLCD

main.cpp

Committer:
okini3939
Date:
2011-06-03
Revision:
19:69b77f9e0446
Parent:
18:9286e5010c14

File content as of revision 19:69b77f9e0446:

/*
 * mbed Weather Platform
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief mbed Weather Platform
 */

#define VERSION "mbed Weather Platform 0.3.0 (C) 2011 Suga koubou Co.,Ltd."

//#define NONBLOCKING // ethernet function non-bloking
 
#include "mbed.h"
#include "BMP085.h"
#include "SHT.h"
#include "WeatherMeters.h"
#include "SDHCFileSystem.h"
#include "MSCFileSystem.h"
#include "EthernetNetIf.h"
#include "NTPClient.h"
#include "HTTPClient.h"
#include "Agentbed.h"
#include "weather.h"
#include "I2CLEDDisp.h"
#include "I2CLCD.h"

Serial pc(USBTX, USBRX), xbee(p13, p14);
volatile int seq = 0;
char filename[20];
char csv[100];
struct Config conf;
DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
LocalFileSystem *local;
SDFileSystem *sd; 
MSCFileSystem *usb;
DigitalIn sd_cd(p21);

// Sensors
struct Sensor sensor, offset, sensor_old;
I2C i2c(p9, p10);
BMP085 bmp085(i2c, BMP085_oss4);
SHT sht15(p12, p11, SHT_high); // sclock, data
WeatherMeters wmeters(p21, p15, p22); // anemo, vane, rain
AnalogIn ailight(p16), aiuv(p17);
AnalogIn *aimoist;
InterruptIn *intcounter;
volatile int count_counter;
volatile unsigned long lastCountTime;

DigitalIn swin2(p19);
DigitalOut swout1(p29), swout2(p30);
I2CLEDDisp *leddisp;
I2CLCD *lcd;
volatile int ledpos, ledflg;
char ledbuf[200];
Ticker ticker;

// Ethernet
EthernetNetIf *eth; 
NTPClient *ntp;
HTTPClient *clientP, *clientT;
DigitalOut led_g2(p24),led_g(p25), led_y(p26);
DigitalIn eth_link(P1_25), eth_speed(P1_26);


float get_photo (AnalogIn &ain) {
    float f;
    
    f = ain * 5.0 / 1000; // A
    return f / 0.0000026; // lx
}

float get_moist (AnalogIn &ain) {
    float f;
    
    f = ain * 5.0; // V
    f = f / ((3.3 - f) / 10.0); // k ohm
    if (f < 0) f = 0;
    return f;
}

float get_uv (AnalogIn &ain) {
    float f;
    
    f = ain * 5.0 / 100000; // A
    f = f / 0.000384; // mW/cm2
    if (f < 0) f = 0;
    return f;
}

void int_counter () {
    count_counter ++;
}

float get_counter (char flg) {
    float t;

    if (flg) {
        // count
        t = (float)count_counter;
    } else {
        // count/min
        if (locUpTime > lastCountTime) {
            t = (float)(locUpTime - lastCountTime) / 6000.0;
        } else {
            t = (float)(0xffffffff - lastCountTime + locUpTime) / 6000.0;
        }
        t = (float)count_counter / t;
    }
    lastCountTime = locUpTime;
    count_counter = 0;
    return t;
}

// Interrupt 10Hz
void isr_timer () {
    int i;
    static int ledfreq = 0;

    // LED Display scroll
    if (conf.leddisp_mesg[0]) {
      ledfreq ++;
      if (ledfreq > LED_FREQ) {
        int i, addr, len;
        
        len = strlen(ledbuf);
        leddisp->locate(0, 0);
        for (i = 0; i < 4; i ++) {
            addr = ledpos + i;
            if (addr >= 0 && addr < len) {
                leddisp->putc(ledbuf[addr]);
            } else {
                leddisp->putc(' ');
            }
        }
        ledpos ++;
        if (ledpos >= len + 4) {
            ledpos = -4;
        }

        ledfreq = 0;
      }
    }

    // timer
    for (i = 0; i < TIMER_NUM; i ++) {
        if (sensor.timer_flg[i] && sensor.timer_cnt[i] < sensor.timer_set[i]) {
            sensor.timer_cnt[i] ++;
        }
    }
    // uptime
    locUpTime = locUpTime + 10;
    led_y = 1;
}

void init () {
    FILE *fp;

    // load config
    sd = new SDFileSystem(p5, p6, p7, p8, "sd");
    if (config("/sd/" CONFIG_FILE) == 0) {
        load_action("/sd/" ACTION_FILE);
    } else {
        delete sd;
        local = new LocalFileSystem("local");
        pc.printf("local strage\r\n", conf.interval);
        config("/local/" CONFIG_FILE);
        load_action("/local/" ACTION_FILE);
    }

    pc.printf("\r\nInterval: %d sec\r\n", conf.interval);

    if (conf.lcd_mesg[0]) {
        // use I2C LCD
        lcd = new I2CLCD(i2c, I2CLCD_ADDR, conf.lcdtype, conf.lcdconf);
    }

    if (conf.leddisp_mesg[0]) {
        // use I2C LED Display
        leddisp = new I2CLEDDisp(i2c);
    }

    if (conf.ipaddr[0]) {
        // use ethernet

        eth_link.mode(PullUp);
        eth_speed.mode(PullUp);
        led_g = eth_link ? 1 : 0;
        led_g2 = 1;
        led_y = 0;
        if (conf.ipaddr[0] == 255) {
            // dhcp
            eth = new EthernetNetIf;
        } else {
            // static
            eth = new EthernetNetIf(conf.ipaddr, conf.netmask, conf.gateway, conf.nameserver);
        }

        EthernetErr ethErr = eth->setup();
        if(ethErr) {
            // error
            conf.ipaddr = IpAddr(0, 0, 0, 0);
        } else
        if (conf.ipaddr[0] == 255) {
            // succeed dhcp
            conf.ipaddr = eth->getIp();
        }
        pc.printf("Ethernet: %d.%d.%d.%d\r\n", eth->getIp()[0], eth->getIp()[1], eth->getIp()[2], eth->getIp()[3]);

        if (conf.ipaddr[0]) {

            if (conf.ntpserver[0]) {
                // ntp
                pc.printf("Ntp: %s\r\n", conf.ntpserver);
                ntpdate();
            }
        
            clientP = new HTTPClient;
            clientT = new HTTPClient;

            if (conf.snmp_commname[0]) {
                Agentbed.begin(conf.snmp_commname, "None", SNMP_DEFAULT_PORT, eth);
                Agentbed.onPduReceive(pduReceived);
                pc.printf("Snmp community name: %s\r\n", conf.snmp_commname);
            }
        }
    } else {
        // not use ethernet
        led_g = eth_link ? 0 : 1;
        led_g2 = 0;
    }

    if (conf.filetype) {
        // seq num

        if (conf.filetype == 1) {
            strcpy(filename, "/sd");
        } else
        if (conf.filetype == 2) {
            usb = new MSCFileSystem("usb");
            strcpy(filename, "/usb");
        }
        strcat(filename, "/weather.seq");
        // load
        fp = fopen(filename, "r");
        if (fp) {
            fscanf(fp, "%d", &seq);
            fclose(fp);
        }
        seq ++;

        // save CSV
        fp = fopen(filename, "w");
        if (fp) {
            fprintf(fp, "%d", seq);
            fclose(fp);
            // csv filename
            if (conf.filetype == 1) {
                sprintf(filename, "/sd/w%05d.csv", seq);
            } else
            if (conf.filetype == 2) {
                sprintf(filename, "/usb/w%05d.csv", seq);
            }
            pc.printf("Filename: %s\r\n", filename);
            led2 = 1;
        }
    }

    pc.printf("Actions: %d\r\n", conf.actionscount);

    // moist sensor or counter
    if (conf.inputtype & INPUT_FALL) {
        intcounter = new InterruptIn(p18);
        intcounter->fall(&int_counter);
    } else
    if (conf.inputtype & INPUT_RISE) {
        intcounter = new InterruptIn(p18);
        intcounter->rise(&int_counter);
    } else {
        aimoist = new AnalogIn(p18);
    }

    count_counter = 0;
    lastCountTime = 0;
}

int main () {
    Timer timer;
    time_t sec;
    
    swout1 = 0;
    swout2 = 0;
    led1 = 1;
    ledpos = -4;
    ledflg = 0;
    strcpy(ledbuf, VERSION);

    init();
    ticker.attach(&isr_timer, 0.1); // Interrupt 10Hz
    pc.printf("%s\r\n\r\n", VERSION);

    if (conf.filetype) {
        // CSV header
        strcpy(csv, "date,pres(hPa),temp(`C),humi(%%),anemo(m/s),vane(`),rain(mm),light(lx),uv(mW/cm2),moist(kohm),\r\n");
        writefile(csv);
    }

    // I2C LED Display (print version)    
    if (conf.leddisp_mesg[0]) {
        ledpos = -4;
        sec = time(NULL);
        strftime(ledbuf, sizeof(ledbuf), "%H:%M", localtime(&sec));
        sprintf(&ledbuf[5], " %ds %s", conf.interval, filename);
        if (conf.ipaddr[0]) {
            sprintf(&ledbuf[strlen(ledbuf)], " %d.%d.%d.%d", conf.ipaddr[0], conf.ipaddr[1], conf.ipaddr[2], conf.ipaddr[3]);
            if (conf.pachube_apikey[0] && conf.pachube_feedid[0]) {
                strcat(ledbuf, " P");
            }
            if (conf.twitter_user[0] && conf.twitter_pwd[0]) {
                strcat(ledbuf, " T");
            }
        }
    }
    
    timer.start();
#ifdef NONBLOCKING
    while (timer.read() < 5) {
        wait_ms(1);
        Net::poll();
    }
    timer.reset();
#endif

    while(1) {
        led1 = 0;

        sec = time(NULL);
        strftime(csv, sizeof(csv), "%Y-%m-%d %H:%M:%S", localtime(&sec));

        // sensors
        __disable_irq();
        bmp085.update();
        sensor.pres = bmp085.get_pressure() + offset.pres;
        sensor.temp2 = bmp085.get_temperature();

        sht15.update(SHT_high);
        sensor.temp = sht15.get_temperature() + offset.temp;
        sensor.humi = sht15.get_humidity() + offset.humi;

        sensor.anemo = wmeters.get_windspeed();
        sensor.vane = wmeters.get_windvane();
        sensor.rain = wmeters.get_raingauge();

        sensor.light = get_photo(ailight);
        if (conf.inputtype == INPUT_MOIST) {
            // moist sensor
            sensor.moist = get_moist(*aimoist);
        } else {
            // counter
            sensor.moist = get_counter(conf.inputtype & INPUT_CPM ? 0 : 1);
        }
        sensor.uv = get_uv(aiuv);

        sprintf(&csv[strlen(csv)], ",%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\r\n",
          sensor.pres, sensor.temp, sensor.humi, sensor.anemo, sensor.vane, sensor.rain, sensor.light, sensor.uv, sensor.moist, sensor.temp2);
        if (conf.filetype) {
            // CSV
            writefile(csv);
        }
        __enable_irq();
        pc.printf(csv);

        // in/out
        action(1);

        // I2C LED Display
        if (conf.leddisp_mesg[0]) {
            if (ledflg) {
                ledpos = -4;
                fmtstr(conf.leddisp_mesg, ledbuf, sizeof(ledbuf));
            }
            ledflg = 1;
        }
        // I2C LCD
        if (conf.lcd_mesg[0]) {
            char buf[80];
            fmtstr(conf.lcd_mesg, buf, sizeof(buf));
            lcd->cls();
            lcd->puts(buf);
        }

        led1 = 1;

        // interval (wait)
        while (timer.read() < conf.interval) {
            wait_ms(100);

            // in/out (timer)
            if (locUpTime % 100 == 0)
                action(0);

            // ethernet LED
            if (conf.ipaddr[0]) {
                led_g = eth_link ? 1 : 0;
                led_g2 = 1;
            } else {
                led_g = eth_link ? 0 : 1;
                led_g2 = 0;
            }
            Net::poll();

            // for debug                        
            if (pc.readable()) {
                int i;
                i = pc.getc();
                if (i == ' ') {
                    break;
                } else {
                    pc.printf("( %d )\r\n", (int)timer.read());
                }
            }
        }
        timer.reset();
    }
}