#define VANE_PIN A0 #define VANE_VOLTAGE 5.0 #define VANE_POWER_PIN 7 #define VANE_REFER 10000 #define VANE_MEASURE_ITERATIONS 3 #define ANEMOMERTER_PIN 2 void setup() { Serial.begin(9600); pinMode(VANE_PIN, INPUT); pinMode(VANE_POWER_PIN, OUTPUT); pinMode(ANEMOMERTER_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(ANEMOMERTER_PIN), anemometerTick, CHANGE); } /* * Wind direction (vane) * * The measurements are made with an R10k as R1 in the voltage divider (VANE_REFER constant). * * List of corrections as in `documentation => measured value`. * 0.32 => 0.37 */ static const float vaneValue[16] {0.37,0.41,0.45,0.62,0.90,1.19,1.40,1.98,2.25,2.93,3.08,3.43,3.84,4.04,4.33,4.62}; static const float vaneDirection[16] {112.5,67.5,90,157.5,135,202.5,180,22.5,45,247.5,225,337.5,0,292.5,315,270}; float getWindVane() { double vin = 0; digitalWrite(VANE_POWER_PIN, HIGH); /* Measure voltage several times for greater accuracy */ for (int i = 0; i < VANE_MEASURE_ITERATIONS; i++) { vin = vin + analogRead(A0); } digitalWrite(VANE_POWER_PIN, LOW); vin = vin / VANE_MEASURE_ITERATIONS; vin = vin * (VANE_VOLTAGE / 1023.0); /* Find the closest value from voltage array */ for (int i = 0; i < 16; i++) { if (vin - vaneValue[i] <= 0) { /* Check for the first */ if (i == 0) return vaneDirection[i]; /* * Check if the new value is in the negative. * This prefers the lower value (4 from 4.5 etc). */ if (-(vin - vaneValue[i]) < vin - vaneValue[i-1]) return vaneDirection[i]; return vaneDirection[i-1]; } } /* * In case a negative value is never reached, return the last value in the array. */ return vaneDirection[15]; } /* Wind speed */ #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 anemometerTick() { long thisTime = micros() - anem_last; anem_last = micros(); if (thisTime > 500) { anem_count++; if (thisTime < anem_min) anem_min = thisTime; } } /* Rain gauge */ #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 rainTick() { long thisTime = micros() - rain_last; rain_last = micros(); if(thisTime > 500) rain_count++; } void loop() { Serial.print(getWindVane()); Serial.println("°"); Serial.println(getUnitWind()); Serial.println(getGust()); delay(1000); }