Hooking Up The Davis Anemometer (Part 5)
Once we have confirmed all the other sensors are working okay we now hookup the last sensor which is the Davis anemometer. This device has two sensors. The wind direction is measured using a potentiometer that changes it’s resistance depending on the direction. We connect this to an analog input on the Arduino.
The wind speed is detected by the cups opening and closing a reed switch. A small magnet on the wind cups passes this reed switch once per revolution. The output of this reed switch is connected to a digital input on the Arduino. The number of revolutions is counted for a time period which is then converted to wind speed. The time duration we use is 2.5 seconds.
For more details on the Davis Anemometer we did a 3 part hookup guide
Part 1) Hookup And Wind Direction Calibration
Part 2) How To Measure Wind Speed
Part 3) Software To Determine Wind Speed And Direction
Code
To get the wind speed we need to count the number of revolutions over a certain time period. We then apply a formula to calculate the wind speed in miles per hour. We have used the time period of 2.5 seconds which is the same as the one Davis use in their technical document.
We are going to use a timer interrupt which triggers every 0.5 seconds. We use the timerCount variable to count up to 2.5 seconds. We calculate the wind speed in the interrupt handler routine as it time critical. You need to be careful around timing critical calculations in the main loop and when you are using commands such as Serial.print(). If you have multiple Serial.print() calls it can mess up your timing accuracy.
In the isr_timer() function we also set the isSampleRequired flag to true when 2.5 seconds has elapsed. In the main loop we check if this flag is true and if so we output all the sensor data to the console.
The second isr (isr_rotation) is used to count the number of revolutions of the wind cups. This sensor is connected to pin 2 on the Arduino board. We attached an interrupt handler (line 124) to this digital pin that is triggered when the reed switch pulses the digital input to ground and back to 5V.
The third interrupt handler (isr_rg) is used for when rain is detected by the Hydreon rain sensor. The sensor open and closes when 0.01mm of rain has been detected. We have configured the sensor for tipping bucket mode and bucket size of 0.01mm.
We have removed the 2 second delay that we used previously to display the data to the console. We do not want to use the delay function as it blocks the operation of any code while the delay is being executed. The advantage of using the timer interrupt is that it allows us to schedule events in code without blocking any other code from executing.
All new code has been highlighted.
Library
We have to include the TimerOne.h and math.h libraries.
Software Sketch
Basic Weather Station Rain Sensor Sketch(Download)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #include “TimerOne.h” #include <math.h> #include “cactus_io_DS18B20.h” #include “cactus_io_BME280_I2C.h” #define Bucket_Size 0.01 // bucket size to trigger tip count #define RG11_Pin 3 // digital pin RG11 connected to #define TX_Pin 8 // used to indicate web data tx #define DS18B20_Pin 9 // DS18B20 Signal pin on digital 9 #define WindSensor_Pin (2) // digital pin for wind speed sensor #define WindVane_Pin (A2) // analog pin for wind direction sensor #define VaneOffset 0 // define the offset for caclulating wind direction volatile unsigned long tipCount; // rain bucket tip counter used in interrupt routine volatile unsigned long contactTime; // timer to manage any rain contact bounce in interrupt routine volatile bool isSampleRequired; // this is set every 2.5sec to generate wind speed volatile unsigned int timerCount; // used to count ticks for 2.5sec timer count volatile unsigned long rotations; // cup rotation counter for wind speed calcs volatile unsigned long contactBounceTime; // timer to avoid contact bounce in wind speed sensor volatile float windSpeed; volatile float totalRainfall; // total amount of rainfall detected bool txState; // current led state for tx rx led int vaneValue; // raw analog value from wind vane int vaneDirection; // translated 0 – 360 wind direction int calDirection; // calibrated direction after offset applied int lastDirValue; // last recorded direction value // Create DS18B20, BME280 object DS18B20 ds(DS18B20_Pin); // on digital pin 9 BME280_I2C bme; // I2C using address 0x77 void setup() { txState = HIGH; // setup rain sensor values tipCount = 0; totalRainfall = 0; // setup anemometer values lastDirValue = 0; rotations = 0; isSampleRequired = false; // setup timer values timerCount = 0; ds.readSensor(); Serial.begin(9600); Serial.println(“cactus.io | Weather Station DS18B20, BME280, RG11, Davis Sensor Test”); Serial.println(“DS Temp\t\tBME Temp\tHumdity\t\tPressure\tRainfall\tSpeed\tDirection”); if (!bme.begin()) { Serial.println(“Could not find BME280 sensor, check wiring!”); while (1); } pinMode(TX_Pin, OUTPUT); pinMode(RG11_Pin, INPUT); pinMode(WindSensor_Pin, INPUT); attachInterrupt(digitalPinToInterrupt(RG11_Pin), isr_rg, FALLING); attachInterrupt(digitalPinToInterrupt(WindSensor_Pin), isr_rotation, FALLING); // setup the timer for 0.5 second Timer1.initialize(500000); Timer1.attachInterrupt(isr_timer); sei();// Enable Interrupts } void loop() { ds.readSensor(); bme.readSensor(); if(isSampleRequired) { getWindDirection(); Serial.print(ds.getTemperature_C()); Serial.print(” *C\t”); Serial.print(bme.getTemperature_C()); Serial.print(” *C\t”); Serial.print(bme.getHumidity()); Serial.print(” %\t\t”); Serial.print(bme.getPressure_MB()); Serial.print(” mb\t”); Serial.print(totalRainfall); Serial.print(” mm\t\t”); Serial.print(windSpeed); Serial.print(” mph\t”); Serial.print(calDirection); Serial.println(“*”); isSampleRequired = false; } } // Interrupt handler routine for timer interrupt void isr_timer() { timerCount++; if(timerCount == 5) { // convert to mp/h using the formula V=P(2.25/T) // V = P(2.25/2.5) = P * 0.9 windSpeed = rotations * 0.9; rotations = 0; txState = !txState; // toggle the led state digitalWrite(TX_Pin,txState); isSampleRequired = true; timerCount = 0; } } // Interrupt handler routine to increment the rotation count for wind speed void isr_rotation() { if((millis() – contactBounceTime) > 15 ) { // debounce the switch contact rotations++; contactBounceTime = millis(); } } // Interrupt handler routine that is triggered when the rg-11 detects rain void isr_rg() { if((millis() – contactTime) > 15 ) { // debounce of sensor signal tipCount++; totalRainfall = tipCount * Bucket_Size; contactTime = millis(); } } // Get Wind Direction void getWindDirection() { vaneValue = analogRead(WindVane_Pin); vaneDirection = map(vaneValue, 0, 1023, 0, 359); calDirection = vaneDirection + VaneOffset; if(calDirection > 360) calDirection = calDirection – 360; if(calDirection > 360) calDirection = calDirection – 360; } |
Sketch Console Output
The sketch displays data from all of the sensors we have connected so far.