Lab3

Urban Jungle Weather - By Kenneth Adams and Spencer Reardon
Urban Jungle Weather is a project to allow remote access to current and past temperature, humidity and pressure sensor readings from an mbed board.  It also keeps track of the current time using an RTC that is initialized with the Columbia County (Georgia) time server at boot time.  The mbed board runs a web server that hosts an html and javascript based web page that displays the current weather (as read from the sensors) and submits sensor readings to pachube (a free online database).  Pachube hosts plots of the sensor data for various time frames; these plots are used on the web page to display the history of sensor data for the three sensors.

The current weather information gathered from the sensors.

 

Historical sensor data plotted on a graph.

 

Map showing the location of the sensors.  The location can be pre-programmed or come from the GPS module.



List of mbed components and peripherals used

  • Ethernet (RJ-45 jack on a breakout board)
  • Pressure/Temp Sensor (SCP1000)
  • Humidity/Temp Sensor (Phidgets P/N1125)
  • Internal Flash Chip (alternate micro SD card code exists, but is untested)
  • Internal RTC
  • (Optional addition) GPS (such as the GlobalSat GPS Module)


Board's LED based Error Codes

LED1       |LED2       |LED3       |LED4      
-----------+-----------+-----------+-----------
Server     |Ethernet   |Sensor Read|Error
Listening  |Ready      |Toggle     |
-----------------------------------------------

If the error led (LED4) is flashing, then there was an error which is described by the other 3 leds as follows:

  • No leds lit - Ethernet Timeout
  • LED1 only - File IO error
  • LED2 only - Feed upload error

Web Page
The web page refreshes sensor readings approximately once every 30 seconds.  From these updated readings, the sensor values displayed on the page are updated and the background image for the page may be updated (e.g. if the temperature drops significantly, it changes the background to an icy, glacier landscape).
The sensor readings come from a json (javascript compatible text file) generated by and located on the mbed board.

Possible Future Additions
Currently, the mbed board generates a json, sensor file populated with arbitrary GPS coordinates that could quickly and easily be replaced by the values read from a GPS device.  These coordinates are passed into a Google maps embedded object, and can be used to generate a marker on a Google map that shows you the location of the GPS device and therefore the location of the mbed board (this may be useful for tracking non-stationary weather boards).

Code

 

#include "mbed.h"

//#define SD_FS

#include "EthernetNetIf.h"
#include "HTTPServer.h"
#include "HTTPClient.h"
#ifdef SD_FS
#include "SDFileSystem.h"
#endif
#include "GPS.h"
#include "NTPClient.h"

#include "SCP1000.h"
#include "PachubeClient.h"
#include "main.h"

/***********
 *   I/O   *
 ***********/
DigitalOut listenStatus(LED1);          // Blink when HTTP server is listening
DigitalOut ipStatus(LED2);              // Set when IP address acquired
DigitalOut pollStatus(LED3);            // Reserved
DigitalOut errorStatus(LED4);           // Blink when error condition occurs; read other LEDs for code.

AnalogIn humiditySensor(p17);           // 
//AnalogIn tempSensor(p16);               // Temp sensor.

SCP1000 scp1000(p5,p6,p7,p8);           // Temp & pressure.


GPS gps(p9, p10);

#ifdef SD_FS
SDFileSystem sd(p5, p6, p7, p8, "fs");  // the pinout on the mbed Cool Components workshop board
#else
LocalFileSystem local("fs");
#endif

NTPClient ntp;

/**
 * Blink the error LED and place the error code on the other LEDs.
 * WARNING: Never returns!
 *
 */
void ledError(ErrorCode code) {
    listenStatus = code & 1;
    ipStatus = (code >> 1) & 1;
    pollStatus = (code >> 2) & 1;

    while (true) {
        errorStatus = !errorStatus;
        wait(BLINK_RATE);
    }
}

/**
 * Read sensor data and write it to file.
 */
void pollSensors() {
    int locked = 0;
    float temp = 0;
    //float tempB = 0;
    
    float lat = 0;
    float lng = 0;
    float pressure = 0;
    float humidity = 0;
   
    char * timeStr;
    time_t ctTime;
    
    pollStatus = !pollStatus;
    
    FILE* fp = fopen("/fs/sensors.htm", "w");
    if (fp == NULL) {
        ledError(ERR_FILE);
    }

    // Temp
    // (SensorValue/4) - 50
    //temp = tempSensor * 160 - 50; // Analog to deg C
    //temp = 1.8 * temp + 32; // deg C to F.
    
    temp = scp1000.readTemperature();
    temp = 1.8 * temp + 32; // deg C to F
    
    // Pressure
    unsigned long ulPressure = scp1000.readPressure();
    pressure = ((float) ulPressure) / 1000.0; // Pa to kPa
    
    // Humidity
    // RH (%) = (SensorValue x 0.1906) - 40.2
    
    // This might be wrong.
    humidity = (1000 * humiditySensor * 0.1906) - 40.2;
    
    ctTime = time(NULL);
    ctTime -= 60 * 60 * 4; // Account for timezone offset.
    timeStr = ctime(&ctTime);
    
    int i = 0;
    while (timeStr[i] != '\0') {
        if (timeStr[i] == '\n') {
            timeStr[i] = ' ';
        }
        i++;
    } 
    

    // True if GPS is locked.
    //if (gps.sample()) {
        //locked = 1;
        //lat = gps.latitude;
        //lng = gps.longitude;
    //}
    
    fprintf(fp, "{\n\t\"gpsLocked\": %d,\n", locked);
    fprintf(fp, "\t\"latitude\": %f,\n", lat);
    fprintf(fp, "\t\"longitude\": %f,\n", lng);
    fprintf(fp, "\t\"temperature\": %4.2f,\n", temp);
    fprintf(fp, "\t\"pressure\": %5.2f,\n", pressure);
    fprintf(fp, "\t\"time\": \"%s ET\",\n", timeStr);
    fprintf(fp, "\t\"humidity\": %5.2f\n}", humidity);
    
    //postFeed(pressure, humidity, temp);
    
    fclose(fp);
}

/**
 * Flip listening status LED.
 */
void flipLed() {
    listenStatus = !listenStatus;
}

/**
 * Entry point
 */
int main() {
    EthernetNetIf eth;
    HTTPServer server;
    
    ipStatus = 0;
    listenStatus = 0;
    pollStatus = 0;

    EthernetErr ethErr = eth.setup();
    if(ethErr) {
        ledError(ERR_ETHERNET);
    }
    
    Host ntpServer(IpAddr(), 123, "nist1.columbiacountyga.gov");
    ntp.setTime(ntpServer);
    
    ipStatus = 1;
    
    // Web root directory
    FSHandler::mount("/fs", "/");
  
    // Bind the filesystem handler for all requests        
    server.addHandler("/"); // "/" matches every URL
    server.bind(80); // listen port
    
    Ticker ledTicker;
    ledTicker.attach(&flipLed, BLINK_RATE);
    
    pollSensors();
    
    Ticker pollTicker;
    pollTicker.attach(&pollSensors, SENSOR_POLL_RATE);
    
    // Listen indefinitely
    while(true)
    {
        Net::poll();
    }
  
    return 0;
}

 

This is the HTML for the Lab3 page:

 


1 comment

23 Feb 2014 . Edited: 23 Feb 2014

hi kenneth,

we are doing a similar project as mentioned in this page,but we do not know how to assign the ip address to the mbed board

can you please give us the details on how to assign the ip address?

thank you.

You need to log in to post a comment