Rotary Encoder

CrossRoads: It's this one http://www.digikey.com/product-detail/en/PEC12R-2125F-N0012/PEC12R-2125F-N0012-ND/4499641 with the filter circuit on page 2 of its drawing http://www.bourns.com/data/global/pdfs/PEC12R.pdf

OK, that's a simple mechanical rotary encoder which creates less (when new) or more (when old and worn out) bouncing while rotating.

All code linked in the playground that uses hardware or pinchange interrupts will lead to less or more crappy results.

The filter circuit will make things better, because that helps preventing bouncing and less bouncing helps crappy code in working better with such encoders.

I'd strongly suggest either polling such encoders or use timer interrupts.

Polling of rotary encoders would be suitable, if the loop function is always running at a high speed with no blocking times and no slow operations, let's say the loop function never takes more than one or two milliseconds to complete. In that case: Just poll the inputs of the rotary encoder and count accordingly to the state up and down.

The other possibility would be the usage of timer interrupts. Set up a timer that generates let's say 500 or 1000 interrupts per second. Then in the interrupt handling read the inputs and count accordingly to the state up and down.

How many of such encoders would you like to use in the application? Just one? More than one (how many total)? Would polling be applicable to your application (loop functions always faster than 2ms)? Or do you have a timer left that could be used for the rotary encoder(s)?

I always had good results with this one:

Ben Buxton's rotary encoder page.

Ian.

I just have the one, nothing else going on until a number is selected, after which the encoder is ignored.

I’ll take a look at the Ben Buxton page too when I get home.

Thanks.

Here is code I wrote to test use and encoder for setting date/time on an RTC prior to including in my WordClock.

#include <Wire.h>
#include <RealTimeClockDS3231.h>

//Enumerations
const int eHours = 0;
const int eMinutes = 1;
const int eDay = 2;
const int eMonth = 3;
const int eYear = 4;
const int eDOW = 5;

//Constants
const int encButton = 5;                         //Rotary Encoder button pin (11)
const int encoder0PinA = 6;                      //Rotary Encoder A pin (12)
const int encoder0PinB = 7;                      //Rotary Encoder B pin (13)

const long debounceDelay = 90;                   //Button debounce time
const long adjustDelay = 10000;                  //10 Second Adjust timeout

//Globals
char formatted[] = "0000-00-00 00:00:00x";

void setup() {
  //  Wire.begin();
  pinMode (encoder0PinA,INPUT);
  digitalWrite(encoder0PinA,HIGH);               //Enable pullup resistor
  pinMode (encoder0PinB,INPUT);
  digitalWrite(encoder0PinB,HIGH);               //Enable pullup resistor
  pinMode (encButton,INPUT);                     //Encoder button is set to input
  Serial.begin(9600);
}

void loop() {
  long loopTime = millis();                 //Read timer
  int mainDelay = 1000;                      // Default main loop delay

  while ((millis() - loopTime) < mainDelay) {

    if (checkButton(encButton)){
      while (checkButton(encButton)){             //Wait for button to be released
      };
      delay(100);
      digitalWrite(13, HIGH);   // set the LED on
      //Serial.println("Button On");
      eAdjust();
      //Serial.println("Button Off");
      digitalWrite(13, LOW);   // set the LED on
    }

  }

  RTC.readClock();				 //Read the current date and time
  RTC.getFormatted2k(formatted);
  Serial.println(formatted);
}

