Weather board not reporting wind

Hi there, just got my first Photon to use with the weather sensor hat - I have the initial weather station example running, however it doesn’t include the capacity to pull data from the wind direction sensors. I’ve looked around and can’t find any examples that just add in that wind direction data, has anyone else found it?

Thanks!

What weather sensor hat, what sensors, what code?

Sorry, I’m making assumptions here:

it’s the sparkfun photon weather shield - https://www.sparkfun.com/products/13956

And the example code that comes with the community library (https://github.com/sparkfun/SparkFun_Photon_Weather_Shield_Particle_Library/tree/master/firmware/examples) is -

        /******************************************************************************
      SparkFun Photon Weather Shield basic example
      Joel Bartlett @ SparkFun Electronics
      Original Creation Date: May 18, 2015
      Updated August 21, 2015
      This sketch prints the temperature, humidity, and barometric pressure OR
      altitude to the Serial port.

      The library used in this example can be found here:
      https://github.com/sparkfun/SparkFun_Photon_Weather_Shield_Particle_Library

      Hardware Connections:
    	This sketch was written specifically for the Photon Weather Shield,
    	which connects the HTU21D and MPL3115A2 to the I2C bus by default.
      If you have an HTU21D and/or an MPL3115A2 breakout,	use the following
      hardware setup:
          HTU21D ------------- Photon
          (-) ------------------- GND
          (+) ------------------- 3.3V (VCC)
           CL ------------------- D1/SCL
           DA ------------------- D0/SDA

        MPL3115A2 ------------- Photon
          GND ------------------- GND
          VCC ------------------- 3.3V (VCC)
          SCL ------------------ D1/SCL
          SDA ------------------ D0/SDA

      Development environment specifics:
      	IDE: Particle Dev
      	Hardware Platform: Particle Photon
                           Particle Core

      This code is beerware; if you see me (or any other SparkFun
      employee) at the local, and you've found our code helpful,
      please buy us a round!
      Distributed as-is; no warranty is given.
    *******************************************************************************/
    #include "SparkFun_Photon_Weather_Shield_Library/SparkFun_Photon_Weather_Shield_Library.h"

    float humidity = 0;
    float tempf = 0;
    float pascals = 0;
    float baroTemp = 0;

    long lastPrint = 0;

    //Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barometric sensor
    Weather sensor;

    //---------------------------------------------------------------
    void setup()
    {
        Serial.begin(9600);   // open serial over USB at 9600 baud

        // Make sure your Serial Terminal app is closed before powering your device
        // Now open your Serial Terminal, and hit any key to continue!
        Serial.println("Press any key to begin");
        //This line pauses the Serial port until a key is pressed
        while(!Serial.available()) Spark.process();

        //Initialize the I2C sensors and ping them
        sensor.begin();

        /*You can only receive accurate barometric readings or accurate altitude
        readings at a given time, not both at the same time. The following two lines
        tell the sensor what mode to use. You could easily write a function that
        takes a reading in one made and then switches to the other mode to grab that
        reading, resulting in data that contains both accurate altitude and barometric
        readings. For this example, we will only be using the barometer mode. Be sure
        to only uncomment one line at a time. */
        sensor.setModeBarometer();//Set to Barometer Mode
        //sensor.setModeAltimeter();//Set to altimeter Mode

        //These are additional MPL3115A2 functions that MUST be called for the sensor to work.
        sensor.setOversampleRate(7); // Set Oversample rate
        //Call with a rate from 0 to 7. See page 33 for table of ratios.
        //Sets the over sample rate. Datasheet calls for 128 but you can set it
        //from 1 to 128 samples. The higher the oversample rate the greater
        //the time between data samples.


        sensor.enableEventFlags(); //Necessary register calls to enble temp, baro and alt

    }
    //---------------------------------------------------------------
    void loop()
    {
          //Get readings from all sensors
          getWeather();

          // This math looks at the current time vs the last time a publish happened
          if(millis() - lastPrint > 5000) //Publishes every 5000 milliseconds, or 5 seconds
          {
            // Record when you published
            lastPrint = millis();

            // Use the printInfo() function to print data out to Serial
            printInfo();
          }
    }
    //---------------------------------------------------------------
    void getWeather()
    {
      // Measure Relative Humidity from the HTU21D or Si7021
      humidity = sensor.getRH();

      // Measure Temperature from the HTU21D or Si7021
      tempf = sensor.getTempF();
      // Temperature is measured every time RH is requested.
      // It is faster, therefore, to read it from previous RH
      // measurement with getTemp() instead with readTemp()

      //Measure the Barometer temperature in F from the MPL3115A2
      baroTemp = sensor.readBaroTempF();

      //Measure Pressure from the MPL3115A2
      pascals = sensor.readPressure();

      //If in altitude mode, you can get a reading in feet with this line:
      //float altf = sensor.readAltitudeFt();
    }
    //---------------------------------------------------------------
    void printInfo()
    {
    //This function prints the weather data out to the default Serial Port

      Serial.print("Temp:");
      Serial.print(tempf);
      Serial.print("F, ");

      Serial.print("Humidity:");
      Serial.print(humidity);
      Serial.print("%, ");

      Serial.print("Baro_Temp:");
      Serial.print(baroTemp);
      Serial.print("F, ");

      Serial.print("Pressure:");
      Serial.print(pascals/100);
      Serial.print("hPa, ");
      Serial.print((pascals/100) * 0.0295300);
      Serial.println("in.Hg");
      //The MPL3115A2 outputs the pressure in Pascals. However, most weather stations
      //report pressure in hectopascals or millibars. Divide by 100 to get a reading
      //more closely resembling what online weather reports may say in hPa or mb.
      //Another common unit for pressure is Inches of Mercury (in.Hg). To convert
      //from mb to in.Hg, use the following formula. P(inHg) = 0.0295300 * P(mb)
      //More info on conversion can be found here:
      //www.srh.noaa.gov/images/epz/wxcalc/pressureConversion.pdf

      //If in altitude mode, print with these lines
      //Serial.print("Altitude:");
      //Serial.print(altf);
      //Serial.println("ft.");

    }

Currently it is printing to serial from the humidity, temp, and pressure sensors, as shown in this code. However, it doesn’t offer an example of syntax for pulling data from the board’s optional wind and rain sensors, which is what I’m stuck on!

Thanks.

An easier question might be - how do I get this to write its output to serial instead of posting to the web?

//Analog Weather Station credit Grady Hillhouse 2015

int pTemperature    = WKP;
int pWindBearing    = D1;
int pPressure       = D3;
int pPrecipProb     = A5;
int pWindSpeed      = D0;
int pAlert          = A4;

int refresh;  //Refresh time in seconds. Min is about 86 seconds (1000 API calls per day are allowed by forecast.io).
double lastRefresh      = 0;    //Unix time of last refresh
double lastGotWeather   = 0;    //Unix time of last time the webhook data was returned

float temperature;
float windBearing;
float pressure;
float precipProbability;
float windSpeed;
float ifAlert;

int mTemperature;
int mwindBearing;
int mPressure;
int mPrecipProb;
int mWindSpeed;
int mAlert;

void setup() {
    Particle.subscribe("hook-response/forecastio_webhook", gotWeatherData, MY_DEVICES);

    pinMode(pTemperature,   OUTPUT);
    pinMode(pWindBearing,   OUTPUT);
    pinMode(pPressure,      OUTPUT);
    pinMode(pPrecipProb,    OUTPUT);
    pinMode(pWindSpeed,     OUTPUT);
    pinMode(pAlert,         OUTPUT);

    Time.zone(-5); //Set time zone as eastern - note that this won't adjust for daylight savings.

    Particle.publish("forecastio_webhook");
    lastRefresh = Time.now();
}

void loop() {

    refresh = 90; //1.5 Minutes (960 total hooks per day)


    if ((Time.now() - lastGotWeather) > 900) { //Display an error code if webhook data has not been received within the past 15 minutes
        digitalWrite(pAlert, HIGH);
    }
    else if ((Time.now() - lastRefresh) > refresh) {
        Particle.publish("forecastio_webhook");
        lastRefresh = Time.now();
    }

    delay(1000);
}

void gotWeatherData(const char *name, const char *data) {

    String str = String(data);
    char strBuffer[125] = "";
    str.toCharArray(strBuffer, 125);
    lastGotWeather = Time.now();

    temperature         = atof(strtok(strBuffer, "~"));
    windBearing         = atof(strtok(NULL, "~"));
    pressure            = atof(strtok(NULL, "~"));
    precipProbability   = atof(strtok(NULL, "~"));
    windSpeed           = atof(strtok(NULL, "~"));
    ifAlert             = atof(strtok(NULL, "~"));

    mTemperature        = (int) constrain( (255.0) * (temperature       - 0.0)      / (100.0    - 0.0),     0, 255 );
    mwindBearing        = (int) constrain( (255.0) * (windBearing       - 0.0)      / (359.0    - 0.0),     0, 255 );
    mPressure           = (int) constrain( (255.0) * (pressure          - 982.0)    / (1043.0   - 982.0),   0, 255 );
    mPrecipProb         = (int) constrain( (255.0) * (precipProbability - 0.0)      / (1.0      - 0.0),     0, 255 );
    mWindSpeed          = (int) constrain( (255.0) * (windSpeed         - 0.0)      / (30.0     - 0.0),     0, 255 );

    analogWrite(pTemperature,   mTemperature);
    analogWrite(pWindBearing,   mwindBearing);
    analogWrite(pPressure,      mPressure   );
    analogWrite(pPrecipProb,    mPrecipProb );
    analogWrite(pWindSpeed,     mWindSpeed  );

    if (ifAlert > 0.0) {
        digitalWrite(pAlert, HIGH);
    }
    else {
        digitalWrite(pAlert, LOW);
    }
}

Have a look at how they did it in the example code you posted, and see if you can ‘copy’ that :wink:

Ha, I appreciate your heavy hint! I had already worked out it was a case of cludging those two scripts together, but my VERY rudimentary coding knowledge is holding me back massively - I can’t see where to call the printInfo func from in order for it to report as often as it does in the first script.

Gotten closer, really hit a wall now though - managed to convert another weathervane script from the forum into something that sends out via Serial, however the only output to serial I get it 0.000.000.000.000. over and over again. Any clues?

// This #include statement was automatically added by the Particle IDE.
#include <SparkFun_Photon_Weather_Shield_Library.h>

// This #include statement was automatically added by the Particle IDE.
// #include "ThingSpeak/ThingSpeak.h"

// This #include statement was automatically added by the Particle IDE.
#include "SparkFun_Photon_Weather_Shield_Library/SparkFun_Photon_Weather_Shield_Library.h"

// Add math to get sine and cosine for wind vane
#include "math.h"

/*
  *****************************************************************************************
  **** Visit https://www.thingspeak.com to sign up for a free account and create
  **** a channel.  The video tutorial http://community.thingspeak.com/tutorials/thingspeak-channels/
  **** has more information. You need to change this to your channel, and your write API key
  **** IF YOU SHARE YOUR CODE WITH OTHERS, MAKE SURE YOU REMOVE YOUR WRITE API KEY!!
  **** To learn more about ThingSpeak, see the introductory video: http://www.mathworks.com/videos/introduction-to-thingspeak-107749.html
  *****************************************************************************************/
//unsigned long thingspeakChannelNumber = <enter your channel number>;
//char thingSpeakWriteAPIKey[] = "<enter your write key";

// Each time we loop through the main loop, we check to see if it's time to capture the sensor readings
unsigned int sensorCapturePeriod = 100;
unsigned int timeNextSensorReading;

// Each time we loop through the main loop, we check to see if it's time to publish the data we've collected
unsigned int publishPeriod = 60000;
unsigned int timeNextPublish;

void setup() {
    // initializeThingSpeak();
    initializeTempHumidityAndPressure();
    initializeRainGauge();
    initializeAnemometer();
    initializeWindVane();

    // Schedule the next sensor reading and publish events
    timeNextSensorReading = millis() + sensorCapturePeriod;
    timeNextPublish = millis() + publishPeriod;


      Serial.begin(9600);   // open serial over USB at 9600 baud


        
}

void loop() {

    // Capture any sensors that need to be polled (temp, humidity, pressure, wind vane)
    // The rain and wind speed sensors use interrupts, and so data is collected "in the background"
    if(timeNextSensorReading <= millis()) {
        captureTempHumidityPressure();
        captureWindVane();

        // Schedule the next sensor reading
        timeNextSensorReading = millis() + sensorCapturePeriod;
    }

    // Publish the data collected to Particle and to ThingSpeak
    if(timeNextPublish <= millis()) {

        // Get the data to be published
        float tempF = getAndResetTempF();
        float humidityRH = getAndResetHumidityRH();
        float pressureKPa = getAndResetPressurePascals() / 1000.0;
        float rainInches = getAndResetRainInches();
        float gustMPH;
        float windMPH = getAndResetAnemometerMPH(&gustMPH);
        float windDegrees = getAndResetWindVaneDegrees();

        Serial.print(tempF);
        Serial.print(humidityRH);
        Serial.print(pressureKPa);
        Serial.print(rainInches);
        Serial.print(windMPH);
        Serial.print(gustMPH);
        Serial.print(windDegrees);

        // Publish the data
        //publishToParticle(tempF,humidityRH,pressureKPa,rainInches,windMPH,gustMPH,windDegrees);
        // publishToThingSpeak(tempF,humidityRH,pressureKPa,rainInches,windMPH,gustMPH,windDegrees);

        // Schedule the next publish event
        //timeNextPublish = millis() + publishPeriod;
    }

    delay(10);
}

//void publishToParticle(float tempF,float humidityRH,float pressureKPa,float rainInches,float windMPH,float gustMPH,float windDegrees) {
  //  Particle.publish("weather",
    //                    String::format("%0.1f�F, %0.0f%%, %0.2f kPa, %0.2f in, Avg:%0.0fmph, Gust:%0.0fmph, Dir:%0.0f�.",
      //                      tempF,humidityRH,pressureKPa,rainInches,windMPH,gustMPH,windDegrees),
        //                60 , PRIVATE);
//}

//===========================================================
// ThingSpeak
//===========================================================

//===========================================================
// Temp, Humidity and Pressure
//===========================================================
// The temperature, humidity, and pressure sensors are on board
// the weather station board, and use I2C to communicate.  The sensors are read
// frequently by the main loop, and the results are averaged over the publish cycle

//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barometric sensor
Weather sensor;

void initializeTempHumidityAndPressure() {
    //Initialize the I2C sensors and ping them
    sensor.begin();
    //Set to Barometer Mode
    sensor.setModeBarometer();
    // Set Oversample rate
    sensor.setOversampleRate(7);
    //Necessary register calls to enble temp, baro and alt
    sensor.enableEventFlags();

    return;
}

float humidityRHTotal = 0.0;
unsigned int humidityRHReadingCount = 0;
float tempFTotal = 0.0;
unsigned int tempFReadingCount = 0;
float pressurePascalsTotal = 0.0;
unsigned int pressurePascalsReadingCount = 0;

void captureTempHumidityPressure() {
  // Read the humidity and pressure sensors, and update the running average
  // The running (mean) average is maintained by keeping a running sum of the observations,
  // and a count of the number of observations

  // Measure Relative Humidity from the HTU21D or Si7021
  float humidityRH = sensor.getRH();

  //If the result is reasonable, add it to the running mean
  if(humidityRH > 0 && humidityRH < 105) // It's theoretically possible to get supersaturation humidity levels over 100%
  {
      // Add the observation to the running sum, and increment the number of observations
      humidityRHTotal += humidityRH;
      humidityRHReadingCount++;
  }

  // Measure Temperature from the HTU21D or Si7021
  // Temperature is measured every time RH is requested.
  // It is faster, therefore, to read it from previous RH
  // measurement with getTemp() instead with readTemp()
  float tempF = sensor.getTempF();

  //If the result is reasonable, add it to the running mean
  if(tempF > -50 && tempF < 150)
  {
      // Add the observation to the running sum, and increment the number of observations
      tempFTotal += tempF;
      tempFReadingCount++;
  }

  //Measure Pressure from the MPL3115A2
  float pressurePascals = sensor.readPressure();

  //If the result is reasonable, add it to the running mean
  // What's reasonable? http://findanswers.noaa.gov/noaa.answers/consumer/kbdetail.asp?kbid=544
  if(pressurePascals > 80000 && pressurePascals < 110000)
  {
      // Add the observation to the running sum, and increment the number of observations
      pressurePascalsTotal += pressurePascals;
      pressurePascalsReadingCount++;
  }

  return;
}

float getAndResetTempF()
{
    if(tempFReadingCount == 0) {
        return 0;
    }
    float result = tempFTotal/float(tempFReadingCount);
    tempFTotal = 0.0;
    tempFReadingCount = 0;
    return result;
}

float getAndResetHumidityRH()
{
    if(humidityRHReadingCount == 0) {
        return 0;
    }
    float result = humidityRHTotal/float(humidityRHReadingCount);
    humidityRHTotal = 0.0;
    humidityRHReadingCount = 0;
    return result;
}


float getAndResetPressurePascals()
{
    if(pressurePascalsReadingCount == 0) {
        return 0;
    }
    float result = pressurePascalsTotal/float(pressurePascalsReadingCount);
    pressurePascalsTotal = 0.0;
    pressurePascalsReadingCount = 0;
    return result;
}

//===========================================================================
// Rain Guage
//===========================================================================
int RainPin = D2;
volatile unsigned int rainEventCount;
unsigned int lastRainEvent;
float RainScaleInches = 0.011; // Each pulse is .011 inches of rain

void initializeRainGauge() {
  pinMode(RainPin, INPUT_PULLUP);
  rainEventCount = 0;
  lastRainEvent = 0;
  attachInterrupt(RainPin, handleRainEvent, FALLING);
  return;
  }

void handleRainEvent() {
    // Count rain gauge bucket tips as they occur
    // Activated by the magnet and reed switch in the rain gauge, attached to input D2
    unsigned int timeRainEvent = millis(); // grab current time

    // ignore switch-bounce glitches less than 10mS after initial edge
    if(timeRainEvent - lastRainEvent < 10) {
      return;
    }

    rainEventCount++; //Increase this minute's amount of rain
    lastRainEvent = timeRainEvent; // set up for next event
}

float getAndResetRainInches()
{
    float result = RainScaleInches * float(rainEventCount);
    rainEventCount = 0;
    return result;
}

//===========================================================================
// Wind Speed (Anemometer)
//===========================================================================

// The Anemometer generates a frequency relative to the windspeed.  1Hz: 1.492MPH, 2Hz: 2.984MPH, etc.
// We measure the average period (elaspsed time between pulses), and calculate the average windspeed since the last recording.

int AnemometerPin = D3;
float AnemometerScaleMPH = 1.492; // Windspeed if we got a pulse every second (i.e. 1Hz)
volatile unsigned int AnemoneterPeriodTotal = 0;
volatile unsigned int AnemoneterPeriodReadingCount = 0;
volatile unsigned int GustPeriod = UINT_MAX;
unsigned int lastAnemoneterEvent = 0;

void initializeAnemometer() {
  pinMode(AnemometerPin, INPUT_PULLUP);
  AnemoneterPeriodTotal = 0;
  AnemoneterPeriodReadingCount = 0;
  GustPeriod = UINT_MAX;  //  The shortest period (and therefore fastest gust) observed
  lastAnemoneterEvent = 0;
  attachInterrupt(AnemometerPin, handleAnemometerEvent, FALLING);
  return;
  }

void handleAnemometerEvent() {
    // Activated by the magnet in the anemometer (2 ticks per rotation), attached to input D3
     unsigned int timeAnemometerEvent = millis(); // grab current time

    //If there's never been an event before (first time through), then just capture it
    if(lastAnemoneterEvent != 0) {
        // Calculate time since last event
        unsigned int period = timeAnemometerEvent - lastAnemoneterEvent;
        // ignore switch-bounce glitches less than 10mS after initial edge (which implies a max windspeed of 149mph)
        if(period < 10) {
          return;
        }
        if(period < GustPeriod) {
            // If the period is the shortest (and therefore fastest windspeed) seen, capture it
            GustPeriod = period;
        }
        AnemoneterPeriodTotal += period;
        AnemoneterPeriodReadingCount++;
    }

    lastAnemoneterEvent = timeAnemometerEvent; // set up for next event
}

float getAndResetAnemometerMPH(float * gustMPH)
{
    if(AnemoneterPeriodReadingCount == 0)
    {
        *gustMPH = 0.0;
        return 0;
    }
    // Nonintuitive math:  We've collected the sum of the observed periods between pulses, and the number of observations.
    // Now, we calculate the average period (sum / number of readings), take the inverse and muliple by 1000 to give frequency, and then mulitply by our scale to get MPH.
    // The math below is transformed to maximize accuracy by doing all muliplications BEFORE dividing.
    float result = AnemometerScaleMPH * 1000.0 * float(AnemoneterPeriodReadingCount) / float(AnemoneterPeriodTotal);
    AnemoneterPeriodTotal = 0;
    AnemoneterPeriodReadingCount = 0;
    *gustMPH = AnemometerScaleMPH  * 1000.0 / float(GustPeriod);
    GustPeriod = UINT_MAX;
    return result;
}


//===========================================================
// Wind Vane
//===========================================================
void initializeWindVane() {
    return;
}

// For the wind vane, we need to average the unit vector components (the sine and cosine of the angle)
int WindVanePin = A0;
float windVaneCosTotal = 0.0;
float windVaneSinTotal = 0.0;
unsigned int windVaneReadingCount = 0;

void captureWindVane() {
    // Read the wind vane, and update the running average of the two components of the vector
    unsigned int windVaneRaw = analogRead(WindVanePin);

    float windVaneRadians = lookupRadiansFromRaw(windVaneRaw);
    if(windVaneRadians > 0 && windVaneRadians < 6.14159)
    {
        windVaneCosTotal += cos(windVaneRadians);
        windVaneSinTotal += sin(windVaneRadians);
        windVaneReadingCount++;
    }
    return;
}

float getAndResetWindVaneDegrees()
{
    if(windVaneReadingCount == 0) {
        return 0;
    }
    float avgCos = windVaneCosTotal/float(windVaneReadingCount);
    float avgSin = windVaneSinTotal/float(windVaneReadingCount);
    float result = atan(avgSin/avgCos) * 180.0 / 3.14159;
    windVaneCosTotal = 0.0;
    windVaneSinTotal = 0.0;
    windVaneReadingCount = 0;
    // atan can only tell where the angle is within 180 degrees.  Need to look at cos to tell which half of circle we're in
    if(avgCos < 0) result += 180.0;
    // atan will return negative angles in the NW quadrant -- push those into positive space.
    if(result < 0) result += 360.0;

   return result;
}

float lookupRadiansFromRaw(unsigned int analogRaw)
{
    // The mechanism for reading the weathervane isn't arbitrary, but effectively, we just need to look up which of the 16 positions we're in.
    if(analogRaw >= 2200 && analogRaw < 2400) return (3.14);//South
    if(analogRaw >= 2100 && analogRaw < 2200) return (3.53);//SSW
    if(analogRaw >= 3200 && analogRaw < 3299) return (3.93);//SW
    if(analogRaw >= 3100 && analogRaw < 3200) return (4.32);//WSW
    if(analogRaw >= 3890 && analogRaw < 3999) return (4.71);//West
    if(analogRaw >= 3700 && analogRaw < 3780) return (5.11);//WNW
    if(analogRaw >= 3780 && analogRaw < 3890) return (5.50);//NW
    if(analogRaw >= 3400 && analogRaw < 3500) return (5.89);//NNW
    if(analogRaw >= 3570 && analogRaw < 3700) return (0.00);//North
    if(analogRaw >= 2600 && analogRaw < 2700) return (0.39);//NNE
    if(analogRaw >= 2750 && analogRaw < 2850) return (0.79);//NE
    if(analogRaw >= 1510 && analogRaw < 1580) return (1.18);//ENE
    if(analogRaw >= 1580 && analogRaw < 1650) return (1.57);//East
    if(analogRaw >= 1470 && analogRaw < 1510) return (1.96);//ESE
    if(analogRaw >= 1900 && analogRaw < 2000) return (2.36);//SE
    if(analogRaw >= 1700 && analogRaw < 1750) return (2.74);//SSE
    if(analogRaw > 4000) return(-1); // Open circuit?  Probably means the sensor is not connected
    Particle.publish("error", String::format("Got %d from Windvane.",analogRaw), 60 , PRIVATE);
    return -1;
}

Looks like you’re doing a lot of work to figure out angles and everything, how about starting really simple with something like:

//Read the wind direction sensor, return heading in degrees
int get_wind_direction()
{
  unsigned int adc;

  adc = analogRead(WDIR); // get the current reading from the sensor

  // The following table is ADC readings for the wind direction sensor output, sorted from low to high.
  // Each threshold is the midpoint between adjacent headings. The output is degrees for that ADC reading.
  // Note that these are not in compass degree order! See Weather Meters datasheet for more information.

  if(adc > 2270 && adc < 2290) return (0);//North
  if(adc > 3220 && adc < 3240) return (1);//NE
  if(adc > 3890 && adc < 3910) return (2);//East
  if(adc > 3780 && adc < 3800) return (3);//SE

  if(adc > 3570 && adc < 3590) return (4);//South
  if(adc > 2790 && adc < 2810) return (5);
  if(adc > 1580 && adc < 1610) return (6);
  if(adc > 1930 && adc < 1950) return (7);

  return (-1); // error, disconnected?
}

That’ll give you a number, 0-7 for cardinal directions. Compare your readings to your north so you can change it accordingly based on how you installed your wind vane. :slight_smile:

edit: also try formatting your serial output a little more, something like…

String line = String::format("wind dir: %f", windDegrees);
Serial.print(line);

Thanks,
David

3 Likes

That’s very helpful, thank you Dave!

1 Like