Showing posts with label Humidity&Temperature Web Logger. Show all posts
Showing posts with label Humidity&Temperature Web Logger. Show all posts

Tuesday, June 10, 2014

Create Graph with DB Data using Chart JS - Humidity & Temperature Web Logger

Let's modify WSDHT1.0.html little bit to create graph.



There is nothing much different from other previous graphs, except that we have two Data and we have two vertical axis.

First do Chart Configuration:

        $(function() {
            $("#chartContainer").dxChart({
                title: {
                    text: 'Temperature & Humidity Graph'
                },
                // Left y-axis: temperature, right y-axis: humidity
                valueAxis: [{ name: 'mainAxis', position: 'left', title: { text: 'Temperature (C)'} },
                        { name: 'secondaryAxis', position: 'right', title: { text: 'Humidity (%)'}}],
                dataSource: chartDataSource,
                legend: { verticalAlignment: "bottom", horizontalAlignment: "center" },
                // Humidity & Temperature have common x-axis: time
                commonSeriesSettings: { argumentField: 'time' },
                // Use 'spline' type to make smooth curves
                series: [{ name: 'Temperature', valueField: 'temperature', point: { visible: false }, type: 'spline', axis: 'mainAxis' },
                     { name: 'Humidity', valueField: 'humidity', point: { visible: false }, type: 'spline', axis: 'secondaryAxis'}]
            });
        });


Then Add Chart Data:

        function graphData() {
            var len, i;
            var chartData = [];
            blockNo = document.getElementById("DataBlockNo").value;
            db.transaction(function(tx) {
                tx.executeSql('SELECT * FROM LogData WHERE block="' + blockNo + '"', [], function(tx, results) {
                    len = results.rows.length;
                    if (len > 42) len = 42;
                    for (i = 0; i < len; i++) {
                        chartData.push({ time: i, temperature: parseFloat(results.rows.item(i).temperature), humidity: parseFloat(results.rows.item(i).humidity) });
                    }
                    observableChartDataSource = ko.observableArray(chartData);
                    var chart = $("#chartContainer").dxChart("instance");
                    var dataSource = chart.option('dataSource', chartData);
                }, null);
            });
        }


Full codes can be found in following links





Monday, June 9, 2014

Log Data Upload - Humidity & Temperature Web Logger

I have purchased DHT11 Humidity & Temperature Sensor from the following site.
http://www.dfrobot.com/index.php?route=product/product&product_id=174#.U4lzu3J_uSq

They deliver only the sensor.  It has Connector and Wire; however, there is no PCB.