// Called from main loop when encoder button pressed
void eAdjust(){
  RTC.readClock();				  //Read the current date and time
  int value = readEncoder();                      //Init encoder readback value and prime encoder sub (result discarded)
  int eMode = eHours;                             //Set mode to eHours
  doDisplay(eMode);                               //Display Hours

  long eTime = millis();			  //Get current CPU time for adjust loop timeout
  while ((millis() - eTime) < adjustDelay) {

    if (checkButton(encButton)){                  //Is encoder button pressed?
      // Mode button pressed
      //Serial.println("Button Pressed");
      while (checkButton(encButton)){             //Wait for button to be released
      };
      delay(100);                                 //Slight delay to allow for button debounce
      //Serial.println("Button Released");
      eMode++;				          //Increment mode
      if (eMode > eDOW){                          //End of modes?
        // Mode cycled past end
        RTC.setSeconds(0);                        //Zero seconds
        RTC.setClock();                           //Set the clock
        //Serial.println("Mode Exit");
        return;                                   //Return
      }
      RTC.getFormatted2k(formatted);
      Serial.println(formatted);
      doDisplay(eMode);		                  //Display the new mode
      eTime = millis();		                  //Reset adjust loop timout
    }

    if (millis() % 10 == 0){                      //Only read every 10mS
      int result = readEncoder();                 //Read encoder. Returns -1,0,1
      //Serial.print("Encoder: ");
      if (!result == 0){			  //Encoder <> 0
        //Encoder wheel was turned
        //Serial.print("Encoder Turned");
        switch (eMode){
        case eHours:                              //Mode eHours
          value = RTC.getHours() + result;        //Read hours and add encoder direction
          RTC.setHours(value % 24);               //Store new hours after legalizing
          break;                                  //No further processing
        case eMinutes:
          value = RTC.getMinutes() + result;
          RTC.setMinutes(value % 60);
          break;
        case eDay:
          value = RTC.getDate() + result;
          RTC.setDate(value % 31);
          break;
        case eMonth:
          value = RTC.getMonth() + result;
          RTC.setMonth(value % 12);
          break;
        case eYear:
          value = RTC.getYear() + result;
          RTC.setYear(value % 99);
          break;
        case eDOW:
          value = RTC.getDayOfWeek() + result;
          RTC.setDayOfWeek(value % 7);
          break;
        default:                                  //What to do if mode unknown
          break;                                  //Nothing
        }
        doDisplay(eMode);                         //Display new mode
        eTime = millis();                         //Reset adjust loop timout
      }
    }
  }
  //Timed out
  //RTC.setClock();
  Serial.println("Timeout");
}

void doDisplay(int Mode){                         //Display relevent data for given mode
  Serial.print("Mode ");
  Serial.print(Mode);
  Serial.print(": ");
  switch (Mode){
  case eHours:
    Serial.println(RTC.getHours());
    break;
  case eMinutes:
    Serial.println(RTC.getMinutes());
    break;
  case eDay:
    Serial.println(RTC.getDate());
    break;
  case eMonth:
    Serial.println(RTC.getMonth());
    break;
  case eYear:
    Serial.println(RTC.getYear());
    break;
  case eDOW:
    Serial.println(RTC.getDayOfWeek());
    break;
  default:
    break;
  }
}	

// Button = pin number to read
int checkButton(int Button) {
  int buttonState = digitalRead(Button);          // Read button
  if (buttonState == HIGH) {                      // If button pressed then wait a bit to allow for debounce
    long Time = millis(); 
    while ((millis() - Time) < debounceDelay) {    
    }
    buttonState = digitalRead(Button);            // Read button again
    return buttonState;                           // Return button state
  }
  else {                                          //Button not pressed so no need to wait for bebounce
    return LOW;
  }
}

int readEncoder() { 
  static int encoder0PinALast = LOW;
  int eDir = 0;
  int n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      eDir = -1;
      //Serial.print("-1");
    } 
    else {
      eDir = 1;
      //Serial.print("1");
    }
  } 
  encoder0PinALast = n;
  //Serial.println(eDir);
  return eDir;
}

Here is a example using polling with debounced digital read of the pins. It is designed to read every quadrature change. If your encoder has detents at every change, it will work. If the detents are not at every change, the code can be modified to increment/decrement only in the detent positions. The encoder you referenced has different options for the detents.

//Based on code from: http://bildr.org/2012/08/rotary-encoder-arduino/
//uses quadrature bit pattern from current and previous reading

