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