Davis Wind Sensor
From: https://www.qsl.net/on7eq/projects/arduino_davis.htm
Intro
ARDUINO readout of DAVIS Wind Sensor
This sketch will readout a DAVIS Wind sensor (Vantage Pro & Vantage Pro 2)
and display the wind direction & speed on a 2x 16 character LCD display. The
same low cost wind sensor is available from other sources (see specs here)
In addition, the temperature is measured with a 10k NTC resistor, which can
be mounted outside, close to the wind sensor.
The wind vane direction can be permanently calibrated with following
procedure : upon startup of the ARDUINO board, depress the CAL button while
the vane is oriented towards the true North. From that moment on, the
correction is stored in EEPROM and readouts will be correct.
See http://www.lexingtonwx.com/anemometer/ for detailed about the sensor.
Schematic of the DAVIS Wind Sensor
This is the sketch or download it here. It was compiled with IDE version
0022.- IMPORTANT : please use the same or you might get errors when
compiling ! You still can download previous versions from ARDUINO website .
The interrupt is triggered by FALLING level, because RISING proved to be
less accurate at high wind speed. The code called by the interrupt provides
a timer (15 ms) to avoid REED contact bounce, it will allow to measure wind
speeds in excess of 150 km/h.
Sketch
/*H*******************************************************
Sketch to read David Wind Vane
de ON7EQ Dec 2011
To disable interrupts:
cli(); // disable global interrupts
and to enable them:
sei(); // enable interrupts
NTC readout routine
http://arduino.cc/playground/ComponentLib/Thermistor2
===================================================================
Thermistor Schematic
===================================================================
(+5v ) ---- (10k-Resister) -------|------- (Thermistor) ---- (GND)
|
Analog Pin 'NTCpin'
===================================================================
DAVIS Vantage Pro & Vantage Pro 2 Wind Sensor (speed & direction
===================================================================
On RJ-45 plug terminals:
Black = pulse from anemometer. Connect to Digital 2 pin, and use a 4k7
resistor as pull up to + 5v.
use a 10 to 22nF capacitor from pin D2 to ground to debounce the reed
switch of anemometer
Red = Ground
Green = Wiper of Wind direction vane - connect to A0. Use a 1 ... 10 µF /
16v capacitor between A0 and ground (observe C polarity) to avoid jitter
Yellow = + 5v (reference of potentiometer)
*********************************************************/
#include // REQUIRED TO MEMORIZE ANTENNA / BAND CONFIG
#include
#include
// **************** DEFINES ****************************
#define PotPin (A0) // define the input pin for the wind vane potentiometer
#define CalPin (A1) // define the input pin to initiate direction
#define RPMsensor (2) //The pin location of the anemometer sensor
#define NTCpin (A4) // Pin for NTC 10k
// **************** PROTOTYPES *************************
double Thermister( int RawADC );
void calibrate();
double Thermister( int RawADC );
// **************** VARIABLES **************************
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int Direction ; // Wind direction
int PotValue = 0; // variable to store the value coming from the
potentiometer
int DirCorr = 0; // Correction on direction ( - 360 to + 360)
calibration @ startup. Ground pin to calibrate
byte DirCorrB1 = 0; // 2 bytes of DirCorr
byte DirCorrB2 = 0;
volatile unsigned long RPMTops; // RPM tops counter in interrupt routine
volatile unsigned long ContactTime; // Timer to avoid conatct bounce in
interrupt routine
float RPM; // RPM count
float TEMP; // Temp
float temp = (0);
byte degree [8] = { // build LCD specific characters 'degrees'
B00100,
B01010,
B00100,
B00000,
B00000,
B00000,
B00000,
};
/*F*******************************************************
*
*********************************************************/
void
setup()
{
// Clean EEPROM
// EEPROM.write( 1, 0);
// EEPROM.write( 2, 0);
// set up the LCD's number of columns and rows:
lcd.begin( 16, 2 );
lcd.clear();
// Print a message to the LCD.
lcd.print( " DAVIS Readout");
lcd.setCursor( 0, 1);
lcd.print( " v2.0 de ON7EQ");
delay( 2000 );
// CALIBRATE if button depressed at startup !
if( (analogRead( CalPin ) < 512))
calibrate ();
// else retrieve CAL vales from EEPROM
DirCorrB1 = EEPROM.read( 1 );
DirCorrB2 = EEPROM.read( 2 );
DirCorr = (DirCorrB1) + (DirCorrB2);
lcd.clear(); // print screen template
// Print variables
lcd.setCursor( 0, 0 );
lcd.print( "Dir " );
lcd.setCursor( 12, 0 );
lcd.print( "Temp" );
pinMode( RPMsensor, INPUT );
attachInterrupt( 0, rpm, FALLING);
lcd.createChar( 0, degree );
lcd.setCursor( 7, 0 );
lcd.write( 0 );
// speed
lcd.setCursor( 0, 1 );
lcd.print( "Spd 0km/h");
}
/*F*******************************************************
*
*********************************************************/
void
loop()
{
// Wind Direction
PotValue = analogRead( PotPin ); // READ VALUE FROM POTMETER
Direction = map( PotValue, 0, 1023, 0, 359 );
Direction = Direction + DirCorr + 3; // FIX OFFSET & 5° PRECISION
convert: // Convert to 360°
if( Direction < 0 )
{
Direction = Direction + 360;
goto convert;
}
if( Direction > 360)
{
Direction = Direction - 360;
goto convert;
}
if( Direction == 360)
Direction = 0;
lcd.setCursor( 4, 0); // PRINT VALUE FROM POTMETER
if( Direction < 100)
lcd.print("0");
if( Direction < 10)
lcd.print("0");
// 5° PRECISION IS ENOUGH TO PRINT TE DIRECTION VALUE
lcd.print( (( Direction / 5) *5), DEC);
lcd.setCursor(9, 0);
if( (Direction) < 23)
{
lcd.print(" N");
}
if( (Direction>22) && (Direction < 68))
{
lcd.print("NE");
}
if( (Direction>67) && (Direction < 113))
{
lcd.print(" E");
}
if( (Direction>112) && (Direction< 158))
{
lcd.print("SE");
}
if( (Direction>157) && (Direction< 203))
{
lcd.print(" S");
}
if( (Direction>202) && (Direction< 247))
{
lcd.print("SW");
}
if( (Direction>246) && (Direction< 292))
{
lcd.print(" W");
}
if( (Direction>291) && (Direction< 337))
{
lcd.print("NW");
}
if( (Direction>336) && (Direction< 360))
{
lcd.print(" N");
}
// measure & print the temp
lcd.setCursor( 11, 1);
TEMP = ((Thermister(1023 - analogRead(NTCpin))) + 0.0);
if( TEMP >= 0 )
lcd.print(" "); // If temp positive, print space, else a '-' will show up
if( abs( TEMP ) < 10)
lcd.print(" ");
lcd.print( TEMP, DEC);
// measure RPM
RPMTops = 0; // SET nBtOPS TO 0 READY FOR CALCULATIONS
sei(); // ENABLES INTERRUPTS
delay( 3000 ); // WAIT 3 SECONDS TO AVERAGE
cli(); // DISABLE INTERRUPTS
// convert to km/h
if( (RPMTops >= 0) and (RPMTops < 21))
RPM = RPMTops * 1.2;
if( (RPMTops > 21) and (RPMTops < 45))
RPM = RPMTops * 1.15;
if( (RPMTops > 45) and (RPMTops < 90))
RPM = RPMTops * 1.1;
if( (RPMTops > 90) and (RPMTops < 156))
RPM = RPMTops * 1.0;
if( (RPMTops > 156) and (RPMTops < 999))
RPM = RPMTops * 1.0;
// print speed
lcd.setCursor( 4, 1);
if( RPM < 100)
lcd.print(" ");
if( RPM < 10)
lcd.print(" ");
lcd.print( int( RPM ), DEC);
}
/*F*******************************************************
* This is the function that interrupt calls to measure RPM
*********************************************************/
void
rpm()
{
if( (millis() - ContactTime) > 15 )
{// DEBOUNCE OF REED CONTACT. WITH 15MS SPEED MORE THAN 150 KM/H CAN BE MEASUREd
RPMTops++;
ContactTime = millis();
}
}
/*F*******************************************************
* This is the function that calibrates the vane
*********************************************************/
void
calibrate()
{
lcd.setCursor( 0, 1 );
lcd.print( "Hold to calibr !");
delay( 2000 ); // WAIT 2 SECOND
if( (analogRead( CalPin) > 512))
setup(); // CAL NOT REALLY REQUIRED ... ABORT
!
lcd.setCursor( 0, 1 );
lcd.print( "Now calibrating ... ");
delay( 1000 ); // WAIT 1 SECOND
PotValue = analogRead( PotPin ); // READ VALUE FROM POTMETER
DirCorr = map(PotValue, 0, 1023, 359, 0);
lcd.setCursor( 0, 1 );
lcd.print( "CAL value = ");
lcd.print( DirCorr, DEC);
lcd.print( " ");
delay( 2000 ); //Wait 2 seconds
DirCorrB1 = DirCorr / 255;
if( DirCorrB1 == 1)
{
DirCorrB1 = 255;
DirCorrB2 = DirCorr - 255 ;
}
else
{
DirCorrB1 = DirCorr;
DirCorrB2 = 0;
}
// DirCorrB1 = DirCorr;
// DirCorrB2 = 0;
EEPROM.write( 1, DirCorrB1 );
EEPROM.write( 2, DirCorrB2 );
wait:
lcd.setCursor( 0, 1 );
lcd.print( "CAL OK - Release ! ");
if( (analogRead( CalPin ) < 512) )
goto wait;
lcd.setCursor( 0, 1 );
lcd.print( "Now rebooting... ");
delay( 1000 );
setup ();
}
/*F*******************************************************
* This function will calculate temperature from 10k NTC readout
*********************************************************/
double
Thermister( int RawADC )
{
double Temp;
Temp = log( ((10240000/RawADC) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp
))* Temp );
Temp = Temp - 273.15; // CONVERT KELVIN TO CELCIUS
// Temp = (Temp * 9.0)/ 5.0 + 32.0; // CONVERT CELCIUS TO FAHRENHEIT
return Temp;
}