//Changes
//Polled rather than interrupts
//Added start up position check to make index +1/-1 from first move
//Add bounce2 and debounce of digitalReads

#define encoderPinA  3  
#define encoderPinB  2
#define buttonPin 5

#include <Bounce2.h>
// Instantiate three Bounce objects for all pins with digitalRead
Bounce debouncerA = Bounce(); 
Bounce debouncerB = Bounce(); 
Bounce debouncer5 = Bounce();

int lastEncoded = 0;
int encoderValue = 0;
int lastencoderValue = 0;

void setup() {
  Serial.begin (115200);

  pinMode(encoderPinA, INPUT_PULLUP); 
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);

  debouncerA.attach(encoderPinA);
  debouncerA.interval(5);
  debouncerB.attach(encoderPinB);
  debouncerB.interval(5);
  debouncer5.attach(buttonPin);
  debouncer5.interval(5);

  //get starting position
  debouncerA.update();
  debouncerB.update();

  int lastMSB = debouncerA.read(); 
  int lastLSB = debouncerB.read(); 

  Serial.print("Starting Position AB  " );
  Serial.print(lastMSB);
  Serial.println(lastLSB);

  //let start be lastEncoded so will index on first click
  lastEncoded = (lastMSB << 1) |lastLSB;

}

void loop(){ 

  debouncerA.update();
  debouncerB.update();

  int MSB = debouncerA.read();//MSB = most significant bit
  int LSB = debouncerB.read();//LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin values to single number

  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  //test against quadrature patterns CW and CCW
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

  lastEncoded = encoded; //store this value for next time

  if(encoderValue != lastencoderValue){
    Serial.print("Index:  ");
    Serial.print(encoderValue);
    Serial.print('\t');

    Serial.print("Old-New AB Pattern:  ");

    for (int i = 3; i >= 0; i-- )
    {
      Serial.print((sum >> i) & 0X01);//shift and select first bit
    }

    Serial.println();

    lastencoderValue=encoderValue;
  }

  //reset index
  debouncer5.update();
  if(debouncer5.read()==LOW){
    encoderValue=0;
  }

}

CrossRoads:
I just have the one, nothing else going on until a number is selected, after which the encoder is ignored.

Here is a little ‘poor mans library for rotary encoders’, which requires no library installation.
Supports: As many rotary encoders as you like (or let’s say max. 6 without speed improvements)
Requires: Timer2 to generate 1000 timer interrupts per second
Inner working: Reads and evaluates the pin states during timer interrupts

Here is the example sketch and how to use:

// rotary encoder demo by 'jurs' for Arduino Forum
// This is the code for the main "sketch"

#include "encoder.h"
#define BAUDRATE 115200L // serial baud rate

void setup() {
  Serial.begin(BAUDRATE);
  Serial.println();
  Serial.println("Good night and good luck!"); // print some Test-Message at beginning
  beginEncoders();
}

void printEncoders()
{ // print current count of each encoder to Serial
  for (int i=0; i<NUMENCODERS; i++)
  {
    Serial.print(encoder[i].count);
    Serial.print('\t');
  }
  Serial.println();
}

void loop() {
  if (updateEncoders()) printEncoders();
}

The library is just a file for a new “Tab”. Create a “Tab” named “encoder.h” and copy this code into the Tab:

// rotary encoder include file by 'jurs' for Arduino Forum
// This is the code for a new "Tab" within the sketch with Tab name "encoder.h"
#include <Arduino.h>
struct rotary_t {byte pinA; byte pinB; int count;};

rotary_t encoder[]={
 {8,9}, 
};  

#define NUMENCODERS (sizeof(encoder)/sizeof(encoder[0]))

volatile byte state_ISR[NUMENCODERS];
volatile int8_t count_ISR[NUMENCODERS];

