<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="sodnpoo.xsl" type="text/xsl"?>
<xml page="/?t=weathoscope"><a href="http://sodnpoo.com/?x=html">HTML version</a><post>
  <tag value="weathoscope"/>
  <tag value="arduino"/>
  <title>weathoscope v2</title>
  <date>29 Sep 2013</date>
  <p>
  </p>
  <p>
  After a long time without any sort of attention, the weathoscope has had a bit of an overhaul. A few months ago I rewrote the <a href="/weathoscope/">web UI</a>, mostly just to use jQuery and <a href="http://www.flotcharts.org/">flot</a> rather than the Google charts API. The <a href="/posts.xml/arduino_with_bmp085_gas_pressure_sensor.xml">BMP085 pressure sensor breakout board</a> I was playing with back in March has been integrated. Here it is on the breadboard:
  </p>
  <image src="/posts.assets/arduino_bmp085_1.jpg"/>
  <p>
  And here it is wrapped in some heat shrink tubing for protection. There's a square hole cut in the tubing with a scalpel to expose the actual sensor. (The white stuff is the remnants of a piece of sticky foam pad; I forgot to take a picture before sticking it down...)
  </p>
  <image src="/posts.assets/weathoscope_v2b.jpg"/>
  <p>
  Although the BMP085 is a pressure sensor it also provides a digital temperature output - as this is factory calibrated it has replaced the readings I was previously getting <a href="/posts.xml/arduino_weather_monitoring_station_1.xml">using a LM335Z</a>. The LM335Z is still connected and logged, I just don't use the values in the front end.
  </p>
  <p>
  The <a href="/posts.xml/arduino_weather_monitoring_station_2.xml">anemometer is the device I first made back in December 2010</a>. It's only recently come into service with some cups taken from a basic weather station kit - it originally had some home made blades but these were just rubbish; they didn't really turn easily and fell apart in the end. 
  </p>
  <image src="/posts.assets/weathoscope_v2a.jpg"/>
  <p>
  Inside the blue box, at the other end of the axle is a cog with a single hole, an infrared LED and light dependant resistor. The LDR is connected to one of the arduino's interrupt pins and gets triggered when the hole is between the LED and the LDR. I.e. once per revolution. Using the radius of the cups and the count of the revolutions over a known time period we can calculate the wind speed.
  </p>  
  <image src="/posts.assets/anemometer-closeup.jpg"/>
  <p>
  <span class="header">Software</span>
  The software stack comprises of the arduino code that deals with the individual sensors, then outputs a set of key value pairs on the uart (once per minute). This is read by a perl script running on the host PC that parses and inserts the readings into a postgres database. A recent amendment makes this script pushes the data up to <a href="http://openweathermap.org/station/62810">OpenWeatherMap</a> too.
  </p>
  <p>
  On the front end web server there's a small PHP script that acts as a simple RPC wrapper around the DB. It'll take one of the date ranges (day, week, month etc) and output a JSON-ified object ready for feeding into flot. Finally there's a bit of jQuery combined with flot to draw the graphs. APC is used to cache the results from the DB to avoid hitting the DB too often.
  </p>
  <p>
  The latest code needs a bit of a clean up before I can release it; hopefully get it posted in the next week or so.
  </p>
  <p>
  <span class="header">Plans</span>
  Current plans include extending the system with a humidity sensor, replace the light sensor that has corroded away and maybe once the 3D printer arrives, build a <a href="https://en.wikipedia.org/wiki/Rain_gauge#Tipping_bucket_rain_gauge">tipping bucket rain gauge</a>.
  </p>
  <p>
  Web UI is <a href="/weathoscope/">here</a>. To see the other weathoscope related posts click the 'weathoscope' tag at the bottom of the page (or click <a href="/?x=&amp;n=&amp;t=weathoscope">here</a>).
  </p>
</post><post>
  <tag value="arduino"/>
  <tag value="weathoscope"/>
  <title>arduino with bmp085 gas pressure sensor</title>
  <date>4 Mar 2013</date>
  <p>
  Just a breadboard arduino and a <a href="https://www.sparkfun.com/products/9694">bmp085 pressure sensor</a> - nothing spectacular just connected via a level shifter to the I2C pins but it did work first time :)
  </p>
  <image src="/posts.assets/arduino_bmp085_1.jpg"/>
  <p>
  And here's a screen grab of the output from the test code I found <a href="http://ilabbali.com/code/Arduino_BMP085.cpp">here</a>.
  </p>
  <image src="/posts.assets/arduino_bmp085_2.jpg"/>
  <p>
  </p>
