• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Arduino Quadrature Decoder digital readout


Well-Known Member
Most Helpful Member
Thread starter #1
Long ago I bought a Mitutoyo linear scale for my milling machine. Not wanting to spend $3000.00 at the time, I interfaced it to a PC but that was inconvenient so I seldom used it.
Now I have to do some precision gunsmithing and I needed a digital readout.
I found some good quadrature code by jrraines and Daniel J. Gonzalez at
Quadrature Encoders in Arduino, done right. Done right.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811/0 using high performance reads and writes with
digitalWriteFast.h at http://code.google.com/p/digitalwritefast/
He is reading motor position. I just don't want to ever miss a beat.

I am using an Arduino Nano and this Serial LCD for Arduino
Read the comments on that page. The library that works with this chip set is available at this link. http://www.play-zone.ch/en/fileuploader/download/download/?d=0&file=custom/upload/File-1345667375.zip
With an external 5 volt wall wart, it fits inside an audio cassette case. You will want a momentary N.O. reset switch to reset / zero it.
This is my version of the sketch by jrraines. Quadrature input to the Arduino are on digital pins 2 & 3. The Serial LCD just needs +5v, grnd, SDA & SCL

*Quadrature Decoder
#include "Arduino.h"
#include <digitalWriteFast.h>  // library for high performance reads and writes by jrraines
                               // see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811/0
                               // and http://code.google.com/p/digitalwritefast/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
//LiquidCrystal_I2C lcd(0x20,16,2);  // Alternate LCD address of 0x20 if 0x27 doesn't work
//LiquidCrystal_I2C lcd(0x3F,16,2);  // Alternate LCD address of 0x3F if 0x27 doesn't work
// It turns out that the regular digitalRead() calls are too slow and bring the arduino down when
// I use them in the interrupt routines while the motor runs at full speed.
// Quadrature encoders
#define InterruptA 0
#define InterruptB 1
#define PinA 2
#define PinB 3
volatile bool ASet;
volatile bool BSet;
volatile bool APrev;
volatile bool BPrev;
float Ticks = 0;
float OldTicks = 0;

void setup()
  lcd.init();                      // initialize the lcd
  // Quadrature encoders
  pinMode(PinA, INPUT);      // sets pin A as input
  pinMode(PinB, INPUT);      // sets pin B as input
  attachInterrupt(InterruptA, HandleInterruptA, CHANGE);
  attachInterrupt(InterruptB, HandleInterruptB, CHANGE);
// So it starts with current condition
    ASet = digitalReadFast(PinA);
    APrev = ASet;
    BSet = digitalReadFast(PinB);  
    BPrev = BSet;
Ticks = 0;

void loop()
//  Serial.print("Encoder Ticks: ");
//  Serial.print(Ticks);
//  Serial.print("\n");

    lcd.setCursor( 0, 0 );   //Top left
    lcd.print(Ticks * 0.00019685 ,4);  // To 4 decimal place 1/5080 on linear scale
    lcd.print(" Inches ");

    lcd.setCursor( 5, 1 );   //Second row
        lcd.print(" MM ");  
        lcd.print(Ticks * 0.005 ,3);  // To 3 decimal place 25.4/5080 on linear scale
        lcd.print("    ");

OldTicks = Ticks;

// Interrupt service routines for the A quadrature encoder Pin
void HandleInterruptA(){
  BSet = digitalReadFast(PinB);
  ASet = digitalReadFast(PinA);

  APrev = ASet;
  BPrev = BSet;

// Interrupt service routines for the B quadrature encoder Pin
void HandleInterruptB(){
  // Test transition;
  BSet = digitalReadFast(PinB);
  ASet = digitalReadFast(PinA);

  APrev = ASet;
  BPrev = BSet;

int ParseEncoder(){
  if(APrev && BPrev){
    if(!ASet && BSet) return 1;
    if(ASet && !BSet) return -1;
  }else if(!APrev && BPrev){
    if(!ASet && !BSet) return 1;
    if(ASet && BSet) return -1;
  }else if(!APrev && !BPrev){
    if(ASet && !BSet) return 1;
    if(!ASet && BSet) return -1;
  }else if(APrev && !BPrev){
    if(ASet && BSet) return 1;
    if(!ASet && !BSet) return -1;

Y axis DRO.jpg
Digital readout.jpg
I cheated on the X axis table travel.
X axis micrometer.jpg

Latest threads

EE World Online Articles