We've all seen those big 'wrought' iron weather vanes that you stick on the top of your house and annoy the whole village with their squeaky nerve grating motion. Now, at last, we can keep all those quaint traditional features, but add on a super accurate 8 bit digital transducer to relay our wind direction to the world wide web.

This project uses the fantastic Bourns ACE-128 digital rotary encoder, a few ball roller bearings and some scraps of rusty old metal to build the ultimate weather vane. During the build, I learnt about some stuff called 'grey code', how to create a pulsed variable frequency output and how to calculate the mode average of my readings.

## Step 1: How It Works

The Bourns encoder has ten pins on the outside and an elaborate array of brushed contacts on the inside. As the wind vane turns, it makes a complicated set of connects and disconnects which results in an 8 digit binary output composed of zeros and ones. These binary numbers are then processed by a tiny 'Nano' arduino inside the wind vane body and compared to a 'Truth Table' supplied by the manufacturer of the encoder. Over a ten minute period 1,200 readings are made and each separate wind direction recorded is added up to work out which direction is the most common - this is the 'Mode' value. This mode value is transmitted by a pulsed frequency down a cable to another arduino in the main weather station box and the frequency is measured and turned into an integer between 0 and 360.

Now the information is assembled with a whole bunch of other reading from an array of sensors and compiled into a special string of characters to be transmitted by a mobile cellular modem to a server in London, UK via the Inter web. If the server successfully receives the data, it makes a 'Call Back' to the weather station and all the sensors are reset to zero. The server then processes the data, making a few simple calculations and then spits it all out into Java Script based charts and PHP raw data tables at: http://www.goatindustries.co.uk/weather/

For now, we're just going to concentrate on the digital wind vane as the rest of the weather station is to be published as other Instructables. Watch this space!

## Step 2: Parts

1. Various bits of old rusty steel
2. Arduino 'Nano' x 1
3. Bourns EAW0J-B24-AE0128L Rotary Encoder 128
4. 10mm stainless steel rod
5. Waste water pipe OD 35mm
6. Thin walled stainless pipe OD38mm
7. 10mm 'Pillow' bearing blocks
8. Electrical cable strain relief grommet x2
9. 4 core cable x 0.75mm2 (SWG 20)
10. Various bolts and screws

## Step 3: Fabrication Process

Fabrication of the sensor was the easy part of the project. I know it's not the prettiest looking wind vane on the planet, but it works well and it's water proof.

******NO FANCY TOOLS WERE USED DURING FABRICATION********

I did use a MIG welder, but the weld could just have easily been made with silver solder or by brazing.

The photos above are in chronological order and should explain how the sensor was built without me waffling on too much. The trickiest bit was working out how to make a waterproof shroud to go over the rotary encoder and the electronics without using a lathe. This was achieved by using a strain relief grommet designed for 10mm cable which makes a water tight seal against the 10mm stainless rod. The rotating shroud fits over the stationary black plastic 35mm waste water pipe which itself houses the electronics. The shroud was packed with grease to prevent water wicking up into the electronics through capillary action.

The wind vane itself needs to be large enough to overcome the small mechanical resistance in the rotary encoder. Mine is about 200 x 300 mm and stops turning in very light winds under 5 mph.

The Nano was wired up using crimpable terminals and made robust by covering in copious quantities of hot glue.

## Step 4: Programming the Nano

The black 35 mm waste water pipe contains an Arduino Nano which is programmed to read the data from the Bourns rotary encoder and compare it to a truth table to give actual wind direction in Polar coordinates (degrees).

Each 'bit' of data is read separately and compiled into a 'String' of data 8 segments long. At this stage it looks like a load of zeros and ones eg. 00100110.

This string is then converted to an integer.

The integer produced is compared to 128 other integers in a truth table to see what direction the sensor is actually pointing at.

Over the course of about ten minutes, readings of the rotary encoder are taken at 0.5 second intervals and a calculation is made to find which one is the most common one. It's not acceptable to just take one reading as wind direction is never actually constant unless the wind speed is too low to move the sensor. A final reading of 248 degrees, for example, is extrapolated from a massive array of about 1200 numbers!

