It was too late last night when I finished the post about building the anemometer that I didn’t want to get into the code to read the wind speed. As I said before, basically what I do is I count the number of “triggers” within a 10 second period and then feed that into the formula that came from testing it with our car.

Here is the code I use for Raspberry Pi…I run this every 5 minutes (with the rest of my measurements) to get the wind speed at that time.

# calculate windspeed
# set up the GPIO to be an input and activate the internal resistor to pull down the pin to low
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

# This is the interrupt function. It opens a file, pulls the number from the file and adds one to it, then rewrites it to the file.
def wind_callback(channel):
windfile = open("/home/pi/wind_count.txt")
windtext = windfile.readline()
windfile.close()

wind_count = int(windtext)
wind_count += 1
windfile = open("/home/pi/wind_count.txt", "w")

windfile.write(str(wind_count))
windfile.close()

# Here is the interrupt setup. We are setting it up on pin 22, looking for it to rise, calling the function "wind_callback" when it is triggered and
# debouncing it by 100ms
GPIO.add_event_detect(22, GPIO.RISING, callback=wind_callback, bouncetime=100)
# Before we start the count, we open the file and set the number to 0
windfile_clear = open("/home/pi/wind_count.txt", "w")
wind_count_clear = 0
windfile_clear.write(str(wind_count_clear))
windfile_clear.close()

# now we sleep for 10 seconds to get the readings
time.sleep(10)

# After sleeping, we open the file and read the number
wind_file = open("/home/pi/wind_count.txt")
wind_count = wind_file.readline()
wind_file.close()

# in order to use it in some math, we need to convert it to an int
wind_count_comp = int(wind_count)

# here is the formula created from testing. Basically it is .0023427x^2 + .46244x
windspeed_a = wind_count_comp * wind_count_comp * .0023427
windspeed_b = wind_count_comp * .46244
windspeed = windspeed_a + windspeed_b

# round it off to 1 decimal.
windspeed = round(windspeed, 1)

I am actually in the middle of a redesign on my weather station due to the Raspberry Pi not being the best at interrupts for the rain gauge. For the one at my father-in-laws farm, I will be using an Adafruit trinket to capture all the data from the anemometer, rain gauge, and wind direction sensor before relaying it to the Pi. This type of sensing is better for a micro controller than it is for a Linux computer such as the Pi. For my home weather station, I’ll be using a Arduino Pro Mini as I have a lot more sensors on my mast. The Trinket code is a little more difficult due to the ATTiny85 that runs it. I’ll post info on how to connect it to a Raspberry Pi later.

Here is the code for the same principal as above on a trinket. The big difference here is that this runs constantly. Every 10 seconds I have a wind speed reading, although I only pull it every 5 minutes.


#include avr/interrupt.h

// setup cbi & sbi for interrupts
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Set up variables used
volatile int windSpeed = 0; // keep track of interrupts from anemometer
volatile int windSpeedSend = 0; // used to send 10 second interrupt value to pi
long debouncing_time_wind = 100; //Debouncing Time in Milliseconds for anemometer
volatile unsigned long last_micros_wind; // micros since last anemometer interrupt
volatile int val2 = 0; // pin 4 value at interrupt

void setup()
{
// Setup Pins for interrupts
pinMode(4,INPUT);

sbi(GIMSK,PCIE); // Turn on Pin Change interrupt
sbi(PCMSK,PCINT4); // Which pins are affected by the interrupt. Turn on Pin 2

}

void loop()
{

// anemometer counts interrupts for 10 second interval. This is sent to master for calculation
windSpeed = 0;
tws_delay(10000);
windSpeedSend = windSpeed;

}

// debounce anemometer. make sure new reading is greater than old reading + debounce wind micros
void debounceWindSpeed() {
if((long)(micros() - last_micros_wind) >= debouncing_time_wind * 1000) {
windSpeedFunc();
last_micros_wind = micros();
}
}

// function to increment anemometer count
void windSpeedFunc() {
windSpeed = windSpeed + 1;
}

// interrupt service routine. What to do when an interrupt occurs as all pin change interrupts
// on ATTiny85 trigger PCINT0 vector.
ISR(PCINT0_vect) {
// get value of pin 4 @ interrupt
val2 = digitalRead(4);

// if pin 4 is HIGH (caused the interrupt), proceed with wind speed (anemomether) increment function
if (val2 == HIGH) {
debounceWindSpeed();
}

}