(Help)Building a wind vane with a incremental optical encoder with index pulse

I have to build a meteorological statation for a university project, it must show wind speed and direction, temperature and humidity on a lcd display. I have already implemented a code that works with a mechanical rotary encoder(mouse wheel) , but when I trade it by the optical one it gives same reading for different shaft rotation speeds. Per exemple, if I spin it prety slow it gives 360 degrees in a quarter of circle and if I do it faster i have 160 degrees in a full turn.

The encoder is tamagawa FA-coder TS5314N 2500 C/T

I started to use arduino this semester in this specific subject, so don’t have much experience. I hope that you guys can help me.

I have annexed the data sheet(my encoder model is in the pages 12 and 13), the isolated code that i am using in the encoder and the entire code of the station (it can be usefull for someone with problems in another part of this kind of project).

Thanks for the attention :grinning: .

datasheet: http://www.tamagawa-seiki.com/pdf/download/1228N55EJ_shusei.pdf

(entire code)

#include <Encoder.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include "DHT.h"
#include <LiquidCrystal.h>
#define buttom1 13
#define DHTPIN 8
#define DHTTYPE DHT22 
#define PINA 2
#define PINB 4
#define INTERRUPT 0
volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
volatile boolean fired;
volatile boolean up;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12,11,7,6,5,10); 
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean lastlcd = true;
int b1 = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
int encoderStepsPerRevolution= 2500;
float angles=0;
float angle=0;

void isr ()
{
if (digitalRead (PINA))
  up = digitalRead (PINB);
else
  up = !digitalRead (PINB);
fired = true;
}

void setup() {
lcd.begin(16,2);
dht.begin();
lcd.setCursor(0,0);
lcd.print("meteorological");
lcd.setCursor(0,1);
lcd.print("station");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("MedTerm ENG03108");
delay(5000);
lcd.clear();
digitalWrite (PINA, HIGH);     // enable pull-ups
digitalWrite (PINB, HIGH); 
attachInterrupt (INTERRUPT, isr, CHANGE); 
attachInterrupt(1, rpm_fun, RISING);
  half_revolutions = 0;
  rpm = 0;
  timeold = 0;
Serial.begin(115200);
}

void rpm_fun()
{
  half_revolutions++;
  //Each rotation, this interrupt function is run twice
}

boolean debounce(boolean last)
{
 boolean current = digitalRead(buttom1);
 if (last != current)
 {
   currentMillis = millis();
if (currentMillis - previousMillis>=5){
 previousMillis=currentMillis;
 
   current = digitalRead(buttom1);
 }
 }
 return current;

}


void loop(){ 
  currentButton = debounce(lastButton);
 if (lastButton == LOW && currentButton == HIGH)
 {
   if (lastlcd) lastlcd = false;
   else lastlcd = true;
 }
 lastButton = currentButton;
 
  if (lastlcd)
 {
   
static long rotaryCount = 0;

if (fired)
  {
  if (up)
    rotaryCount++;
  else
    rotaryCount--;
  fired = false;
      }
      // end if fired
angles= 2*rotaryCount;
angle=abs(angles);
if (angle>=360)
{
 rotaryCount=0;
}

 if (half_revolutions >= 20) { 
    //Update RPM every 20 counts, increase this for better RPM resolution,
    //decrease for faster update
    rpm = 30*1000/(millis() - timeold)*half_revolutions;
    timeold = millis();
    half_revolutions = 0;
 }
{
char dirF[6]; 
char velF[6];
dtostrf(angle, 1, 3, dirF);
dtostrf(rpm, 1, 1, velF);
lcd.setCursor(0,0);
lcd.print("Dir: ");
lcd.print(dirF);
lcd.print((char)223);
lcd.print("        ");
lcd.setCursor(0,1);
lcd.print("Vel: ");
lcd.print(velF);
lcd.print("m/s  ");
}


 
}

else
{
 float temperature, humidity;

 humidity = dht.readHumidity();
 temperature = dht.readTemperature();
 
char tempF[6]; 
char humF[6];
dtostrf(temperature, 5, 2, tempF);
dtostrf(humidity, 2, 0, humF);
 
currentMillis = millis();
if (currentMillis - previousMillis>=2000){
 previousMillis=currentMillis;
 lcd.clear();
}

lcd.setCursor(0,0);
lcd.print("Temp: "); 
lcd.print(tempF);
lcd.print((char)223);
lcd.print("C ");
lcd.setCursor(0,1);
lcd.print("Humi: ");
lcd.print(humF);
lcd.print("%         ");
}
}

