Sparkfun Weather Station

I installed the Sparkfun Weather Meters mainly for the rain gauge.  It is quite expensive, and didn’t even come with the small screws which hold the anemometer and wind vane to the support arm.  It does seem to be well made, and makes my system look like a weather station.

Sparkfun Weather Meters in the wild

The datasheet shows that the rain gauge and the anemometer are magnetic reed switches; every 0.011″ of rain causes a momentary contact and a 2.4km/h wind will cause a momentary contact every second for the anemometer.  These inputs will be connected to Arduino interrupts.  The wind vane uses an array of resistors which can be read through the ADC of the Arduino, but the datasheet is wrong for the wind vane.  At 315°, the datasheet states that the voltage should be 4.78V, but in actuality, with a 10K resistor in series with a 64.9K resistor, the voltage drop across the vane will be 4.33V.

The following code setups up the inputs and the interrupts to read this device.  Note that setting a pin to INPUT and then writing a HIGH value to it turns on the internal 20K pull up resistor in the Arduino, which prevents the need for external pull up resistors on the interrupt driven devices.  The wind vane requires a 10K resistor in series with the vane’s resistors, and to save power, this resistor and the vane are powered from a digital output, which is driven HIGH only when the reading is to be taken.

#define ANEMOMETER_PIN 3
#define ANEMOMETER_INT 1
#define VANE_PWR 4
#define VANE_PIN A0
#define RAIN_GAUGE_PIN 2
#define RAIN_GAUGE_INT 0

void setupWeatherInts()
{
  pinMode(ANEMOMETER_PIN,INPUT);
  digitalWrite(ANEMOMETER_PIN,HIGH);  // Turn on the internal Pull Up Resistor
  pinMode(RAIN_GAUGE_PIN,INPUT);
  digitalWrite(RAIN_GAUGE_PIN,HIGH);  // Turn on the internal Pull Up Resistor
  pinMode(VANE_PWR,OUTPUT);
  digitalWrite(VANE_PWR,LOW);
  attachInterrupt(ANEMOMETER_INT,anemometerClick,FALLING);
  attachInterrupt(RAIN_GAUGE_INT,rainGageClick,FALLING);
  interrupts();
}

In order for the anemometer to be accurate, any surrounding objects must be 4 time as far as they are higher than the anemometer.  For example, if my anemometer is 5 feet off the ground, and my house is 25 feet tall, the anemometer would need to be 80 feet from the house to be able to measure the wind speed accurately.  In my case, nothing close to this leeway is possible, but I still setup the anemometer just for the educational experience.

Every rotation of the anemometer causes a call to the interrupt service routine anemometerClick().  Switch debouncing is accomplished by assuming any interrupt that occurs within 500 uS of the previous one is a bounce and should be ignored.  This limits the max speed this configuration can measure to about 2900 miles per hour, but since I don’t live on Jupiter I think I can live with this compromise.  The getUnitWind() function returns the average wind speed since the last poll, which is every 60 seconds.  The getGust function uses the shortest time between 2 interrupts to calculate the fastest wind speed since the last poll.

#define WIND_FACTOR 2.4
#define TEST_PAUSE 60000

volatile unsigned long anem_count=0;
volatile unsigned long anem_last=0;
volatile unsigned long anem_min=0xffffffff;

double getUnitWind()
{
  unsigned long reading=anem_count;
  anem_count=0;
  return (WIND_FACTOR*reading)/(TEST_PAUSE/1000);
}

double getGust()
{

  unsigned long reading=anem_min;
  anem_min=0xffffffff;
  double time=reading/1000000.0;

  return (1/(reading/1000000.0))*WIND_FACTOR;
}

void anemometerClick()
{
  long thisTime=micros()-anem_last;
  anem_last=micros();
  if(thisTime>500)
  {
    anem_count++;
    if(thisTime<anem_min)
    {
      anem_min=thisTime;
    }

  }
}

