Connecting a weather station to your Arduino
Interrupts
Basically, an interrupt is a signal to a processor by either software or hardware that an event needs immediate attention. I use hardware interrupts in the SDL_Weather_80422
class.
Every time the anemometer rotates, a magnet closes a reed relay connecting one pin to another. Looking at the schematic for the WeatherArduino board, you can see that one end of the reed relay is connected to a 10kohm resistor that pulls up that end to +5V. The other end is connected to ground. When the relay closes, the output line is pulled down to ground momentarily and then goes back to +5V when the line is released.
I am connecting this line to one of the Arduino Mega interrupts (Int5). I set this interrupt to respond to a rising edge (ground going to +5V when the relay is released). Similar statements set up an interrupt to respond to the rain bucket relay closing (Listing 4). Counting these interrupts is how the Arduino determines the wind speed and how much rain has fallen.
Listing 4
Setting Interrupts
01 pinMode(pinAnem, INPUT); // pinAnem is input to which a switch is connected 02 digitalWrite(pinAnem, HIGH); // Configure internal pull-up resistor 03 pinMode(pinRain, INPUT); // pinRain is input to which a switch is connected 04 digitalWrite(pinRain, HIGH); // Configure internal pull-up resistor 05 attachInterrupt(_intAnem, serviceInterruptAnem, RISING); 06 attachInterrupt(_intRain, serviceInterruptRain, RISING);
Interrupt Service Routine
The interrupt service routine (ISR) for both interrupts are similar. Listing 5 is the ISR for the anemometer. Look through the code to see how the data is passed both directions. Getting an ISR to work properly is a little difficult in a C++ class with the Arduino, which is one reason SDL_Weather_80422
is designed to be a singleton class.
Listing 5
Anemometer ISR
01 unsigned long lastWindTime; 02 03 void serviceInterruptAnem() 04 { 05 unsigned long currentTime= (unsigned long)(micros()-lastWindTime); 06 07 lastWindTime=micros(); 08 if(currentTime>1000) // debounce 09 { 10 SDL_Weather_80422::_currentWindCount++; 11 if(currentTime<SDL_Weather_80422::_shortestWindTime) 12 { 13 SDL_Weather_80422::_shortestWindTime=currentTime; 14 } 15 } 16 }
Specifically, notice the statements in lines 5-8. The truth of the matter is that mechanical devices bounce as they close – usually on the order of a millisecond – which is why I ignore any interrupts that happen less than 1,000µsec (1msec) after a previous interrupt (line 8). In this way, I set a maximum speed at which I can take measurements with the anemometer. In this case, it's 1,492mph, so I'm not too worried about it, not living on Venus.
As a side note, my father, Folke Cigard Shovic, patented a bounceless relay in the 1950s for use in Minuteman ICBMs. As far as the Air Force could tell, it was bounceless when measured with the equipment of the day. I'd be interested in testing it with today's test equipment to see if that is still true.
Buy this article as PDF
(incl. VAT)