</post><post>
  <tag value="arduino"/>
  <tag value="weathoscope"/>
  <title>arduino weather monitoring station 5</title>
  <date>16 Jan 2011</date>  
  <header>In situ pictures</header>
  <p>
  Below is a picture of the weathoscope mounted on the inside of the shed. You can see the USB cable on the right and the black/yellow cable of the temperature probe on the left. The probe cable runs out through the gap beween the wall and the roof, the probe itself hanging in the air.
  </p>
  <image src="/posts.assets/weathoscope_insitu.jpg"/>
  <p>
  I'm hoping that hanging there will be both out of direct sunlight and out of the rain.
  </p>
  <image src="/posts.assets/weathoscope_insitu_outside.jpg"/>
  <p>
  Weathoscope can be found <a href="/weathoscope">here</a>.
  </p>
  <p>
  Code available on <a href="https://github.com/sodnpoo/arduino/tree/master/weathoscope">github</a>.
  </p>
</post><post>
  <tag value="arduino"/>
  <tag value="weathoscope"/>
  <title>arduino weather monitoring station 4</title>
  <date>16 Jan 2011</date>  
  <header>Server side code changes</header>
  <p>
  I've just pushed the latest server side code changes up to github. The biggest change is that the persistent storage has been moved to a postgres database instance to allow efficient retrieval based on date ranges. The database schema is just one table with two columns - a timestamp and the temperature.
  </p>
  <p>
  The background perl script - <a href="https://github.com/sodnpoo/arduino/blob/master/weathoscope/weathoscope_logger_db.pl">weathoscope_logger_db.pl</a> - now uses the DBI perl module and simply inserts the values into the database as they are read from the arduino.
  </p>
  <p>
  On the web front end, the php script - <a href="https://github.com/sodnpoo/arduino/blob/master/weathoscope/index.php">index.php</a> - runs a small SQL query to extract the latest captured temperature :
  </p>
  <pre>
  SELECT temp FROM log ORDER BY ts DESC LIMIT 1
  </pre>
  <p>
  It also outputs a couple of image tags linking to a third php script - <a href="https://github.com/sodnpoo/arduino/blob/master/weathoscope/temp_chart_db.php">temp_chart_db.php</a> - which handles the dirty job of taking the data returned from the DB and formatting it into something the google charts api can work with. It can take an optional parameter that changes the date range from 1 day to 1 week. I plan to make longer ranged graphs available as soon as I have the data (within the bounds of reasonable query response times anyway).
  </p>
  <p>
  There been some strange spikes on the graphs over the past week - I suspect the probe need repositioning further away from the house and the on-device smoothing probably needs it's number of samples increasing.
  </p>
  <p>
  Weathoscope (with graphs) can be found <a href="/weathoscope">here</a>.
  </p>
  <p>
  Code available on <a href="https://github.com/sodnpoo/arduino/tree/master/weathoscope">github</a>.
  </p>
</post><post>
  <tag value="arduino"/>
  <tag value="weathoscope"/>
  <title>arduino weather monitoring station 3</title>
  <date>3 Jan 2011</date>  
  <header>Initial version</header>
  <p>
  Here's the first version of the weathoscope. This initial version only supports temperature but I'll add sensors as they and time become available. It's now installed in the shed with the LM335Z sticking outside sampling the air in the back garden.
  </p>
  <image src="/posts.assets/weathoscope_v1a.jpg"/>
  <p>
  And with the lid on:
  </p>
  <image src="/posts.assets/weathoscope_v1b.jpg"/>
  <p>
  The code running on it (below) dumps the current values of the sensors on a single line consisting of key/value pairs, to the serial port every 60 seconds. 
  </p>
  <pre>
#include "stdlib.h"
#include "math.h"
#include "wiring.h"
#include "WProgram.h"
#include "Wire.h"

#include &lt;Smoothing.h&gt;
#include &lt;Timer.h&gt;

//status LED
const int LEDPIN = 13;

//rotorary encoder photocell - wind speed
/* NOT USED
const int PHOTOPIN = 0;
volatile int state = LOW;
volatile int counter = 0;
*/

//LM335Z - temperature
const int LM335RATE = 1000; // 1 second
const int LM335PIN = 0;
Timer LM335Timer;
Smoothed LM335Smooth;
int LM335toDegreesC(int raw, int fudge){
//Algorithm to convert the LM335 output signal from the ADC to degrees C.
  return (((raw * 500L) / 1023L) - 273L) + fudge; 
} 