void startTimer2()  // start TIMER2 interrupts
{
  noInterrupts();
  // Timer 2 CTC mode
  TCCR2B = (1<<WGM22) | (1<<CS22)  | (1<<CS20);
  TCCR2A = (1<<WGM21);
  OCR2A = 124;   // 249==500,  124==1000 interrupts per second
                 // 63 ==2000,  31==4000
                 // 15 ==8000,   7==16000
  TIMSK2 = (1<<OCIE2A); // enable Timer 2 interrupts
  interrupts();
}

void stopTimer2() // stop TIMER2 interrupts
{
  noInterrupts();
  TIMSK2 = 0;
  interrupts();
}

int8_t readEncoder(byte i)
{ // this function is called within timer interrupt to read one encoder!
  int8_t result=0;
  byte state=state_ISR[i];
  state= state<<2 | (byte)digitalRead(encoder[i].pinA)<<1 | (byte)digitalRead(encoder[i].pinB); 
  state= state & 0xF;   // keep only the lower 4 bits
  /* // next two lines would be code to read 'quarter steps'
  if (state==0b0001 || state==0b0111 || state==0b1110 || state==0b1000) result= -1;
  else if (state==0b0010 || state==0b1011 || state==0b1101 || state==0b0100) result= 1;
  */
  // next two lines is code to read 'full steps'
  if (state==0b0001) result= -1;
  else if (state==0b0010) result= 1;
  state_ISR[i]= state;
  return result;
}

void beginEncoders()
{ // active internal pullup resistors on each encoder pin and start timer2
  for (int i=0; i<NUMENCODERS; i++)
  {
    pinMode(encoder[i].pinA, INPUT_PULLUP);
    pinMode(encoder[i].pinB, INPUT_PULLUP);
    readEncoder(i); // Initialize start condition
  }
  startTimer2();
}

boolean updateEncoders()
{ // read all the 'volatile' ISR variables and copy them into normal variables
  boolean changeState=false;
  for (int i=0; i<NUMENCODERS; i++)
  {
    if (count_ISR[i]!=0)
    {
      changeState=true;
      noInterrupts();
      encoder[i].count+= count_ISR[i];
      count_ISR[i]=0;
      interrupts();
    }
  }
  return changeState;
}


ISR(TIMER2_COMPA_vect)  // handling of TIMER2 interrupts
{
  for (int i=0; i<NUMENCODERS; i++) 
  {
    count_ISR[i]+= readEncoder(i); 
  }
}

This file is prepared to use one encoder on pin-8 and pin-9.
If you need more than one encoder or different pins, change the “encoder” array data accordingly.
Just connect the mechanical rotary encoder pins to the Arduino:

  • no external pull resistors required
  • no external filter circuit required
  • internal Atmega pullups will be activated

The example sketch does just one simple thing: If any rotation is detected, print count values of all defined encoders into one line of the serial monitor.

The following functions and variables in “encoder.h” are intended to be used in sketches:

 beginEncoders(); ==> Usually used in the setup() function to enable pins and timer
 updateEncoders(); ==> Call regularly from the loop function to update count
 encoder[i].count  ==> after updateEncoders(); this int will contain the current count value

The ‘updateEncoders();’ function returns a ‘false’ if no change on any of the encoders had occurred, or it returns ‘true’ if any count value on any encoder has been changed since the function was last called.

The pushbutton available on some mechanical encoders is not supported by this simple library and needs to be connected and handled as a normal pushbutton.

If you want to deactivate the rotary encoder, just make a call to “stopTimer2();”

jurs,
That works great with my encoders.
How do I use it to count up from 00 to FF then wrap back to 00, and similarly count from 00 and wrap up to 255?
Right now I just have the code dumbly counting 0 to 9 and back to 0 to show the hardware is working, while the encoder counts merrily up & down on the serial monitor.
I tried changing the encoder.h code to have the count wrap there, but not successfully.
Then it dawned on me that I really wanted the +1, -1 returned back to the program so the program could do something with it, and I can’t figure out how to get that #.
Thanks
Robert

