You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
2.9 KiB
C++

#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);
}