//dump data timer
Timer dumpTimer;
const int DUMPRATE = 60000; //60 seconds

void setup(){
  Serial.begin(9600);
  Serial.println("setup");

  digitalWrite(LEDPIN, LOW);

  /* NOT USED
  pinMode(PHOTOPIN, INPUT);
  attachInterrupt(PHOTOPIN, windSpeedISR, FALLING);
  */
  
  newSmoothed(&amp;LM335Smooth, 10);
  newTimer(&amp;LM335Timer, LM335RATE);

  newTimer(&amp;dumpTimer, DUMPRATE);
  
  delay(1000);
}

void windSpeedISR()
{
  /*
  state = !state;
  counter++;
  */
}

int smoothedLM335 = 0;

void loop(){
  if( checkTimer(&amp;LM335Timer) ){
    int rawLM335 = analogRead(LM335PIN);
    smoothedLM335 = smoothReading(&amp;LM335Smooth, rawLM335);
  }
  
  if( checkTimer(&amp;dumpTimer) ){
    digitalWrite(LEDPIN, HIGH);
    
    int degreesC = LM335toDegreesC(smoothedLM335, -4);
  
    Serial.print("degreesC:");
    Serial.print(degreesC);

    Serial.print('/'); // divider
      
    Serial.println();
    
    digitalWrite(LEDPIN, LOW);
  }
  
}  
  </pre>
  <p>
  On the web server a perl script reads the line from the USB serial port and writes out two files. First it writes the latest line to <a href="http://sodnpoo.com/weathoscope/weathoscope.out">weathoscope.out</a> - this file can then be easily picked up by a PHP script for displaying the live data. Secondly it parses it into it's key/value pairs building a simple CSV line to be appended to <a href="http://sodnpoo.com/weathoscope/weathoscope.csv">weathoscope.csv</a>. The CSV file can later be used for historical analysis and graphing. Both these files are available on the public part of the web server for potential re-use. 
  </p>
  <pre>
#!/usr/bin/perl

use Device::SerialPort;
use DateTime;
use Data::Dumper;

$LOGDIR    = "/var/www/htdocs";
#$LOGDIR    = "/tmp";
$LOGFILE   = "weathoscope.out";
$CSVFILE   = "weathoscope.csv";
$PORT      = "/dev/ttyU0";
#$PORT      = "/dev/ttyUSB1";

my $port = Device::SerialPort-&gt;new($PORT);
$port-&gt;databits(8);
$port-&gt;baudrate(9600);
$port-&gt;parity("none");
$port-&gt;stopbits(1);

open(LOG,"&gt;${LOGDIR}/${LOGFILE}") || die "can't open log file\n";
open(CSV,"&gt;&gt;${LOGDIR}/${CSVFILE}") || die "can't open csv file\n";