// added rotary encoder demo by 'jurs' for Arduino Forum
// This is the code for the main "sketch"

#include "encoder.h" // unchanged except for swapping 8, 9 to be B, A

#include <SPI.h> // (will be used with SD card eventually)

// test of pins - press start to light LEDs, press select to turn off LEDs
byte redLed = 14;
byte greenLed = 15;
byte yellowLed = 16;
byte selectPin = 3;
byte startPin = 2;

byte shiftRCK = 19;
byte shiftSCK = 18;
byte shiftSerial = 17;

byte fontArray [] = {
  0b00111111, // 0
  0b00000110, // 1
  0b01011011, // 2
  0b01001111, // 3
  0b01100110, // 4
  0b01101101, // 5
  0b01111101, // 6
  0b00000111, // 7
  0b01111111, // 8
  0b01101111, // 9
  0b00000000, // blank
};
byte digit1 = 0;
byte digit2 = 1;

void setup(){
  pinMode (shiftSCK, OUTPUT);
  pinMode (shiftRCK, OUTPUT);
  pinMode (shiftSerial, OUTPUT);
  pinMode (redLed, OUTPUT);
  pinMode (greenLed, OUTPUT);
  pinMode (yellowLed, OUTPUT);
  pinMode (selectPin, INPUT_PULLUP);
  pinMode (startPin, INPUT_PULLUP);
  Serial.begin(115200);

  SPI.begin();
  beginEncoders();
}

void printEncoders()
{ // print current count of each encoder to Serial
  for (int i=0; i<NUMENCODERS; i++)
  {
    Serial.print(encoder[i].count);
    Serial.print('\t');
  }
  Serial.println();
}

void loop(){
  if (digitalRead(startPin) == LOW){
    digitalWrite (greenLed, HIGH);
    digitalWrite (redLed, HIGH);
    digitalWrite (yellowLed, HIGH);
  }
  if (digitalRead (selectPin) == LOW){
    digitalWrite (greenLed, LOW);
    digitalWrite (redLed, LOW);
    digitalWrite (yellowLed, LOW);
  }


  digit1 = digit1 + 1;
  if (digit1 == 10){
    digit1 = 0;
  }
  digit2 = digit2 + 1;
  if (digit2 == 10){
    digit2 = 0;
  }
  digitalWrite (shiftRCK, LOW);
  shiftOut(shiftSerial, shiftSCK, MSBFIRST, fontArray[digit2]);  
  shiftOut(shiftSerial, shiftSCK, MSBFIRST, fontArray[digit1]);
  digitalWrite (shiftRCK, HIGH);

delay(300);

if (updateEncoders()) printEncoders();
}

CrossRoads: How do I use it to count up from 00 to FF then wrap back to 00, and similarly count from 00 and wrap up to 255?

If you just want an 8-bit counter that is wrapping over at 255/0 instead of the default 16-bit int counter, you simply can use the lower byte of the counter:

void loop() {
  if (updateEncoders()) 
  {
    byte myCount=encoder[0].count; // use only lower byte of counter
    char buf[21];
    snprintf(buf,sizeof(buf),"0x%02X %3d",myCount,myCount);
    Serial.println(buf); // Same byte formatted in hex and decimal
  }
}

jurs,
How do I get just the +1, -1 back? That’s what I want, so can I update two 0 to F counters and send the updated count to two shift registers.

// added rotary encoder demo by 'jurs' for Arduino Forum
// This is the code for the main "sketch"

#include "encoder.h"

#include <SPI.h>

// test of pins - press start to light LEDs, press select to turn off LEDs
byte redLed = 14;
byte greenLed = 15;
byte yellowLed = 16;
byte selectPin = 3;
byte startPin = 2;

byte shiftRCK = 19;
byte shiftSCK = 18;
byte shiftSerial = 17;