(Isolated encoder code)

#include "Arduino.h"
#include <digitalWriteFast.h>
#include <Encoder.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include <LiquidCrystal.h>
volatile boolean fired;
volatile boolean up;
LiquidCrystal lcd(12,11,7,6,5,10); 
float angles=0;
float angle=0;
#define PINA 2
#define PINB 4
#define PINC 9
#define INTERRUPT 0  // that is, pin 2

// Interrupt Service Routine for a change to encoder pin A
void isr ()
{
if (digitalRead (PINA))
  up = digitalRead (PINB);
else
  up = !digitalRead (PINB);
fired = true;
}  // end of isr


void setup ()
{
lcd.begin(16,2);
digitalWrite (PINA, HIGH);     // enable pull-ups
digitalWrite (PINB, HIGH); 
attachInterrupt (INTERRUPT, isr, CHANGE);   // interrupt 0 is pin 2, interrupt 1 is pin 3

Serial.begin (250000);
}  // end of setup

void loop ()
{
static long rotaryCount = 0;

if (fired)
  {
  if (up)
    rotaryCount++;
  else
    rotaryCount--;
  fired = false;
 float angles= ( rotaryCount%encoderStepsPerRevolution) * 360/encoderStepsPerRevolution;

  
  Serial.print ("Count = ");  
  lcd.setCursor(1,0);
  lcd.print (angle);

   angle= 0.144*rotaryCount;
if (angle>=360)
  {
   rotaryCount=0;
  }
  }  // end if fired
  

}  // end of loop

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

encoderisolado.ino (1.22 KB)

codigoestacao.ino (3.07 KB)

That is a very large datasheet. What pages are relevant to your problem?

...R

the relevant pages are 12 and 13. I kinda solve the problem using the tensy encoder library and the basic exemple contained in it, but I can’t return the angle to zero when it reaches 360 degrees using all the precision of the encoder it generete 10000 pulses per full turn (I don’t know how) . Thanks for the answer !

here is the new code:

with 1 degree of precision and reaching zero when the angle is =>0 360

#include <Encoder.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include "DHT.h"
#include <LiquidCrystal.h>
#define buttom1 13
#define DHTPIN 8
#define DHTTYPE DHT22 
#define PINA 2
#define PINB 4
#define INTERRUPT 0
volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12,11,7,6,5,10); 
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean lastlcd = true;
int b1 = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;

float angles=0;
float angle=0;
Encoder myEnc(2,4);
int encoderStepsPerRevolution= 10000;

void setup() {
lcd.begin(16,2);
dht.begin();
lcd.setCursor(0,0);
lcd.print("meteorological");
lcd.setCursor(0,1);
lcd.print("station");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("MedTerm ENG03108");
delay(5000);
lcd.clear();
attachInterrupt(1, rpm_fun, RISING);
   half_revolutions = 0;
   rpm = 0;
   timeold = 0;
Serial.begin(115200);
}

void rpm_fun()
 {
   half_revolutions++;
   //Each rotation, this interrupt function is run twice
 }

boolean debounce(boolean last)
{
  boolean current = digitalRead(buttom1);
  if (last != current)
  {
    currentMillis = millis();
 if (currentMillis - previousMillis>=5){
  previousMillis=currentMillis;
  
    current = digitalRead(buttom1);
  }
  }
  return current;

}

long oldPosition  = -999;

void loop(){ 
   currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    if (lastlcd) lastlcd = false;
    else lastlcd = true;
  }
  lastButton = currentButton;
  
   if (lastlcd)
  {
    long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
 angles= (newPosition % encoderStepsPerRevolution) * 360/encoderStepsPerRevolution;
  angle=abs(angles);
  }
  
    


  if (half_revolutions >= 20) { 
     //Update RPM every 20 counts, increase this for better RPM resolution,
     //decrease for faster update
     rpm = 30*1000/(millis() - timeold)*half_revolutions;
     timeold = millis();
     half_revolutions = 0;
  }
 {
char dirF[6]; 
 char velF[6];
 dtostrf(angle, 1, 3, dirF);
 dtostrf(rpm, 1, 1, velF);
 lcd.setCursor(0,0);
 lcd.print("Dir: ");
 lcd.print(dirF);
 lcd.print((char)223);
 lcd.print("        ");
 lcd.setCursor(0,1);
 lcd.print("Vel: ");
 lcd.print(velF);
 lcd.print("m/s  ");
}


  
}

