Friday 17 January 2014

The Wind Sensor

Hello again!

it's almost 2 months since my last post and believe it or not, I have not abandoned the project.
To say the truth I have been tempted to "postpone" developments and start a couple new ones and actually I have started working on a drone BUT I have to go on with this "Ship Computer" project -if not for anything else- for the simple reason that I need to have it!

So, on my last post I was putting a draft version of the system together using a Raspberry PI as the heart of the system.

I had also mentioned that I was going to use an I2C Analog to Digital converter and I had actually bought a couple -pretty expensive- ones.

The thing is, I thought it over a bit and decided to use a Arduino Pro Mini for interfacing with the Wind Sensor.

The Arduno Pro Mini is this one:
It is a full-fledged Arduino in a tiny package.
How tiny is tiny?
Tiny enough to look small next to a credit-card sized Raspberry:
The same time it can be bought from ebay for just a couple euros, making it extremely more cost effective compared to the ADC I was thinking of using while still far more versatile.

So, it was not much of a question really, I was going to use the Arduino in order to get measurements for wind speed and direction.

The actual transducer for getting this measurements was a low cost NASA MARINE masthead unit as shown here.

Two months and something ago I had tried to get in contact with Nasa Marine in order to get some info on this unit but there was not a reply.
So, I had to do a bit of reverse engineering.
The unit terminates on a 5-pin DIN connector, same as the one of the old (pre-nineties) PC keyboard, whose pin layout is as follows:
Playing a bit with a multimeter, I decoded the signals:
  1. Pin 1:Pulse per Wind Cups rotation
  2. Pin 2:GND
  3. Pin 3:+5V
  4. Pin 4:Analog output 1
  5. Pin 5:Analog output 2
The values of the two analog signals somehow indicated the wind direction and I had to decode that.
The wind speed would be almost proportional to the rotating speed of the cup rotor, which produced a pulse for a full turn.

Next I attached the masthead unit to a bookcase next to my desk so that I could rotate the windex and the cup rotor:


...and I fed the signals to the Arduino:
 ...and also connected an LCD display so that I would have a quick way to see what was going on.

All I needed was a bit of software, the soul that would make it tick.

I spent a couple of nights and here it is:
#define bsize 10
#include <LiquidCrystal.h>
#include <FlexiTimer2.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);

const int APin2 = A1;
const int APin4 = A0;  //Connector PIN4, Wire color BROWN
const int led = 13;    //Built-in led
const int PulsePin = 3;  //The wind rotor, PI5, color ORANGE

struct buffer {
  int data[bsize];
  byte bptr;
  int total;
  int average;
};

struct buffer V2bf, V4bf;
int heading = 0;
int V2 = 0;
int V4 = 0;
int period=0;

void getHeading(){
  V2= analogRead(APin2);
  V4= analogRead(APin4);

  V2bf.total-=V2bf.data[V2bf.bptr];
  V2bf.data[V2bf.bptr]=V2;
  V2bf.total+=V2bf.data[V2bf.bptr];
  V2bf.average=V2bf.total/bsize;
  V2bf.bptr++;
  if (V2bf.bptr>=bsize) V2bf.bptr=0;
  V2=V2bf.average;

  V4bf.total-=V4bf.data[V4bf.bptr];
  V4bf.data[V4bf.bptr]=V4;
  V4bf.total+=V4bf.data[V4bf.bptr];
  V4bf.average=V4bf.total/bsize;
  V4bf.bptr++;
  if (V4bf.bptr>=bsize) V4bf.bptr=0;
  V4=V4bf.average;
  if (V2<=180){//1st quadrand, 1-90, based on V4
                // V4 takes values
                // it corresponds to a function of a line that passes from points (18,89) & (78,0)
                // see http://www.webmath.com/equline1.html
    heading=(-89.0/58*V4/10+3382.0/29);
  }
  if (V4<=220){  //2nd quadrand, 91-180, based on V2, passing from (18,90) & (76,179)
     heading=(89.0/58*V2/10+1809.0/29);
  }
  if (V2>=758){  //3rd quadrand, 181-270, based on V4, passing from (22,180) & (76,269)
    heading=(89.0/54*V4/10+3881.0/27);
  }
  if (V4>=758){  //4th quadrand, 271-360 based on V2, passing from (76,270) & (18,359)
    heading=(-89.0/57*V2/10+1166.0/3);
  }
  if (heading>=360) heading-=360;
  if (heading<0) heading+=360;
}
 
void pulse(){  //this runs when a pulse is received from the windmeter rotor
  static int msecs=0;
  int temp;
  temp=millis();
  period=temp-msecs;
  msecs=temp;
}
 
void setup() {
  lcd.begin(16,2);
  lcd.clear();
  lcd.print("WindMeter");
  FlexiTimer2::set(50, getHeading); // 50ms period
  pinMode (led,OUTPUT);
  attachInterrupt (1, pulse, FALLING);  // attach interrupt handler
  FlexiTimer2::start();
}
void loop() {
  lcd.clear();
  lcd.print("dir=");lcd.print(heading);
  lcd.setCursor (8,0);
  lcd.print("p=");lcd.print(period);
  lcd.setCursor (0,1);
  lcd.print("V2=");lcd.print(V2);
  lcd.setCursor (8,1);
  lcd.print("V4=");lcd.print(V4);
  delay(200);
Style-wise it could be better polished but function-wise I think it's fine.
It is completely Interrupt Driven (the main loop all it does is to display the readings), it handles smoothing of the analog values, it is a perfect base for I want to do next, which is to set the Arduino as a I2C slave device, connect it to the Raspberry and set up a high-level protocol for their communication.

But more on that next time!

Thanks for reading,

G.
 

PS
Using the NASA Masthead unit was a dog.
The analog values are not stable enough, they change along with the ambient temperature and the cup rotor only creates a single pulse per revolution. This is a low cost unit and it shows.
Nevertheless, if anyone is thinking of using it in a project, do drop a line, we might exchange notes!









No comments:

Post a Comment