byte fontArray [] = {
  0b00111111, // 0
  0b00000110, // 1
  0b01011011, // 2
  0b01001111, // 3
  0b01100110, // 4
  0b01101101, // 5
  0b01111101, // 6
  0b00000111, // 7
  0b01111111, // 8
  0b01101111, // 9
  0b01110111, // A
  0b01111100, // b
  0b00111001, // C
  0b01011110, // d
  0b01111001, // E
  0b01110001, // F
  0b00000000, // blank
};
byte lowerDigit = 0;
byte upperDigit = 0;

void setup(){
  pinMode (shiftSCK, OUTPUT);
  pinMode (shiftRCK, OUTPUT);
  pinMode (shiftSerial, OUTPUT);
  pinMode (redLed, OUTPUT);
  pinMode (greenLed, OUTPUT);
  pinMode (yellowLed, OUTPUT);
  pinMode (selectPin, INPUT_PULLUP);
  pinMode (startPin, INPUT_PULLUP);
  Serial.begin(115200);

  SPI.begin();
  beginEncoders();
}

void printEncoders()
{ // print current count of each encoder to Serial
  for (int i=0; i<NUMENCODERS; i++)
  {
    Serial.print(encoder[i].count);
    Serial.print('\t');
  }
  Serial.println();
}
void loop(){
  if (digitalRead(startPin) == LOW){
    digitalWrite (greenLed, HIGH);
    digitalWrite (redLed, HIGH);
    digitalWrite (yellowLed, HIGH);
  }
  if (digitalRead (selectPin) == LOW){
    digitalWrite (greenLed, LOW);
    digitalWrite (redLed, LOW);
    digitalWrite (yellowLed, LOW);
  }

  if (updateEncoders()){

    // +1 returned
    if (+1 returned){     // << how to get that?
      lowerDigit = lowerDigit + 1;
      if (lowerDigit == 0x10){
        lowerDigit = 0;
        upperDigit = upperDigit +1;
        if (upperDigit == 0x10){
          upperDigit = 0;
        }
      }
    }
    // -1 returned
    if (-1 returned){     // << how get that?
      if ((lowerDigit == 0)&& (upperDigit == 0)){  // rollover upper, lower from 00 to FF
        lowerDigit = 0x0F;
        upperDigit = 0x0F;
      } 
      if ( (lowerDigit == 0) && (upperDigit >0)){ // rollover lower from 0 to F and decrement upper by 1
        lowerDigit = 0x0F;
        upperDigit = upperDigit - 1;
      }
      if (lowerDigit >0){                       // decrement lower
        lowerDigit = lowerDigit -1;
      } 
    }
 // now update the display
    digitalWrite (shiftRCK, LOW);
    shiftOut(shiftSerial, shiftSCK, MSBFIRST, fontArray[upperDigit]);  
    shiftOut(shiftSerial, shiftSCK, MSBFIRST, fontArray[lowerDigit]);
    digitalWrite (shiftRCK, HIGH);

  }
}

Thanks
Robert

CrossRoads:
How do I get just the +1, -1 back?

The counting and synchronizing with the volatile variables is hidden in the update function.
And you don’t count 0 or +1, -1 only with every update, possibly.
If you don’t update each and every millisecond, the count may increase or decrease by 2, 3 or more with one update while rotating fast and updating slow.

So why not use the lowByte from the counter, extract the upper and lower nibble and send directly?

Code suggested:

// added rotary encoder demo by 'jurs' for Arduino Forum
// This is the code for the main "sketch"

#include "encoder.h"

#include <SPI.h>

// test of pins - press start to light LEDs, press select to turn off LEDs
byte redLed = 14;
byte greenLed = 15;
byte yellowLed = 16;
byte selectPin = 3;
byte startPin = 2;

byte shiftRCK = 19;
byte shiftSCK = 18;
byte shiftSerial = 17;