else
{
  float temperature, humidity;

  humidity = dht.readHumidity();
  temperature = dht.readTemperature();
  
 char tempF[6]; 
 char humF[6];
 dtostrf(temperature, 5, 2, tempF);
 dtostrf(humidity, 2, 0, humF);
  
 currentMillis = millis();
 if (currentMillis - previousMillis>=2000){
  previousMillis=currentMillis;
  lcd.clear();
 }
 
 lcd.setCursor(0,0);
 lcd.print("Temp: "); 
 lcd.print(tempF);
 lcd.print((char)223);
 lcd.print("C ");
 lcd.setCursor(0,1);
 lcd.print("Humi: ");
 lcd.print(humF);
 lcd.print("%         ");
}
}

and with full precision but with infinite angle (I couldn’t solve it yet).

#include <Encoder.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include "DHT.h"
#include <LiquidCrystal.h>
#define buttom1 13
#define DHTPIN 8
#define DHTTYPE DHT22 
#define PINA 2
#define PINB 4
#define INTERRUPT 0
volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12,11,7,6,5,10); 
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean lastlcd = true;
int b1 = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;

float angles=0;
float angle=0;
Encoder myEnc(2,4);
int encoderStepsPerRevolution= 10000;

void setup() {
lcd.begin(16,2);
dht.begin();
lcd.setCursor(0,0);
lcd.print("meteorological");
lcd.setCursor(0,1);
lcd.print("station");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("MedTerm ENG03108");
delay(5000);
lcd.clear();
attachInterrupt(1, rpm_fun, RISING);
   half_revolutions = 0;
   rpm = 0;
   timeold = 0;
Serial.begin(115200);
}

void rpm_fun()
 {
   half_revolutions++;
   //Each rotation, this interrupt function is run twice
 }

boolean debounce(boolean last)
{
  boolean current = digitalRead(buttom1);
  if (last != current)
  {
    currentMillis = millis();
 if (currentMillis - previousMillis>=5){
  previousMillis=currentMillis;
  
    current = digitalRead(buttom1);
  }
  }
  return current;

}

long oldPosition  = -999;

void loop(){ 
   currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    if (lastlcd) lastlcd = false;
    else lastlcd = true;
  }
  lastButton = currentButton;
  
   if (lastlcd)
  {
    long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
 angles= 0.036*newPosition;
  angle=abs(angles);
  if (angle>=360)
  {
    newPosition=0;
    }
  }
  
  
    


  if (half_revolutions >= 20) { 
     //Update RPM every 20 counts, increase this for better RPM resolution,
     //decrease for faster update
     rpm = 30*1000/(millis() - timeold)*half_revolutions;
     timeold = millis();
     half_revolutions = 0;
  }
 {
char dirF[6]; 
 char velF[6];
 dtostrf(angle, 1, 3, dirF);
 dtostrf(rpm, 1, 1, velF);
 lcd.setCursor(0,0);
 lcd.print("Dir: ");
 lcd.print(dirF);
 lcd.print((char)223);
 lcd.print("        ");
 lcd.setCursor(0,1);
 lcd.print("Vel: ");
 lcd.print(velF);
 lcd.print("m/s  ");
}


  
}

else
{
  float temperature, humidity;

  humidity = dht.readHumidity();
  temperature = dht.readTemperature();
  
 char tempF[6]; 
 char humF[6];
 dtostrf(temperature, 5, 2, tempF);
 dtostrf(humidity, 2, 0, humF);
  
 currentMillis = millis();
 if (currentMillis - previousMillis>=2000){
  previousMillis=currentMillis;
  lcd.clear();
 }
 
 lcd.setCursor(0,0);
 lcd.print("Temp: "); 
 lcd.print(tempF);
 lcd.print((char)223);
 lcd.print("C ");
 lcd.setCursor(0,1);
 lcd.print("Humi: ");
 lcd.print(humF);
 lcd.print("%         ");
}
}