The final mode integer is then converted into it's own distinct frequency using the Arduino 'Tone' function and sent down the 4 core cable, via a 10K resistor, as a very short square wave pulse every 0.5 seconds. We could send a continuous signal, but this would waste valuable electrical energy.

Finally, there is a pin on the Nano dedicated to receiving a call back signal from the main weather station processor to reset all the values and start assembling a brand new mode wind direction value.

```<p>int p=0;<br>  unsigned long n=0;
int answerAB;   // Change this to an int for debugging.
int count=0;
int resetNanoStatus;
const int ledPin = 13; // the pin that the LED is attached to
int callBackFromMaster = 11;
// Tone output on pin 10.
int val1 =0;
int resetStatus = LOW;

int aa=0;
int ab=0;
int ac=0;
int ae=0;
int af=0;
int ag=0;

int ah=0;
int ai=0;
int aj=0;
int ak=0;
int al=0;
int am=0;
int ba=0;
int bb=0;
int bc=0;
int bd=0;
int be=0;
int bf=0;

int bg=0;
int bh=0;
int bi=0;
int bj=0;
int bk=0;
int bl=0;
int ca=0;
int cb=0;
int cc=0;
int cd=0;
int ce=0;
int cf=0;

int cg=0;
int ch=0;
int ci=0;
int cj=0;
int ck=0;
int cl=0;
int ea=0;
int eb=0;
int ec=0;
int ed=0;
int ee=0;
int ef=0;

int eg=0;
int eh=0;
int ei=0;
int ej=0;
int ek=0;
int el=0;
int fa=0;
int fb=0;
int fc=0;
int fd=0;
int fe=0;
int ff=0;
int fg=0;
int fh=0;
int fi=0;
int fj=0;
int fk=0;
int fl=0;
int ga=0;
int gb=0;
int gc=0;
int gd=0;
int ge=0;
int gf=0;
int gg=0;
int gh=0;
int gi=0;
int gj=0;
int gk=0;
int gl=0;
int ha=0;
int hb=0;
int hc=0;
int hd=0;
int he=0;
int hf=0;
int hg=0;
int hh=0;
int hi=0;
int hj=0;
int hk=0;
int hl=0;
int ia=0;
int ib=0;
int ic=0;
int id=0;
int ie=0;
int iff=0;
int ig=0;
int ih=0;
int ii=0;
int ij=0;
int ik=0;
int il=0;
int ja=0;
int jb=0;
int jc=0;
int jd=0;
int je=0;
int jf=0;
int jg=0;
int jh=0;
int ji=0;
int jj=0;
int jk=0;
int jl=0;
int ka=0;
int kb=0;
int kc=0;
int kd=0;
int ke=0;
int kf=0;
int kg=0;
int kh=0;
int ki=0;
int kj=0;
int kk=0;
int kl=0;
int la=0;
int lb=0;
int lc=0;
int ld=0;
int le=0;
int lf=0;
int lg=0;
int lh=0;
int li=0;
int lj=0;
int lk=0;
int ll=0;
int lm=0;
void setup() {
pinMode(ledPin, OUTPUT);

//start serial connection
Serial.begin(115200);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
// tone is on pin 10
pinMode(11, INPUT_PULLUP);             // Call back from Master.
pinMode(13, OUTPUT);
String d;
}
void loop() {
resetValues();

count =count+1;
//  Serial.print("Integers =              ");
//  Serial.print(columnOne);
//  Serial.print(columnTwo);
//  Serial.print(columnThree);
//  Serial.print(columnFour);
//  Serial.print(columnFive);
//  Serial.print(columnSix);
//  Serial.print(columnSeven);
//  Serial.println(columnEight);
//  Serial.print("n =                      ");Serial.println(n);

String d = String(columnOne)+String(columnTwo)+String(columnThree)+String(columnFour)+String(columnFive)+String(columnSix)+String(columnSeven)+String(columnEight);
//  Serial.print("data in string format = ");Serial.println(d);
//  Serial.print("count = ");Serial.println(count);
n = d.toInt();
if (n==10011000){p=6;}
if (n==10011111){p=17;}
if (n==10000111){p=29;}
if (n==10010111){p=30;}
if (n==10001111){p=34;}
if (n==10001110){p=35;}
if (n==10000011){p=68;}
if (n==10001011){p=69;}
if (n==10001001){p=70;}
if (n==10000001){p=71;}
if (n==10000000){p=72;}
if (n==10000100){p=73;}
if (n==10010100){p=74;}
if (n==10010000){p=121;}
if (n==10010010){p=122;}
if (n==10011010){p=123;}
if (n==10011110){p=124;}
if (n==10111000){p=5;}
if (n==10101111){p=15;}
if (n==10111111){p=16;}
if (n==10100100){p=26;}
if (n==10100110){p=27;}
if (n==10100111){p=28;}
if (n==10101001){p=59;}
if (n==10100011){p=67;}
if (n==10111100){p=110;}
if (n==10111110){p=111;}
///////////////////////////////////////////
if (n==11111110){p=112;}
if (n==11010100){p=75;}
if (n==11110100){p=76;}
if (n==11110000){p=77;}
if (n==11110010){p=78;}
if (n==11111010){p=79;}
if (n==11111011){p=80;}
if (n==11111001){p=81;}
if (n==11110001){p=82;}
if (n==11010001){p=83;}
if (n==11000001){p=84;}
if (n==11000101){p=85;}
if (n==11000100){p=86;}
if (n==11000000){p=87;}
if (n==11111101){p=96;}
if (n==11111100){p=97;}
if (n==11111000){p=98;}
if (n==11101000){p=99;}
if (n==11100000){p=100;}
if (n==11100010){p=101;}
if (n==11101001){p=60;}
if (n==11100001){p=61;}
if (n==11100101){p=62;}
if (n==11110101){p=63;}
if (n==11110111){p=64;}
if (n==11110011){p=65;}
if (n==11100011){p=66;}
if (n==11010011){p=44;}
if (n==11000011){p=45;}
if (n==11001011){p=46;}
if (n==11101011){p=47;}
if (n==11101111){p=48;}
if (n==11100111){p=49;}
if (n==11000111){p=50;}
if (n==11010111){p=31;}
if (n==11011111){p=32;}
if (n==11001111){p=33;}
/////////////////////////////////////////
if (n==111111){p=1;}
if (n==111110){p=2;}
if (n==111010){p=3;}
if (n==111000){p=4;}
if (n==11000){p=7;}
if (n==1000){p=8;}
if (n==1111){p=13;}
if (n==101111){p=14;}
if (n==11111){p=18;}
if (n==11101){p=19;}
if (n==11100){p=20;}
if (n==1100){p=23;}
if (n==100){p=24;}
if (n==100100){p=25;}
if (n==1110){p=36;}
if (n==101110){p=37;}
if (n==100110){p=38;}
if (n==110){p=39;}
if (n==10){p=40;}
if (n==10010){p=41;}
if (n==111){p=52;}
if (n==10111){p=53;}
if (n==10011){p=54;}
if (n==11){p=55;}
if (n==1){p=56;}
if (n==1001){p=57;}
if (n==101001){p=58;}
if (n==100000){p=104;}
if (n==100001){p=105;}
if (n==100101){p=106;}
if (n==110101){p=107;}
if (n==111101){p=108;}
if (n==111100){p=109;}
if (n==110001){p=118;}
if (n==110000){p=119;}
if (n==10000){p=120;}
if (n==11110){p=125;}
////////////////////////////////////////
if (n==1001000){p=9;}
if (n==1001001){p=10;}
if (n==1001101){p=11;}
if (n==1001111){p=12;}
if (n==1111111){p=0;}
if (n==1011100){p=21;}
if (n==1001100){p=22;}
if (n==1010010){p=42;}
if (n==1010011){p=43;}  // Take the front 0 off.
if (n==1000111){p=51;}
if (n==1000000){p=88;}
if (n==1000010){p=89;}
if (n==1001010){p=90;}
if (n==1101010){p=91;}
if (n==1111010){p=92;}
if (n==1111000){p=93;}
if (n==1111001){p=94;}
if (n==1111101){p=95;}
if (n==1100010){p=102;}
if (n==1100000){p=103;}
if (n==1111110){p=113;}
if (n==1111100){p=114;}
if (n==1110100){p=115;}
if (n==1110000){p=116;}
if (n==1110001){p=117;}
if (n==1011110){p=126;}
if (n==1011111){p=127;} </p><p>// Group A:
if (p==0){aa=aa+1;}
if (p==1){ab=ab+1;}
if (p==2){ac=ac+1;}
if (p==4){ae=ae+1;}
if (p==5){af=af+1;}
if (p==6){ag=ag+1;}

// Group B:
if (p==7){ah=ah+1;}
if (p==8){ai=ai+1;}
if (p==9){aj=aj+1;}
if (p==10){ak=ak+1;}
if (p==11){al=al+1;}
if (p==12){am=am+1;}
// Group C:
if (p==13){ba=ba+1;}
if (p==14){bb=bb+1;}
if (p==15){bc=bc+1;}
if (p==16){bd=bd+1;}
if (p==17){be=be+1;}
if (p==18){bf=bf+1;}
// Group D:
if (p==19){bg=bg+1;}
if (p==20){bh=bh+1;}
if (p==21){bi=bi+1;}
if (p==22){bj=bj+1;}
if (p==23){bk=bk+1;}
if (p==24){bl=bl+1;}
// Group E:
if (p==25){ca=ca+1;}
if (p==26){cb=cb+1;}
if (p==27){cc=cc+1;}
if (p==28){cd=cd+1;}
if (p==29){ce=ce+1;}
if (p==30){cf=cf+1;}
// Group F:
if (p==31){cg=cg+1;}
if (p==32){ch=ch+1;}
if (p==33){ci=ci+1;}
if (p==34){cj=cj+1;}
if (p==35){ck=ck+1;}
if (p==36){cl=cl+1;}
// Group I:
if (p==37){ea=ea+1;}
if (p==38){eb=eb+1;}
if (p==39){ec=ec+1;}
if (p==40){ed=ed+1;}
if (p==41){ee=ee+1;}
if (p==42){ef=ef+1;}
// Group J:
if (p==43){eg=eg+1;}
if (p==44){eh=eh+1;}
if (p==45){ei=ei+1;}
if (p==46){ej=ej+1;}
if (p==47){ek=ek+1;}
if (p==48){el=el+1;}
// Group K:
if (p==49){fa=fa+1;}
if (p==50){fb=fb+1;}
if (p==51){fc=fc+1;}
if (p==52){fd=fd+1;}
if (p==53){fe=fe+1;}
if (p==54){ff=ff+1;}
// Group L:
if (p==55){fg=fg+1;}
if (p==56){fh=fh+1;}
if (p==57){fi=fi+1;}
if (p==58){fj=fj+1;}
if (p==59){fk=fk+1;}
if (p==60){fl=fl+1;}
// Group M:
if (p==61){ga=ga+1;}
if (p==62){gb=gb+1;}
if (p==63){gc=gc+1;}
if (p==64){gd=gd+1;}
if (p==65){ge=ge+1;}
if (p==66){gf=gf+1;}
// Group N:
if (p==67){gg=gg+1;}
if (p==68){gh=gh+1;}
if (p==69){gi=gi+1;}
if (p==70){gj=gj+1;}
if (p==71){gk=gk+1;}
if (p==72){gl=gl+1;}
// Group O:
if (p==73){ha=ha+1;}
if (p==74){hb=hb+1;}
if (p==75){hc=hc+1;}
if (p==76){hd=hd+1;}
if (p==77){he=he+1;}
if (p==78){hf=hf+1;}
// Group P:
if (p==79){hg=hg+1;}
if (p==80){hh=hh+1;}
if (p==81){hi=hi+1;}
if (p==82){hj=hj+1;}
if (p==83){hk=hk+1;}
if (p==84){hl=hl+1;}
// Group Q:
if (p==85){ia=ia+1;}
if (p==86){ib=ib+1;}
if (p==87){ic=ic+1;}
if (p==88){id=id+1;}
if (p==89){ie=ie+1;}
if (p==90){iff=iff+1;}
// Group R:
if (p==91){ig=ig+1;}
if (p==92){ih=ih+1;}
if (p==93){ii=ii+1;}
if (p==94){ij=ij+1;}
if (p==95){ik=ik+1;}
if (p==96){il=il+1;}
// Group S:
if (p==97){ja=ja+1;}
if (p==98){jb=jb+1;}
if (p==99){jc=jc+1;}
if (p==100){jd=jd+1;}
if (p==101){je=je+1;}
if (p==102){jf=jf+1;}
// Group T:
if (p==103){jg=jg+1;}
if (p==104){jh=jh+1;}
if (p==105){ji=ji+1;}
if (p==106){jj=jj+1;}
if (p==107){jk=jk+1;}
if (p==108){jl=jl+1;}
// Group U:
if (p==109){ka=ka+1;}
if (p==110){kb=kb+1;}
if (p==111){kc=kc+1;}
if (p==112){kd=kd+1;}
if (p==113){ke=ke+1;}
if (p==114){kf=kf+1;}
// Group V:
if (p==115){kg=kg+1;}
if (p==116){kh=kh+1;}
if (p==117){ki=ki+1;}
if (p==118){kj=kj+1;}
if (p==119){kk=kk+1;}
if (p==120){kl=kl+1;}
// Group W:
if (p==121){lg=lg+1;}
if (p==122){lh=lh+1;}
if (p==123){li=li+1;}
if (p==124){lj=lj+1;}
if (p==125){lk=lk+1;}
if (p==126){ll=ll+1;}
if (p==127){lm=lm+1;}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.print("position is:            ");Serial.println(p);
delay(500);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void resetValues()
{
if (val1 == HIGH)
{
if (resetStatus == LOW)
{
resetStatus = HIGH;
//   digitalWrite(ledPin,HIGH);
Serial.println("resetEverything = ON");
}
p=0;
n=0;
count=0;
aa=0;
ab=0;
ac=0;
ae=0;
af=0;
ag=0;
ah=0;
ai=0;
aj=0;
ak=0;
al=0;
am=0;
ba=0;
bb=0;
bc=0;
bd=0;
be=0;
bf=0;
bg=0;
bh=0;
bi=0;
bj=0;
bk=0;
bl=0;
ca=0;
cb=0;
cc=0;
cd=0;
ce=0;
cf=0;
cg=0;
ch=0;
ci=0;
cj=0;
ck=0;
cl=0;
ea=0;
eb=0;
ec=0;
ed=0;
ee=0;
ef=0;
eg=0;
eh=0;
ei=0;
ej=0;
ek=0;
el=0;
fa=0;
fb=0;
fc=0;
fd=0;
fe=0;
ff=0;
fg=0;
fh=0;
fi=0;
fj=0;
fk=0;
fl=0;
ga=0;
gb=0;
gc=0;
gd=0;
ge=0;
gf=0;
gg=0;
gh=0;
gi=0;
gj=0;
gk=0;
gl=0;
ha=0;
hb=0;
hc=0;
hd=0;
he=0;
hf=0;
hg=0;
hh=0;
hi=0;
hj=0;
hk=0;
hl=0;
ia=0;
ib=0;
ic=0;
id=0;
ie=0;
iff=0;
ig=0;
ih=0;
ii=0;
ij=0;
ik=0;
il=0;
ja=0;
jb=0;
jc=0;
jd=0;
je=0;
jf=0;
jg=0;
jh=0;
ji=0;
jj=0;
jk=0;
jl=0;
ka=0;
kb=0;
kc=0;
kd=0;
ke=0;
kf=0;
kg=0;
kh=0;
ki=0;
kj=0;
kk=0;
kl=0;
la=0;
lb=0;
lc=0;
ld=0;
le=0;
lf=0;
lg=0;
lh=0;
li=0;
lj=0;
lk=0;
ll=0;
lm=0;
}
else
{
if (resetStatus == HIGH)
{
resetStatus = LOW;
//   digitalWrite(ledPin,LOW);
Serial.println("resetEverything = OFF");
}
}
}</p>```