byte fontArray [] = {
  0b00111111, // 0
  0b00000110, // 1
  0b01011011, // 2
  0b01001111, // 3
  0b01100110, // 4
  0b01101101, // 5
  0b01111101, // 6
  0b00000111, // 7
  0b01111111, // 8
  0b01101111, // 9
  0b01110111, // A
  0b01111100, // b
  0b00111001, // C
  0b01011110, // d
  0b01111001, // E
  0b01110001, // F
  0b00000000, // blank
};
byte lowerDigit = 0;
byte upperDigit = 0;

void setup(){
  pinMode (shiftSCK, OUTPUT);
  pinMode (shiftRCK, OUTPUT);
  pinMode (shiftSerial, OUTPUT);
  pinMode (redLed, OUTPUT);
  pinMode (greenLed, OUTPUT);
  pinMode (yellowLed, OUTPUT);
  pinMode (selectPin, INPUT_PULLUP);
  pinMode (startPin, INPUT_PULLUP);
  Serial.begin(115200);

  SPI.begin();
  beginEncoders();
}


void loop(){
  if (digitalRead(startPin) == LOW){
    digitalWrite (greenLed, HIGH);
    digitalWrite (redLed, HIGH);
    digitalWrite (yellowLed, HIGH);
  }
  if (digitalRead (selectPin) == LOW){
    digitalWrite (greenLed, LOW);
    digitalWrite (redLed, LOW);
    digitalWrite (yellowLed, LOW);
  }

  if (updateEncoders()){
     byte myCount=encoder[0].count; // use only lower byte of counter
     upperDigit= myCount>>4; // shift high nibble 4 bits to the right
     lowerDigit = myCount & 0b1111; // keep only the low nibble
 // now update the display
    digitalWrite (shiftRCK, LOW);
    shiftOut(shiftSerial, shiftSCK, MSBFIRST, fontArray[upperDigit]);  
    shiftOut(shiftSerial, shiftSCK, MSBFIRST, fontArray[lowerDigit]);
    digitalWrite (shiftRCK, HIGH);
  }
}

Doesn’t that work for your counter digits?

I'll try it. I feel dense looking at software I didn't write sometimes. Gotta get some dinner before I do anymore. Been assembling cards, bootloading, prepping for shipping all afternoon, head's not in the programming game at the moment. Thanks for sticking with me on this.

Didn't eat yet, but the code's working :) Thanks very much jurs :grin: http://youtu.be/f51eSlcZt-g

Sorry to dig up this thread but I wonder if that poor mans encoder library might work on an adruino micro... I guess not since tje micro has no timer2?

Vulpecula:
Sorry to dig up this thread but I wonder if that poor mans encoder library might work on an adruino micro… I guess not since tje micro has no timer2?

The code will need a change for compatibility with ATmega32u4 microcontrollers like Leonardo or Micro then.

Perhaps rewrite the timer functions to use Timer3 (or Timer1 maybe) instead Timer2.
Are you able to do that?

I am fairly new to that but I'll give it a try. :)

CrossRoads: Didn't eat yet, but the code's working :) Thanks very much jurs :grin: http://youtu.be/f51eSlcZt-g

Resurrection time Hi Crossroads by chance do you still have a copy of the sketch you used. Think its the answer to my wind direction issue (no not that kind I can aim that pretty well and walk away)

I don’t have the encoder only code, but I do have the code that runs on the board. You can pick out the Encoder parts pretty easily.

Jurs’ code is still posted a few replies back it looks like.

StandaloneProgrammerWithDisplays125g.ino (43.1 KB)

font7segment.h (2.36 KB)

Don't forget the RC filter that the datasheet calls for. See sheet 2 http://www.bourns.com/docs/Product-Datasheets/PEC12R.pdf

Thanks so much.

EDIT reason for needing a reset at at zero point is am wanting to use an encoder for wind direction to an MKR1000 weather system. Nothing too fancy but trying to keep it simple.

Have something for the uC to read at 0 so you know when you get there.