Wind Direction Using a HRPG AS16#51C Rotary encoder

Hi,

I am looking for help/advice, I am hoping to use a keysight technoligies HRPG AS16#51c rotary encoder, for a sixteen point wind direction sensor, for my weather station.

It uses quadrature digital output and is a 16cpr smooth running device, No detents

I have connected it to a arduino UNO and have used sketch "InteruptRotator" created by Matthias Hertel. which works well, showing 16 positions for 1 rotation which is what I want, but if I go past the 1st rotation on 2, 3, 4, rotations it counts on 16-17-18-19-20 and so on.

As I want the the 16 positions to represent the 16 different points on a compass ie eg pos 0 = N, 1 = NNE, 2 = NE and so on, how/can I, using a sketch stop it counting past position 15 so you get this :

rotation 1 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, rotation 2 = 0, 1, 2, 3, 4, 5, and so on.

I hope it can be done, at present I am using a sensor based on using reed switches, which is ok, but I would like to if can be done, use the above encoder, so it will hopefully be more accurate.

Any help and advise will be greatly appreciated,

regards

martyn

try modulus operator direction=counts%16

Hi again,

Thankyou for your reply racpi.

I am wondering were abouts in the sketch, should modulus operator, "direction=counts%16" be placed, as I am very new to the arduino scene, and I have NO programming experiance.

This is all very new to me and very bewildering. and I am at present finding it hard to get an understanding of how it works. So please be patient with me.

Regards

tyntop

Hi,

Here is the sketch that i am working with at the moment.

// -----
// InterruptRotator.ino - Example for the RotaryEncoder library.
// This class is implemented for use with the Arduino environment.
// Copyright (c) by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
// More information on: http://www.mathertel.de/Arduino
// -----
// 18.01.2014 created by Matthias Hertel
// -----

// This example checks the state of the rotary encoder in the loop() function.
// The current position is printed on output when changed.

// Hardware setup:
// Attach a rotary encoder with output pins to A2 and A3.
// The common contact should be attached to ground.

#include <RotaryEncoder.h>

// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);

void setup()
{
  Serial.begin(57600);
  Serial.println("SimplePollRotator example for the RotaryEncoder library.");

  // You may have to modify the next 2 lines if using other pins than A2 and A3
  PCICR |= (1 << PCIE1);    // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
  PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // This enables the interrupt for pin 2 and 3 of Port C.
} // setup()



// The Interrupt Service Routine for Pin Change Interrupt 1
// This routine will only be called on any signal change on A2 and A3: exactly where we need to check.
ISR(PCINT1_vect) {
  encoder.tick(); // just call tick() to check the state.
}


// Read the current position of the encoder and print out when changed.
void loop()
{
  static int pos = 0;

  int newPos = encoder.getPosition();
  if (pos != newPos) {
    Serial.print(newPos);
    Serial.println();
    pos = newPos;

    // Just to show, that long lasting procedures don't break the rotary encoder:
    // When newPos is 66 the ouput will freeze, but the turned positions will be recognized even when not polled.
    // The interrupt still works.
    // The output is correct 6.6 seconds later.
    if (newPos == 66)
      delay(6600);
  } // if
} // loop ()

// The End

hope this is of use

regards

tyntop

InterruptRotator.ino (2 KB)

Serial.print(newPos%16);

the arduino has a rotary encoder library that might work better for you
#include <Encoder.h>
Encoder windvane(A2, A3);

newPos = windvane.read();

whats this about

// The output is correct 6.6 seconds later.
if (newPos == 66)
delay(6600);

it seems very unnecessary

this might interest you too

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}
const char  wd[][4]={{" N "},{"NNE"},{" NE"},{"ENE"},{" E "},{"ESE"}, {" SE"},{"SSE"},{" S "},{"SSW"}, {" SW"},{"WSW"},{" W "},{"WNW"}, {" NW"},{"NNW"}};
void loop() {
  static int i=0;
  // put your main code here, to run repeatedly:
 Serial.println(wd[i++%16]);
 delay( 500);
}

Hi racpi,

thanks for the replies,

with regards to “whats this about” above, that was already in the sketch when I downloaded it.

the suggestions you have made I thank you for, but like i have already said above I am bewildered by these sketches, so is there any chance that you could put together a sketch that you think would work. which I could then give you feedback on how I get on.

hope you dont mind me asking.

thanks again
tyntop.

I trust you will use this as a learning experience

#include <Encoder.h>
Encoder windvane(A2, A3);
void setup() {
  Serial.begin(9600);
}
int old_pos = windvane.read();
const char  wd[][4] = {{" N "}, {"NNE"}, {" NE"}, {"ENE"}, {" E "}, {"ESE"}, {" SE"}, {"SSE"}, {" S "}, {"SSW"}, {" SW"}, {"WSW"}, {" W "}, {"WNW"}, {" NW"}, {"NNW"}};
void loop() {
  int i = windvane.read();;
  i = windvane.read();
  if (i != old_pos) {
    Serial.println(wd[abs(i % 16)]);
    old_pos = windvane.read();
  }
}

Hi racpi,

Thankyou so much for your help, it is so much appreciated.

It is and will be used as a learning experience, now I've had a few pointers, I'm a bit happier and hopefully can start to work things out for myself.