BUT, it doesn't have cable to connect to Arduino.
So I had to purchase the Arduino jumper wire set, which I thought was useless. :(
http://www.eleparts.co.kr/EPXCTKGY ( the following site is Korean site. You might have to search for other site in your own country if you need to purchase one. )



Using the correct colors ( it's not a must ), connect it to Arduino.  I attached it to Connector on RTC Shield.

Red cable: +5V Power.  Top left connector, fifth pin from the top.
Black cable: GND.  Bottom left connector, first pin from the top.
Green cable: A0.  Top right connector, fourth pin from the top.

Download library and import it.


If you upload the dht.ino included in the zip file,



  1. Temperature: It was very hot today; however, it looks somewhat correct.  When I get an actual thermometer I will re-check.
  2. Humidity: Humidity calculation is based on Temperature, thus if the temperature is not correct humidity cannot be correct.
  3. Although there is a decimal point, the decimal value is always 0.  If we change to better sensor I assume it will give us the decimal values so I'm going to stick with the float.  Accuracy of sensor is not the point in this posting so I'm going to move on.

In dht.ino change #define DHT11_PIN 4 to #define DHT11_PIN A0, and 
chk = DHT.read11(DHT11_PIN); to int chk = DHT.read11(DHT11_PIN);.


Protocol

I have modified Get Data Block "GETn".
D = <time stamp> + <Temperature> + <Humidity>
We are going to send time stamp, temperature, and humidity all at the same time.



Arduino Code

Following is excerpts from the code.  The entire code can be found in the link at the very bottom.  I modified WSAdam5.ino to create the following code.
#include <dht.h>
... OMIT ...
#define LOG_BLOCK_SIZE 96
... OMIT ...
//-------------------------------------DHT-11
#define DHT11_PIN A0
//#define SAMPLING_INTERVAL (3*1000)

// If you set it to this, it will read sensor value every minute.
// It takes forever to debug if you set it to 10 minutes.
// Arduino default is 16 bit int. If you don't do (uint32_t)
// it becomes -5536
#define SAMPLING_INTERVAL (uint32_t)60*1000
#define MAX_REC_SIZE  42 // 512/12 = 42.666...

dht DHT;
float humidity;
float temperature;
void DHTPoll();
... OMIT ...
void loop() {
 wsServer.listen();
 
 if(sdStatus) {
  if((millis() - lastPollTime) >= SAMPLING_INTERVAL) {
   lastPollTime = millis();
   DHTPoll();
  }
 }
}

/*
  ----------------------------------------------------------------
   D H T - 1 1   h a n d l e r
  ----------------------------------------------------------------
*/
void DHTPoll() {
 if(DHT.read11(DHT11_PIN) == DHTLIB_OK) {
  humidity = DHT.humidity;
  temperature = DHT.temperature;

  if(sdStatus) makeLogBlock();
 }
}
... OMIT ...
void SDbegin(void) {
... OMIT ...
 //load last block
 sdCard.readBlock(currBlock, sdBuffer);
 pB = sdBuffer;

 if(*((uint32_t*)pB) != USED_MARK) { // New data block
  *((uint32_t*)pB) = USED_MARK; // Used Flag
  *((uint32_t*)(pB + 4)) = 0; // for this Logging Block
                              // set the record to 0 and
                              // add 3 bytes padding
 }

 LogBlockSize = sdBuffer[4]; // Used data block
 sdStatus++;  
 printCurrBlock(); //debug purpose
}
... OMIT ...
void makeLogBlock(void) {
... OMIT ...
 //------------------------- push Data into Buffer
 pB = sdBuffer + 8 + (LogBlockSize * 12);
 now = rtc.now();

 *((uint32_t*)pB) = now.unixtime(); // Time-stamp 
 *((float*)(pB + 4)) = temperature; // Temperature
 *((float*)(pB + 8)) = humidity; // Humidity
... OMIT ...
 //------------------------- write to SD card everytime
 LogBlockSize++;
 sdBuffer[4] = LogBlockSize;
 sdCard.writeBlock(currBlock, sdBuffer);

 //------------------------- If the Data Block is complete, 
 //           fix the Free block location and reset Buffer
 if(LogBlockSize >= MAX_REC_SIZE) {
  currBlock++;
  update_currBlock();

  pB = sdBuffer;
  *((uint32_t*)pB) = USED_MARK; // Used Flag
  *((uint32_t*)(pB + 4)) = 0; // Set this logging Block's record
                              // to 0 and add 3 bytes padding
  LogBlockSize = 0;
 }  
... OMIT ...
void upload_DataBlock(uint32_t reqBlock) {
... OMIT ...
 cnt = *pS;
 pS += 4;
 printLn[0] = 'D';

 while(cnt--) {
  // time stamp (seconds)
  ltoa(*((uint32_t*)pS), printLn + 2, 10);
  pC = printLn + strlen(printLn);
  *pC++ = '=';
  pS += 4;
  
  // Temperature
  dtostrf(*((float*)pS), 6, 2, pC); // -12.34C
  pC = printLn + strlen(printLn);
  *pC++ = '=';
  pS += 4;

  // Humidity
  dtostrf(*((float*)pS), 6, 2, pC); // 12.34%
  pS += 4;
  WSsend(printLn, strlen(printLn));
 }

 printLn[2] = '0'; //timestamp == 0, end-of-data
 WSsend(printLn, 3);
... OMIT ... 


HTML / JS Code

This code shows how to upload data using Web Socket, and how to create Web DB using the uploaded data.  Codes below are only part of the code.  If you want to see the entire code look at the link at the very bottom.
This code is modified from WSAdam6_5.html.

Clicking [GetDataBlock] button will display the Temperature & Humidity Data in DB.



... OMIT ...
      var db = openDatabase('WebLogger10', '1.0', 'Web Logger', 512*1024);

      $(document).ready(function() {
        WebSocketConnect();
        db.transaction(function (tx) {
          tx.executeSql('CREATE TABLE IF NOT EXISTS LogIndex(block, timeStamp)');
          tx.executeSql('CREATE TABLE IF NOT EXISTS LogData(block, timeStamp, temperature, humidity)');
        });
      });
... OMIT ...
      function WebSocketConnect() {
... OMIT ...
            // receive Data Block
            if(ar[0] == 'D'){
              data[rcvCnt++] = ar[1];
              data[rcvCnt++] = ar[2];
              data[rcvCnt++] = ar[3];
              if(ar[1] == '0'){
                $("#recordCntPara").empty();  
                $("#recordCntPara").append('Received:' + rcvCnt);
                if(blockNo != 0){
                  db.transaction(function (tx) {                  
                    if(rcvCnt>126) rcvCnt = 126;
                    rcvCnt /= 3;
                    $("#recordCntPara").append(',Record Count:' + rcvCnt);
                    for(i=0;i<rcvCnt;i++){
                      tx.executeSql("INSERT INTO LogData VALUES(?, ?, ?, ?)", [blockNo, data[i*3], data[i*3+1], data[i*3+2]]);
                    } 
                  });
                  db.transaction(function (tx) {
                    tx.executeSql("INSERT INTO LogIndex VALUES(?, ?)", [blockNo, data[0]]);
                  });
... OMIT ...
      function viewData() {
... OMIT ...
            for(i=0;i<len;i++){
              timeStamp = results.rows.item(i).timeStamp;
              tod.setTime((timeStamp - (9*3600)) * 1000);
              $("#dumpPara").append('<p>' + tod.toLocaleString() + '  ' + results.rows.item(i).temperature + 'C ' + results.rows.item(i).humidity + '%<p>');
            }
... OMIT ...



Full codes can be found in following links





Sunday, June 8, 2014

Construct - Humidity & Temperature Web Logger

This time I'm going to create Humidity & Temperature Logger to outline how easy it is to create Web Logger.



Humidity & Temperature Sensor

I have used DHT11, the most common Arduino Humidity & Temperature sensor.
http://www.dfrobot.com/index.php?route=product/product&product_id=174#.U4--irkU9aR
The above site has many more interesting gadgets to look at.

DHT11 datasheet can be downloaded from following site, or it can also be found in the link at the bottom.
http://www.micro4you.com/files/sensor/DHT11.pdf

Item Measurement Range Humidity Accuracy Temperature Accuracy Resolution Package
DHT11 20-90% RH
0-50°C
±5% RH ±2°C 1 4 Pin Single Row

Accuracy for both Temperature & Humidity sucks; however, DHT11 is easy to purchase and connect.  I will try working with higher accuracy model next time.

It says Resolution for both are 8 bit; however, if you look at the data format it is a different story.

Data Format: 

  • 8 bit integral RH data 
  • + 8 bit decimal RH data 
  • + 8 bit integral T data 
  • + 8 bit decimal T data 
  • + 8 bit check sum

If we start thinking about decimal points it gets confusing when coding.  Thus we are going to use floating just like we did for ADAM-4017.




Data Block Components

It is highly unlikely Temperature & Humidity changes drastically.
For this sensor, the response time for humidity is 15 seconds and temperature is 30 seconds ( in data sheet ).
I am going to measure every 10 minutes.

If we measure every 10 minutes, it is going to take multiple hours to fill up 1 sector.  And if for some reason if you decide to reboot, you are going to lose hours worth of Data.
This is very unwanted situation, thus we are going to write to SD every time we measure.
Add time stamp to each measured data.


  • Used Flag: 4 bytes
    Set it to 0xaa55a55b
  • Data Count: 1 byte
    Number of Data in sector. 0, 1 - 42
  • Extra: 3 bytes
    Fill it with Null.
  • Data: 12 bytes
    42 will fit in 1 Data Block (8 + 42 * 12 = 512)
    • Time Stamp: 4 bytes
      Use only sec part of POSIX time_t.
      Must *1000 because we are not using millisecond part.
      It is 32 bit unsigned integer.
    • Temperature: 4 bytes floating
    • Humidity: 4 bytes floating

Each sector will contain 42 * 10 min = 420 min = 7 hrs worth of data.
Each Data has its own time stamp, thus sector is not ordered in time or date.



Full codes can be found in following links