Weather Station Data Collection
Using The
Raspberry Pi
d. bodnar revised 8-29-13
Overview I have had a weather station at home for a number of years. The most sophisticated unit is an older system from RainWise, the WS-1000
It includes a rain gauge, anemometer, wind vane and temperature, humidity and barometric pressure sensors. The data is stored and can be displayed by the console shown above. While this system was state-of-the-art in its day it is quite old and I decided to do some upgrades so that I had a bit more control over its operation and had a better chance of maintaining it. With this in mind I retired the console unit and began disassembling the rain gauge, anemometer & wind vane unit so that I could install my own PIC based electronics. I also chose a humidity sensor, 1 wire temperature sensor and barometric pressure sensor all of which connect directly to the Raspberry Pi. What follows is a compilation of my notes on the conversion of the WS-1000, connecting sensors to the Pi and the custom hardware and software that connects it all together. It is not intended to be a tutorial but notes that will help me to maintain and upgrade the system in the future. The results of some of the experiments discussed here can be see on this web page http://www.trainelectronics.com/RaspberryPi/Graph_Temperature/Graph.htm It includes graphs from various sensors attached to the Pi.
|
Raspberry Pi Setup Start with the newer Raspberry Pi, Model B (It has more internal memory) and download and install the operating system onto an 8 gig SD card - http://www.raspberrypi.org/downloads - I used 2013-07-26-wheezy-raspbian.zip Once installed do the following:
|
Hardware Connections The following pins on the Pi's 26 pin i/o header will be used:
|
Serial Connection The serial connection between the PIC (that receives & interprets wind speed, wind direction and rainfall) must have its level adjusted to exchange information with the 3.3 volt Pi. This is done with the MAX3232 - this page has more details about how this is done. http://www.trainelectronics.com/RaspberryPi/#Connecting_to_the_built-in_RS-232_Port_with_a_MAX3232 These photos show how I did the wiring. This device is the MAX3232 converter, top view of the wiring, which is done on the back. The RS-232 on the PIC connects on the left and the Pi on the right. This plug goes into the IO header on the Pi - pins 1 and 2 are on the right. This is a top view of the plug - pins 1 and 2 are on the right. Here are the DB9 connections using pins 2 (orange), 3 (yellow) and 5 (green).
Serial Port Testing
import time import serial s = serial.Serial("/dev/ttyAMA0", 9600, timeout=0.9) for i in range (1,600000): print "at top", i data = s.readline() #reads up to 1024 characters, or until \r\n or until timeout (if set) if (data.startswith('D')): print "found D" print data # time.sleep(1) 'WX Date to Pi test d. bodnar 8-9-13 Include "modedefs.bas" ansel = 0 cmcon0 = 7 Serial_out var gpio.0 'pin 7 ' TIP101 var gpio.2 'pin 5 hpwm 1 SerToPi var gpio.5 'pin 2 Temp var word Serout serial_out,n9600,[13,10,"d. bodnar Ver 1.0 Send serial to Raspberry Pi",13,10] Serout serial_out,n9600,[13,10,"Careful with oscillator and baud rate!",13,10] Serout serial_out,n9600,[13,10,"08-03-13",13,10] Serout serial_out,n9600,[13,10,"MUST disable serial login on Pi! See:",13,10] Serout serial_out,n9600,[13,10," http://www.hobbytronics.co.uk/raspberry-pi-serial-port",13,10] gpio = %00000000 'all outputs Temp=0 Testing: high tip101 'flash LED during send serout Sertopi,n9600,["D=330 S=00000 R=002 ",#temp ,18,14] low tip101 pause 1000 Temp = temp + 1 goto testing |
Humidity / Temperature Sensor The DHT11 is an inexpensive humidity sensor. It also measures temperature. Since it's temperature sensing may not be as accurate as it could be I chose to use a 1 wire temperature sensor as well (see next section) More detailed information on using the DHT11 is here: http://www.trainelectronics.com/RaspberryPi/Graph_Humidity/ Connect the sensor to the interface board
The red wire goes to the 3.3 volt positive connection on the DHT11, the white wire goes to the data line and the black wire to ground. Note that the 3rd pin is not connected. In this view you can see the 10K resistor that goes between the data line and +3.3 volts. Here the connections to the i/o plug can be seen. The data line (white) goes to pin 11, GPIO 17. Power and ground go to + 3.3 volts and ground. Software for DHT11 git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git The command that I use to read the sensor is below - note that the "11" before the "17" that identifies the port is the type of device. sudo Adafruit-Raspberry-Pi-Python-Code/Adafruit_DHT_Driver/Adafruit_DHT 11 17 This same command can be used from within a Python program. |
DS18B20 1 Wire Temperature Sensor The humidity sensor and the barometric pressure sensor each give a temperature reading in addition to their primary function. The humidity sensor will go outside (in a proper, shaded enclosure) so it could be used for temperature readings. Its readings compare favorably with those from other sensors but I like to have the option of using the DS18B20 as well. This link has detailed information on using these sensors: http://www.trainelectronics.com/RaspberryPi/Graph_Temperature/index.html The short version is as follows:
|
Barometric Pressure Sensor To measure atmospheric pressure I use a BMP085 sensor. This web site has details on its use with the Pi: These are the basic steps that you need to follow to use this sensor:
|
Software Objectives The Raspberry Pi software will be configured to do the following:
|
Code Being Used as of
8-28-2013 Barometric Pressure: Note the two conversions - one corrects for my altitude and the other converts to inches of mercury #!/usr/bin/python from Adafruit_BMP085 import BMP085 # =========================================================================== # Example Code # =========================================================================== # Initialise the BMP085 and use STANDARD mode (default value) # bmp = BMP085(0x77, debug=True) bmp = BMP085(0x77) # To specify a different operating mode, uncomment one of the following: # bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode # bmp = BMP085(0x77, 1) # STANDARD Mode # bmp = BMP085(0x77, 2) # HIRES Mode # bmp = BMP085(0x77, 3) # ULTRAHIRES Mode while True: temp = bmp.readTemperature() pressure = bmp.readPressure() altitude = bmp.readAltitude() fahrenheit = temp * 9 / 5 + 32 print "Temperature: %.2f C" % temp, print fahrenheit print "Pressure: %.2f hPa" % (pressure / 100.0) feet = int (altitude * 39.37 / 12) print "Altitude: %.2f" % altitude , print feet temp = 9.0 / 5.0 * temp + 32 #convert to fahrenheit import time import datetime now=datetime.datetime.now() global timestring timestring = now.strftime("%m-%d-%Y %H:%M:%S") pressure = pressure * 1.0465959046 #correct barometric pressure for my altitude pressure = pressure / 33.8638866667 #convert to in Hg print pressure / 100 timestring = timestring + " "+ str(temp) + " " + str(pressure / 100.0) + " " + str(altitude) fo=open("barometer_out3.txt","a+") fo.write(timestring) fo.write ("\n") fo.close() import os os.system("gnuplot barometer.plt") print "graph 1 generated" os.system("curl -u u35664817:pwpwpwpw ftp://davebodnar.com/public_html/DGB/pond/temperature/ -T barometer.gif") os.system("curl -u u35664817:pwpwpwpw ftp://davebodnar.com/public_html/DGB/pond/temperature/ -T barometer_out3.txt") time.sleep(60) GNUPLOT Script for Pressure Graph: set terminal gif small size 640, 480 transparent# x000000 set output "barometer.gif" set time set xtics rotate set xdata time set timefmt "%m-%d-%Y %H:%M" set y2tics set grid set title "Barometric Pressure - revised 08-28-13" set ylabel " pressure " set xlabel "\n5 Minute Observations" set key below plot 'barometer_out3.txt' using 1:4 title "Pressure in HG" with lines set output Python Code Wind Speed /
Direction / Rainfall: import time import serial s = serial.Serial("/dev/ttyAMA0", 9600, timeout=0.9) for i in range (1,600000): s.flushInput() data = s.readline() #reads up to 1024 characters, or until \r\n or until timeout (if set) if (data.startswith('D=')): print data, data = data.replace("="," ") print data time.sleep(60) import datetime now=datetime.datetime.now() global timestring timestring = now.strftime("%m-%d-%Y %H:%M:%S") timestring = timestring + " "+ data fo=open("windrainout.txt","a+") fo.write(timestring) fo.close() import os os.system("gnuplot windrain.plt") os.system("gnuplot winddir.plt") os.system("gnuplot rain.plt") print "graphs 1 & 2 generated" os.system("curl -u u35664817:pwpwpwpw ftp://davebodnar.com/public_html/DGB/pond/temperature/ -T windrain.gif") os.system("curl -u u35664817:pwpwpwpw ftp://davebodnar.com/public_html/DGB/pond/temperature/ -T winddir.gif") os.system("curl -u u35664817:pwpwpwpw ftp://davebodnar.com/public_html/DGB/pond/temperature/ -T windrainout.txt") os.system("curl -u u35664817:pwpwpwpw ftp://davebodnar.com/public_html/DGB/pond/temperature/ -T rain.gif") print "file transferred" Graphs are created from these GNUPLOT scripts: FOR WIND SPEED: set terminal gif small size 640, 480 transparent# x000000 set output "windrain.gif" set time set xtics rotate set xdata time set timefmt "%m-%d-%Y %H:%M" set y2tics set grid set title "Wind Speed - revised 08-28-13" set ylabel "Speed" set xlabel "\n5 Minute Observations" set key below plot 'windrainout.txt' using 1:6 title "Speed" with lines set output FOR WIND DIRECTION: # this one works 8-25-13 set terminal gif small size 640, 480 transparent set output "winddir.gif" set time set xtics rotate set xdata time set timefmt "%m-%d-%Y %H:%M" set y2tics set grid set title "Wind Direction Only - revised 08-22-13 Test on PC - works! needs 2 days data " set ylabel "Direction" set xlabel "\n5 Minute Observations" set key below plot 'windrainout.txt' using 1:4 title "Direction" with lines set output FOR RAINFALL: set terminal gif small size 640, 480 transparent# x000000 set output "rain.gif" set time set xtics rotate set xdata time set timefmt "%m-%d-%Y %H:%M" set y2tics set grid set title "Rainfall - revised 08-28-13" set ylabel " rain" set xlabel "\n5 Minute Observations" set key below plot 'windrainout.txt' using 1:10 title "Rain" with lines set output Humidity: |
Modification of the RainWise WS-1000 Rainfall, Wind Direction and Wind Speed Sensors |
This photo shows the RainWise unit that goes on the roof.
The part circled in blue is the rain gauge, the part circled in red
is the anemometer and the part in the yellow circle is the wind
vane. This photo shows the wind vane's inner workings. There are 9 evenly spaced reed switches on the circuit board, each 40 degrees apart (360 degrees / 9 = 40 degrees). There are two magnets on the moving part of the wind vane (see next photo) that are positioned so that one or two of the reed switches are activated depending on where the wind vane is located. This arrangement gives 36 different readings, each representing 10 degrees of rotation. Each of the reed switches has been connected to the PIC processor by the rainbow cable shown here. This allows the processor to know where the wind vane is pointed. Its software (below) converts the 9 bit binary number from the 9 reed switches into a number from 1 to 36 (representing 10 to 360 degrees) |
The schematic shows the 16F684 that takes
care of watching the wind vane and the anemometer. The 12f683
has one job, watching the rain gauge. Since the signal from
the rain gauge can come at any time and can be missed by the busy
16F684 the smaller chip is dedicated to that task. The 12F683
toggles a pin each time the bucket trips - since these events can
only come every few seconds, even in a driving rain storm, the
16F684 should never miss recording a 1/100" increment in rainfall. The 16F684 sends data on its readings via a serial line that goes to the receiving unit in the house. |
PIC Code for the Wind Vane:
'New
Function - Weather Station Wind Vane Reader 7-23-2013 DEFINE DEBUG_REG PORTA DEFINE PULSIN_ MAX 1000'0 'ansel=0 'allows you to use pins as
digital rather than analog D1 var portc.3 'pin 7 option_reg.7=0 'turn on wpu trisc = %11111111 PULSIN Anemometer,0,anemPulse debug "R=" goto test:
|
PIC Code for the LCD Display: Note: this processor and the display are in the home and receive data from the 16F684 on the sensor unit via a serial data stream. 'd. bodnar 7-27-13 - Read & display
weather station data SerialIn var porta.5 'pin 2 on chip trisc=0:cmcon0=7:ansel=0 'for 14 pin
chip top: startit: serin2 serialin, 27889, [wait
("D="),dec3 Direction, skip 3, dec5 Speed,skip 3, dec3 rain]
______________________________________________________________________________
|
This is a close-up of the wind vane board.
This is the back of the board before modification.
The two magnets that trigger one or two reed switches on the wind vane board are circled. This divided bucket toggles from one side..... ... to the other each time 1/100" of rain is collected. A small magnet (circled in yellow) goes past a small reed switch (circled in red) each time the bucket moves from one side to the other. Here the anemometer has been opened. The device that is circled is an infrared photo sensor that detects the movement of the rotating drum. The two circled slots in the anemometer's drum are sensed as it rotates. The pulses that are generated are timed and turned into wind speed.
|