Arduino Quadrature Decoder digital readout

Status
Not open for further replies.

ClydeCrashKop

Well-Known Member
Most Helpful Member
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.
https://yameb.blogspot.com/2012/11/quadrature-encoders-in-arduino-done.html
and
**broken link removed** using high performance reads and writes with
digitalWriteFast.h at https://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
https://www.mpja.com/Serial-2-X-16-LCD-Display-for-Arduino/productinfo/31164+MP
Read the comments on that page. The library that works with this chip set is available at this link. https://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

C:
/*
*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
  lcd.backlight();
  Serial.begin(9600);
  // 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);

  Ticks+=ParseEncoder();
  APrev = ASet;
  BPrev = BSet;
}

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

  Ticks+=ParseEncoder();
  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;
  }

}



I cheated on the X axis table travel.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…