## Step 5: Final

So now we have our digital wind vane busily recording wind direction values every half a second and giving a web based polar coordinate with an accuracy of + or - 2.8 degrees. Surely it is the 'Must have' digital accessory for 2016? We at Meusydd don't know how we ever managed for so long without one!

In theory, there are more accurate wind vanes that work on 12 or 16 bit technology and others that work on reading resistance like a potentiometer. The question here is: 'Since wind is inherently so turbulent, is a more accurate sensor really relevant?' My first wind direction sensor was one of the cheap ones from sparkfun / maplin but this was fairly hopeless as the resistance 'truth table' that I created kept on changing for some reason. Maybe this was due to bad wiring or temperature changes? In any case, the sensor has pretty bad resolution (45 degrees) and some of the resistance mapping has very narrow bands which, all in all, lead to my total lack of confidence in the device.

Accuracy itself is not the final consideration as it needs to be compared to the sensor's reliability and it's tendancy to slew off it's intended parameters. A professional potentiometer based wind vane will be tested out sometime soon - watch this space!. The great thing about this 8 bit digital wind vane is that it never needs calibrating or adjusting for changes in temperature and each reading is totally 'absolute'. The only question I ask myself is 'how long will the Bourns transducer last?' The manual specifies 10,000 revolutions but how many revolutions or equivalent movements will my weather vane be making per year? Also, maybe there are better 8 bit transducers out there?