When the system included the logger shield, SRAM memory was so tight that I had to move variable data from SRAM to FLASH.  Using PROGMEM allowed me to move the vane directions and the expected values out of SRAM, and in itself saved almost 100 bytes of the 2000 the Arduino has (moving String values in addition freed up about 500 bytes of SRAM).  The pgm_read_word function pulls the values out of FLASH and into SRAM when needed, but only works with integers, so the actual wind directions are stored as 10X their value.

As mentioned in the MCP9700 post, the analogReference for the Wind Vane must be switched from the 1.1V the MCP9700 was using to the 5V default value.  Since it takes some time for the ADC to adjust to the new reference, the first 10 adc readings are just thrown out.

To save battery power, the wind vane is powered by the digital pin VANE_PWR right before it is used.  a 100ms delay is inserted after the power pin is driven high just to left things settle down.  The rest of the function compares the ADC value to the ideal values in vaneValues, and returns the corresponding wind direction.


static int vaneValues[] PROGMEM={66,84,92,127,184,244,287,406,461,600,631,702,786,827,889,946};
static int vaneDirections[] PROGMEM={1125,675,900,1575,1350,2025,1800,225,450,2475,2250,3375,0,2925,3150,2700};

double getWindVane()
{
  analogReference(DEFAULT);
  digitalWrite(VANE_PWR,HIGH);
  delay(100);
  for(int n=0;n<10;n++)
  {
    analogRead(VANE_PIN);
  }

  unsigned int reading=analogRead(VANE_PIN);
  digitalWrite(VANE_PWR,LOW);
  unsigned int lastDiff=2048;

  for (int n=0;n<16;n++)
  {
    int diff=reading-pgm_read_word(&vaneValues[n]);
    diff=abs(diff);
    if(diff==0)
       return pgm_read_word(&vaneDirections[n])/10.0;

    if(diff>lastDiff)
    {
      return pgm_read_word(&vaneDirections[n-1])/10.0;
    }

    lastDiff=diff;
 }

  return pgm_read_word(&vaneDirections[15])/10.0;

}

The rain gauge work much like the anemometer in that it drives an interrupt, and a 500us debounce time is used.  The interrupt the simply counts the number of switch contacts that occurred since the last poll and multiplies that by the number of mm of rain each switch contact represents.

#define RAIN_FACTOR 0.2794

volatile unsigned long rain_count=0;
volatile unsigned long rain_last=0;

double getUnitRain()
{

  unsigned long reading=rain_count;
  rain_count=0;
  double unit_rain=reading*RAIN_FACTOR;

  return unit_rain;
}

void rainGageClick()
{
    long thisTime=micros()-rain_last;
    rain_last=micros();
    if(thisTime>500)
    {
      rain_count++;
    }
}
Advertisements