with 1 degree of precision and reaching zero when the angle is =>0 360 and with full precision but with infinite angle (I couldn't solve it yet).

I am not clear on your problem, but I think you are talking about these two pieces of your code

if (lastlcd)
  {
    long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
 angles= (newPosition % encoderStepsPerRevolution) * 360/encoderStepsPerRevolution;
  angle=abs(angles);
  }
if (lastlcd)
  {
    long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
 angles= 0.036*newPosition;
  angle=abs(angles);
  if (angle>=360)
  {
    newPosition=0;
    }
  }

Why do you think there is a difference in precision? I think that the modulo math to calculate angles in the first snippet resolves to the same math as in the second case.

I can not be correct to set newPosition to zero in the second case, as you will loose reference to the original zero position which is usually due North.

I'm not sure that angle = abs(angles) is correct. For example if you have moved 1/4 turn + from zero(North) you will be +90 degrees(East), and if you have moved 1/4 turn - from zero you will be -90 degrees(West). You don't want these both to be 90, but one should be 90 and the other 270. If angles is negative, I think that you want angle to be 360 - abs(angles).

pedrobs66: it generete 10000 pulses per full turn

Where did you get that figure?

On page 13 I see 100~2500C/T

...R

Robin is correct about the 2500 figure, but it is never clear whether or not that refers to the full quadrature counts, or the number of pulses per channel. I would be more inclined to think that the 2500 is when all the four available quadrature pulses are read.

The way you are using encoder.h with only one interrupt pin, I think that you may only be reading 1250 counts per revolution.

You really need to do some simple and isolated testing of the encoder to see what you have, and how the library is treating the encoder pulses.

Here is some very simple and robust code for reading all 4 available transitions. You might want to give it a try instead of the library. It uses two interrupts and A/B should go to pins D2 and D3.

const char encTable[16] = {0, 1, -1, 0, -1, 0, -0, 1, 1, 0, 0, -1, 0, -1, 1, 0}; //gives -1, 0 or 1 depending on encoder movement
volatile long encoderCount;
volatile long errorCount;
volatile byte encState;
unsigned long prevDisplay;
unsigned long interval = 1000;

void setup() {
  Serial.begin(115200);
  attachInterrupt(0, readEnc, CHANGE);
  attachInterrupt(1, readEnc, CHANGE);
}

void loop() {
  if (millis() - prevDisplay >= interval)
  {
    prevDisplay += interval;
    noInterrupts();
    long copyEncoderCount = encoderCount;
    encoderCount = 0;
    long copyErrorCount = errorCount;
    errorCount = 0;
    interrupts();
    
    Serial.print(copyEncoderCount);
    Serial.print('\t');
    Serial.println(copyErrorCount);
  }
}

void readEnc() {
  encState = ((encState << 2) | ((PIND >> 2) & 3)) & 15; //use encoder bits and last state to form index
  encoderCount += encTable[encState];//update actual position on encoder movement
  if(encTable[encState] == 0)
     errorCount++;
}

I tried with one more robust code, first with one interrupt then with both, but it generate the problem that I describe in my first post: one slow turn gives much more pulses than a fast one. With the library the problem has been solved, I atached a piece of duct tape on the shaft, draw a smal reference point on the encoder and turn it several times at different speeds, the results were basically the same all the time, around 10000 counts. Yesterday I saw a post here where the same library was used on a 1024 C/T encoder and , when attached to the arduino, it generated 4096 counts.

Here's the page from the library:http://www.pjrc.com/teensy/td_libs_Encoder.html

Are you using the 220 ohm pull up resistors on the data lines as shown in the data sheet?

What arduino model are you using? Or is it a Teensy?

Cattledog, the first code gives one degree of resolution while the second one gives 0.036(it's slightly usuless and unrealistic for one mechanical wind vane made from scrap,so i gonna stick with one degree), that if (newPosition>=360) comand doesn't work (the angle keeps incrementing independent of it being satisfied or not) and my objective was avoid readings like 900,1080,2000 degrees and etc. About the abs(angles)...It was a mistake, I was with an fixed idea about one of that big arrows present in the wind vanes indicating the direction and had forgotten that I've to show the wind direction only by data displayed on an LCD, I will change the code. Thanks for the advices.

It's an arduino UNO and I didn't saw that pull up resistor there, it was lack of attention of mine... sorry =|

Would you please test the code I gave you with the pull up resistors. There is no way it will miss pulses, and I have tested it to very high pulse rates. It has bench marked as the fastest code I have seen.

If you are using a UNO, then I don't see how the library can be giving the full quadrature counts because it is not on two interrupt pins, and it should give you half the resolution. If indeed it is giving 10000 counts/rev then it can not be optimized for speed as it will be polling pin 4 in the loop.

#define PINA 2
#define PINB 4

so i gonna stick with one degree

Good idea. In fact, the 5000 counts/rev should give you plenty of resolution, but you will have to change the declaration or the math will be wrong./

int encoderStepsPerRevolution= 10000;
angles= (newPosition % encoderStepsPerRevolution) * 360/encoderStepsPerRevolution;

I will buy the 220 ohm resistors monday and try your code =). This week I will build the the entire structure, calibrate the anemometer, refine the calibration of dht22 sensor, cross my fingers and hope that everything works well.

This is the code I’m using until the moment, after try cattledog’s code I will decide what going to do with the angle(I’ve added cardial directions to it). I’ve changed the encoder pins for use two interrupts and still have the same C/T with this library.

#include <Encoder.h>                  //including all libraries
#define ENCODER_OPTIMIZE_INTERRUPTS
#include "DHT.h"
#include <LiquidCrystal.h>
#define buttom1 13
#define DHTPIN 8
#define DHTTYPE DHT22 
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12,11,7,6,5,10); 
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean lastlcd = true;
const int hallPin=9;
const unsigned long sampleTime=1000;
int b1 = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
float angles=0;
int angle=0;
Encoder myEnc(2,3); // teensy lib
int encoderStepsPerRevolution= 10000;
int getRPM()
{
  // sample for sampleTime in millisecs
  int kount=0;
  boolean kflag=LOW;
  unsigned long currentTime=0;
  unsigned long startTime=millis();
  while (currentTime<=sampleTime)
  {
    if (digitalRead(hallPin)==HIGH)
    {
      kflag=HIGH;
    }
    if (digitalRead(hallPin)==LOW && kflag==HIGH)
    {
      kount++;
      kflag=LOW;
    }
    currentTime=millis()-startTime;
  }
  int kount2rpm = int(60000./float(sampleTime))*kount;
  return kount2rpm;
}
void setup() {
lcd.begin(16,2);
dht.begin();
lcd.setCursor(0,0);
lcd.print("meteorological");
lcd.setCursor(0,1);
lcd.print("station");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("MedTerm ENG03108");
pinMode(hallPin,INPUT);
delay(5000);
lcd.clear();
Serial.begin(115200);
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(buttom1); //button debounce without delay
  if (last != current)
  {
    currentMillis = millis();
 if (currentMillis - previousMillis>=5){
  previousMillis=currentMillis;
  
    current = digitalRead(buttom1);
  }
  }
  return current;

}