thanks again

Regards

tyntop

I have compiled and run the above sketch but there is 1 problem. for 1 rotation of the encoder I am getting 4 sets of compass points when I only want 1. I have tried changeing some numbers in the sketch but that has not made any difference.

I am thinking that the use of interrupts is required

Am i right in that thinking ?

regards

tyntop

I am thinking that the use of interrupts is required

encoder.h does use interrupts
your encoder is 16 cpr the encoder library is a full ppr edge count therefore counts 64 edges per rev
try
Serial.println(wd[abs(i % 64)/4]);

AGAIN THANKYOU,

will try this out this evening as I have a full day ahead, I will let you know how I get on .

regards tyntop.

Why the abs and modulus? This is simpler, faster, and does the job.

Serial.println(wd[i & 0x0F]);

edit: ...and if it is 0 to 63 converted to 0 to 15 that you are looking for...

Serial.println(wd[(i & 0x3F) >> 2]);

Hi,

I have tried some of the amendments to the above sketch and now I am getting 4x each compass point eg ;N,N,N,N, NNE,NNE,NNE,NNE, NE,NE,NE,NE, and so on which for my purposes is usable although I would like to get it down to 1 of each per 1 rotation if possible, so will keep working on it,.

A big thankyou to the responders of this topic they have have helped me out enormously, any further hints will still be welcome.

regards

tyntop.

your encoder has 64 positions per rotation , they are divided into 16 cardinal points ,so yes each cardinal point has 4 positions . if your objective is to display current wind direction why do you think is this a problem ? if you only require an output when a cardinal position change occurs ,then modify the "i" variable to store the cardinal position rather than the actual position keep in mind that your encoder has no index output , this means its vital not to miss any encoder counts or else the indicated direction will drift

Hi, I have read post 14 and I think I understand what you are saying so point taken.

Is there any chance racpi that you can help me some more ?

I have already built a weather station which up and running, it is a station using hardware/sensors which as far as i can tell are the same as ones used in the sparkfun weather station. I am hoping to upgrade the Windvane and Anemometer which at present use reed switches.

Anemometer I think I have sorted out as the upgrade I want do, is to use hall effect sensors, this Mod has been allowed for in the software that I am using, from what I can gather there are no changes required to the software, you can correct me if I am wrong

Windvane ; I am hoping to use the "HRPG AS16#51C Rotary encoder that you have helped me sort out a sketch for. My problem now is to intergrate this sketch into the software that I am using.

The weather station is based on the "Weatherduino Pro2" which can be found at this web site,

http://www.meteocercal.info/forum/index.php

The software and info can be found there but the person who has done all the work is to busy to help me out with windvane mod/upgrade that I am hoping to do there are 2 parts to the software TX and RX so I dont weather I only need to make changes just to the Tx software or both.

So I am hoping that you willing and able to help me in this task.

Greatest Regards

tyntop

I don't think a hrpg as series re is particularly suited for remote weather station use for a number of reasons 1 .Supply Current ICC up to 40 mA , this will eat batteries 2. its not weather proof 3 . its not indexed 4 . its an incremental device , an absolute output is far more suitable 5. It may not play well with other software if interrupts are involved the link you posted for weather station software requires a login , I can't even look at it ,sorry

Hi,
Thankyou for the reply, I have taken on board what you have said, I was only going to use that sensor because I got it fairly cheaply, so I would like to try it. in the meantime I will will look for the type of encoder that you suggest, have you you any suggetions, preferably as cheap as possible.

sorry about the link sent I didnt think about the login side of things.

I have attached a zip file of the sofware for you to have a look at.

regards

tyntop

martyn.

WeatherDuino_Pro2_v013_20150321.zip (669 KB)

the weatherduino code uses a fineoffset sensor in the silicon chip article I read

http://www.ebay.com.au/itm/Spare-part-for-weather-station-to-test-the-wind-direction-Sensor-Wetterstation-/271845218193?pt=LH_DefaultDomain_146&hash=item3f4b3cd791

it would be difficult to find better value , even if you made your own

this appears to be the relevant wind vane code that needs to be adjusted

double getWindVane()




{




//  analogReference(DEFAULT);      // Restore analogRef to 5V default




  digitalWrite(VANE_PWR,HIGH);




  delay(100);




  for(int n=0;n<10;n++)           // apenas manda fora as primeiras 10 leituras




  {




    analogRead(VANE_PIN);




  }





  unsigned int reading = analogRead(VANE_PIN);





  digitalWrite(VANE_PWR,LOW);




  unsigned int lastDiff=2048;





 for (int n=0; n < 16; n++)




 {




   int diff =reading - pgm_read_word(&vaneValues[n]);




   diff =abs(diff);




   if(diff == 0)




   {




      return pgm_read_word(&vaneDirections[n]);




   }




 




    if(diff > lastDiff)




    {




      return pgm_read_word(&vaneDirections[n-1]);




    }





    lastDiff = diff;  




  }




      return pgm_read_word(&vaneDirections[15]); 




}

you could try this mod to the getWindVane function , I don’t see why it would not work

double getWindVane(){
int n=(windvane.read()&3f)/4;
return pgm_read_word(&vaneDirections[n]);
}