while (1) {
  my $data = $port-&gt;lookfor();
  if ($data) {
    #print "$data\n";

    #write latest to LOG
    truncate(LOG, 0);
    seek(LOG, 0, 0);
    syswrite LOG, $data;

    #now decode for the CSV
    my $dt = DateTime-&gt;now();

    #looking for these
    my $degreesC = "";

    $data =~ s/\r|\n//g;
    
    my @keyvals = split(/\//, $data);
    foreach(@keyvals){
      my @keyval = split(/:/, $_);
      #degreesC
      if(@keyval[0] =~ /degreesC/){
        $degreesC = @keyval[1];
      }
      #blahblah
      #if(@keyval[0] =~ /blahblah/){
      #  $blahblah = @keyval[1];
      #}
      
    }
    #write csv
    my $csv = "$dt, $degreesC\n";
    syswrite CSV, $csv;
  } else {
    sleep(1);
  }
}
  </pre>
  <p>
  The lines outputed from the arduino are in the following format, which you can see just need to be split by a forward slash to get an array of key/value pairs and then each of these to be split by a colon to get the key and value.
  </p>
  <pre>
  key1:value1/key2:value2/key3:value3
  </pre>
  <p>
  The nicely presented data can be found <a href="http://sodnpoo.com/weathoscope/index.php">here</a>. The PHP script opens the .out file and double-splits the line, parsing the value(s) it needs. It outputs a 'standard' sodnpoo.com <a href="http://sodnpoo.com/posts.xml/atom_feed_using_xml_and_xslt.xml">blog XML file</a> that automatically gets transformed and styled.
  </p>
  <pre>
&lt;?php header('Content-Type: text/xml'); ?&gt;
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;?xml-stylesheet type="text/xsl" href="/sodnpoo.xsl"?&gt;
&lt;xml&gt;
&lt;post&gt;
  &lt;title&gt;weathoscope&lt;/title&gt;
  &lt;date&gt;&lt;/date&gt;
  &lt;p&gt;
  &lt;span class="header"&gt;Current temperature:
  &lt;?php 
    $out = file_get_contents("/htdocs/weathoscope.out");
    $keyvals = explode('/', $out);
    foreach($keyvals as $keyval){
      //echo $keyval."\n";
      $kv = explode(':', $keyval);
      if($kv[0] == 'degreesC'){
        echo $kv[1];
      }
    }
  ?&gt;
  &lt;/span&gt;&lt;/p&gt;
  &lt;p&gt;
  &lt;a href="/weathoscope.csv"&gt;log file (csv)&lt;/a&gt;
  &lt;/p&gt;
&lt;/post&gt;
&lt;/xml&gt;
  </pre>
  <p>
  I'm planning on adding a humidity sensor and my <a href="http://sodnpoo.com/posts.xml/arduino_weather_monitoring_station_2.xml">homemade wind speed meter</a> next. Although I have plans for a laser rainfall meter and barometer eventually.
  </p>
  <p>
  Code available on <a href="https://github.com/sodnpoo/arduino/tree/master/weathoscope">github</a>.
  </p>
</post><post>
  <tag value="arduino"/>
  <tag value="weathoscope"/>
  <title>arduino weather monitoring station 2</title>
  <date>18 Dec 2010</date>  
  <p>
  <span class="header">Wind speed</span>
  </p>
  <p>
  To measure wind speed I needed to be able to count the rotations of some sort of propeller in a given time period. This is the device I came up with to measure the rotations:
  </p>
  <image src="/posts.assets/anemometer.jpg"/>
  <p>
  The device uses an infrared LED and photocell taken from a broken PS2 ball mouse. The output from the photocell is connected to an arduino interrupt pin.
  </p>
  <p>
  The vertical axle and cog are taken from a broken small toy helicopter. The bottom of the cog has been covered with black tape except for a single window that exposes the photocell to the IR from the LED once per rotation.
  </p>
  <p>
  Below is a close up where you can see the clear LED at the bottom, the black photocell at the top and the window in the cog.
  </p>
  <image src="/posts.assets/anemometer-closeup.jpg"/>
  <p>
  I still need to make the propeller - which will most likely be two cups on the end of short arms connected to the axle head - and to acquire a suitable housing for it that can be easily mounted.
  </p>
  <p>
  Example code can be found here : <a href="https://github.com/sodnpoo/arduino/blob/master/weatherstation/weatherstation.pde">weatherstation.pde</a>.
  </p>
</post><post>
  <tag value="arduino"/>
  <tag value="weathoscope"/>
  <title>arduino weather monitoring station 1</title>
  <date>18 Dec 2010</date>  
  <p>
  <span class="header">Temperature</span>
  </p>
  <p>
  I've started building an arduino powered weather monitoring station. The plan is to have sensors for the various different aspects (wind speed, temperature etc) so I can publish the live data and keep a log that can be used for later analysis.
  </p>
  <p>
  For temperature measurement I'm using the LM335Z which can cover a range of -40 to +100 degrees centigrade. It needs one analog pin which after some conversion gives you the temperature in Kelvin.
  </p>
  <p>
  Below you can see I'm only using two of the 335's legs - v+ and v-. V+ is pulled high on one side via a 1K resistor and on the other is connected to an arduino analog pin. V- is connected to ground.
  </p>
  <image src="/posts.assets/LM335Z.jpg"/>
  <p>
  I use the function below where raw is the raw value returned from analogRead() and fudge is how much to offset the result by after calibration. (I used ice in a bag.) The '-273' is there to convert from Kelvin to degrees centigrade.
  </p>
  <pre>
  int LM335toDegreesC(int raw, int fudge){
    return (((raw * 500L) / 1023L) - 273L) + fudge;
  }   
  </pre>
  <p>
  Example code can be found here : <a href="https://github.com/sodnpoo/arduino/blob/master/weatherstation/weatherstation.pde">weatherstation.pde</a>.
  </p>
</post></xml>