Awesome. Love the dog!
<p>Yes the dog is cute although technically including cute photos of animals is cheating the competitions.</p>
This is a good &quot;inspirational&quot; start for a couple of sensors I want to hook up to a LinkItOne board. I have circuits for a water level detector and a battery monitor that both produce 8 bit outputs. I had not thought of using a NANO but they are cheap enough to buy in quantities and have I2C output so I could use them as remote sensors. Thanks for the idea!
<p>You'll only have 4 metres of cable length on the I2C which is why I used a pulsed frequency. Good luck and post up your creation!</p>
You have my vote! <br>Two questions thought<br>Could I use any rotary encoder? <br>And how long would one last, would it not ware out quickly?
There are a few other possible rotary encoders. This one is good for 50,000 revolutions and is cheap and easy to replace.
Sorry, I posted the questions without reading ALL that you typed.
<p>Fantastic, you have no idea how much work you have just saved me LOL</p>
Thanks! What are you / were you going to build?
<p>Oddly enough, almost exactly this project LOL The only difference is a mechanical readout as well as the web one.</p>
<p>It would be great to see your mechanical readout. I can imagine some kind of coffee table wifi enabled device that moves in sync with the outside vane. How about a mechanical readout for the thermometer and windspeed etc?</p>
<p>You are thinking along the right lines for the mechanical readout. I wanted to have a vacuum tube display for the temp and wind speed, but the wife didn't like that idea, and as I'm building it for her she gets the final say (she does anyway, but for this she has more reason to than normal LOL)</p>
<p>You'll need to design something that you'll both enjoy, which will be better than if either of you had designed it alone. To quote Aristotle: &quot;The whole is greater than the sum of the parts&quot;.</p>
<p>Anything that stops me getting nagged is totally beautiful as far as I'm concerned LOL</p>