34 thoughts on “Sparkfun Weather Station

  1. Hello,
    i am interested in your project. I am planing the wheter station and i would like to get some informations from you. Could you please send me more informations about your project.

    manny thanks
    jcerny

  2. Hi,
    i am also build an weatehr station with an arduino. But i do not find any infomations for the connection of the weather meter parts to the arduino, have you got some
    circuit diagram for me?

    • Hi,
      Thanks for your repply.
      I run an amateur weather station based on Cumulus and two Arduinos. I don’t know if what I have is what you need, but I’ll be happy to send you all the code and any additional information related to their use. I’m sure you will understant the code, it is simple and farly well commented.

      Currently my system includes an Arduino with barometric pressure sensor (BMP085), who also works as a RF receiver to capture data from wind direction and speed sensor (these are a from a cheap meteorological station that has no USB connection) . This Arduino with the same RF receiver, also receives data from other sensors (temp / hum, UV and Solar Rad) that a second Arduino sends by RF (using virtual wire library) with easily available 433.92MHz emitter.

      Please give me an e_mail address, so I can send you what I have. If it will be of any use to you, use it, modify it, as you wish

      If you wanto to see some photos from this project, visite this page: http://www.meteocercal.info/wxaurioltools.php
      The page are only in Portuguese language, sorry for that, and also for my poor English.

  3. Hi,
    I would like to use your code, to simple read the wind speed and direction from exactly the same type of sensor you are using.
    I’m a beginner with Arduino, I can understand mostly of the code, but it seems to me that something is missing on the code for reading the vane:
    Line 23: Where diff variable gets it’s value? Also is not defined anywhere…
    Line 18 : Should be: for (int n=0;n<lastDiff, n++), right?

    I'll be grateful if you could help me with the necessary corrections.

    Greetings
    ACaneira

  4. Hi, again

    I’m attempt to use your code, but I’m with some difficulties … I think I understand how the program works in general, but I do not understand some details, perhaps you can help me.
    Reading the wind direction is working well, but the readings of wind gust and average are quite high, almost twice the value I get from my weather station. The sensors are exactly the same as you are using, so I think I can use the same WIND_FACTOR

    line 20: double time=reading/1000000.0;

    Where the “time” variable is used in the program?
    Would it be your intention to use it on line 22, resulting : return (1/(time))*WIND_FACTOR;

    ———————-

    line 22: return (1/(reading/1000000.0))*WIND_FACTOR;

    From what you get the 1000000.0 value? This can be obvious, but I can’t see.

    Any help is appreciated.
    Thanks in advance

    ACaneira

  5. I have found that, if on line 22 I use a value of 500000.0 insted of 1000000.0 I get values for wind gust and average, almost equal to what I read from my actual weather station… but I like to understand the mean of this numbers. Why you use 1000000.0?
    I’ll be grateful with any help.

  6. Forget my last comment on the number 1000000.0, I had not studied the code enough. Of course it has to be this number.

    I still get very often very high values ​​for the wind gusts. However, the values ​​for the average wind speed are consistent with the values ​​I get from my weather station.
    I have rised the Switch debouncing time from 500 uS to other values, but it seems don’t have any effect on the high values I get.
    M

    How many times a minute I can call the function getGust ()? Or it has no importance and I can call it for example 10 in 10 seconds?

    I appreciate any help.

    Greetings
    AC

  7. Problem is SOLVED.
    The reed switch from this kind of anemometer makes a lot of bouncing. With a simple debouncing circuit, with a 100 nF capacitor between pin 3 and ground solves the problem. No more wind gust splikes.
    This is a great piece of software! I’m using it now. Thanks for having it published.

    AC

  8. hi Kevin
    i try this code to read the wind speed meter and i cannot compile it
    undefined reference to `loop’
    can you help me with that ?

  9. I have tried reading data from sensors with your code but I always get 0.0 values for wind speed, gust speed and rain fall, and for wind direction I always get 270.0. Do you have an idea what could be wrong?

  10. Hello, do you have some Schematic that show how did you connect the weather meters to the arduino ?? Do you have the codes in C# ?, THANKS

  11. Hi kevin! I’m trying to connect the max44009 to the arduino uno using your code yet I’m having some problems, I was wondering if you can help me out?

    Heres the code I’m trying to use:

    #include
    #include
    #include
    #define MAX_ADDR 203

    void setup()
    {
    Serial.begin(9600);
    }

    int readI2CAddr(int addr);

    int
    main(void)
    {
    int luxHigh=readI2CAddr(0x03);
    int luxLow=readI2CAddr(0x04);
    int exponent=(luxHigh&0xf0)>>4;
    int mant=(luxHigh&0x0f)<<4|luxLow;
    float x = (pow(2,exponent)*mant)*0.045;
    Serial.println("Hello World");
    Serial.println(x);
    return(0);

    }

    int readI2CAddr(int addr)
    {

    Wire.beginTransmission(MAX_ADDR);
    Wire.write(addr);
    Wire.endTransmission();

    Wire.requestFrom(MAX_ADDR,1);

    int n=0;
    for(n=0;n<25;n++)
    {
    if(Wire.available())
    break;

    delay(100);
    }

    if (n==25)
    return 0;
    else
    return Wire.read();
    }

  12. Hi There thank you very much for the Article. I am doing a similar project to yours. However, there some bits of your code that I am not understanding. If you would share the full code I will be grateful. I have done major part of my project. However I was simulating the temperature, wind speed and wind direction with readings from potentiometer but now I decided to use the real weather kit from sparkfun and I am having difficults to write a code that reads the values from these devices.

    Thank you in advance

  13. Hi
    Just wondering if this was intended to be a completer sketch? Looks like the main section is missing and is doesn’t compile when copying and pasting the sections.
    Thanks

  14. Hi Good day to you..I’m interested with your project could you please send me also the full codes and circuit diagrams of your projects. Your work could greatly help me with my projects. Thanks in Advance.

  15. Love your code – seems to be the touchstone with the Sparkfun instrument,
    It works great As long as the chip is running all the time, however when trying to put it to sleep – the timings you use all go away since the clocks are all turned off.

    If there was a only a way in code to debounce the anemometer click while sleeping.

  16. I am working on arduino weather station project I could not able find sparkfun weather station wiring diagram could you please give the wiring diagram which we be more help full

    Thanks,
    Mani

  17. I am working on arduino weather station project I could not able to find sparkfun weather station wiring diagram, could you please give the wiring diagram and the code it will be more helpful for me. my email id is maniprevo@gmail.com

    Thanks,
    Mani

  18. I’m a complete noob with both programming and arduinos trying to figure this stuff out. I stumbled across this thread, and have just ordered the same device. I was wondering if you would be able to email me the whole file(s) you built to collect data from the weather meter. Trying to comprehend how all this works logically, and it’s hard to tell seeing the bits and sections instead of the whole thing. My email is brodiemcd@austin.rr.com Thanks so much for any help you might provide.

  19. Hi- I would like very much to use some of your code in my weather station project, but it appears to me that the code is not complete. Am I missing something?

  20. Hello-I posted on Sep 21, requesting more complete code, and I haven’t seen any replies. I am learning how to program, and I guess what I need is an example of the whole program. Also, the following lines have been truncated on your website because of the width of your window. Could you please provide the missing numbers?

    static int vaneValues[]
    static int vaneDirections[]

    Any information will be appreciated!

  21. Hi,

    I am also planning to buy the “Sparkfun Weather Meters” but I am not sure if I can connect ist directly to the arduino. Can you tell me if this is possible or if I have to use any further hardware?

    Thanks in advance,
    Jo

  22. Hello, we have the same weather meters used, and our weather meter the rain gauge producing its own value even though it is not raining.. do you have some suggestion else can we ask a copy of the arduino program? thanks..

  23. Hi,
    Wondering if you can help me, am a complete noob to programing and have only very, very slight knowledge of arduino, I have built a weatherduino weatherstation which is based on work done by A Caneira, whom you have helped above. The weatherstation is up and running fine, using the basic fine offset hardware which is the same as the sparkfun hardware that you yourself have used
    I am hoping to upgrade both the anemometer and windvane, I think the anemometer is not to bad to work out as I only intend to replace the reed switches, with hall effect sensors.
    The windvane I think will be a bit more fun to sort out. I have obtained a 16 pulse per rotation optical rotary sensor which is smooth running NO detents. I have obtained a sketch with the help of some on the arduino forum but my problem is the implimenting use the of an encoder in the weatherduino software. I have approached A Caneira, but he is happy with his coding at present. so can you help ? I am pretty certain that i can work out the mods required for the pcb for the TX,
    Please would you inform me if you are willing and able to help, as it appears to me that you seem to be the best person to ask.
    Awaiting your reply.

    regards

    Martyn Topham
    aka tyntop on the weatherduino / arduino forums,

    Email : tyntopnhoj@hotmail.co.uk

    • Although you may have me confused with someone else, I will be happy to try and help you. Please send some code that you have, and a detailed account of what you are trying to do.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s