long oldPosition  = -999;

void loop(){ 
  int rpm=getRPM();
   currentButton = debounce(lastButton);  //saving last button state
  if (lastButton == LOW && currentButton == HIGH)
  {
    if (lastlcd) lastlcd = false;
    else lastlcd = true;
  }
  lastButton = currentButton;
  
   if (lastlcd)
  {
    long newPosition = myEnc.read(); //wind direction acquisition
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
 angles= (newPosition % encoderStepsPerRevolution) * 360/encoderStepsPerRevolution;
  angle=abs(angles);
  }
 {
char dirF[6]; 
 char velF[6];
 dtostrf(angle, 1, 0, dirF);
 dtostrf(rpm, 1, 1, velF);
 lcd.setCursor(0,0);
 lcd.print("Dir: ");
 lcd.print(dirF);
 lcd.print((char)223);
 lcd.print("  ");
 lcd.setCursor(0,1);
 lcd.print("Vel: ");
 lcd.print(velF);
 lcd.print("m/s  ");
 lcd.setCursor(9, 0);                
 
   if ((angle)<23) {
    lcd.print(" N  ");
    } 
   if ((angle>22) && (angle<68)) {
    lcd.print("NE  ");
    } 
   if ((angle>67) && (angle<113)) {
    lcd.print(" E");
    } 
   if ((angle>112) && (angle<158)) {
    lcd.print("SE  ");
    } 
   if ((angle>157) && (angle<203)) {
    lcd.print(" S  ");
    } 
    if ((angle>202) && (angle<247)) {
    lcd.print("SW  ");
    } 
    if ((angle>246) && (angle<292)) {
    lcd.print(" W  ");
    } 
    if ((angle>291) && (angle<337)) {
    lcd.print("NW  ");
    } 
    if ((angle>336) && (angle<=360)) {
    lcd.print(" N  ");
    } 
}
  }

else
{
  float temperature, humidity;

  humidity = dht.readHumidity();
  temperature = dht.readTemperature();
  
 char tempF[6]; 
 char humF[6];
 dtostrf(temperature, 5, 2, tempF);
 dtostrf(humidity, 2, 0, humF);
  
 currentMillis = millis();
 if (currentMillis - previousMillis>=2000){
  previousMillis=currentMillis;
  lcd.clear();
 }
 
 lcd.setCursor(0,0);
 lcd.print("Temp: "); 
 lcd.print(tempF);
 lcd.print((char)223);
 lcd.print("C ");
 lcd.setCursor(0,1);
 lcd.print("Humi: ");
 lcd.print(humF);
 lcd.print("%         ");
}
}

and here is the basic example used as basis.

/* Encoder Library - Basic Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(5, 6);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}