Project tutorial
How to Use Incremental Encoders

How to Use Incremental Encoders © GPL3+

How to connect incremental encoders for industrial use with RS-422 interface to an Arduino UNO.

  • 1,744 views
  • 0 comments
  • 3 respects

Components and supplies

Necessary tools and machines

Apps and online services

About this project

Incremental encoders are often used for industrial applications like robotics or positioning tracking. Encoders for industrial applications comes mostly with a differential RS-422 interface.

The RS-422 is only used as a hardware layer. No serial protocol will be transmitted over the RS-422. Only the pulses of the encoder itself are directly transferred via 3 different RS-422 channels: SIN, COS and Z (zero position).

I will show in this small project how to use an industrial incremental encoder - in our case SICK DFS60 - with an Arduino UNO. Because of the 3 independent RS-422 channels we need 3 RS-422 inputs for the Arduino. For this purpose I've used 3 pcs of my Arduino RS422/RS485 shields - stacked on one Arduino.

DIP switch setting for RS422 shield:

the dip switch setting for any shield is the same.

  • S1: ON, OFF, OFF, OFF
  • S2: OFF, OFF, ON, ON
  • S3: ON, OFF, OFF, OFF

Jumper setting for RS422 shields:

The Jumper setting for any shield is different. Depending from the connected channel the RX pin is configured to:

  • Z: D2
  • COS: D3
  • SIN: D4

The voltage jumper JP1 must be setted to 5V.

Wiring:

Power supply:

The encoder can be powered by an laboratory power supply or directely by the 5V of the Arduino UNO

Final test:

Open the serial monitor with 115200 baud. You will see the current increment value (updated all 0,5s) and the current status of the encoder there....

Code

Code for Arduino UNOArduino
/*
 *  Application note: incremental encoder and RS422/RS485 Shield  
 *  Version 1.0
 *  Copyright (C) 2020  Hartmut Wendt  www.zihatec.de
 *  
 *  used encoder: SICK DFS60 www.sick.com
 *  
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/   


// Pin definitions
const byte ZeroPin = 2;  // RS422 input for Z channel (zero detection)
const byte COSPin = 3;   // RS422 input for A channel (cos signal) 
const byte SINPin = 4;   // RS422 input for B channel (sin signal)  

// variables
enum {ENC_STOP, ENC_CLOCKWISE_ROTATION, ENC_COUNTERCLOCKWISE_ROTATION};  // encoder operation modes
volatile byte encoder_state = ENC_STOP;
volatile int encoder_position = 0; 
volatile int encoder_oldpos = 0; 



void setup() {
  Serial.begin(115200); //Use serial monitor for debugging

  // Define pins for input and output
  pinMode(SINPin, INPUT);

  // set internal pullup resistor for interrupt pin
  pinMode(COSPin, INPUT_PULLUP);
  pinMode(ZeroPin, INPUT_PULLUP);
  
  
  // set 1st interrupt service routine to COSPin and 'RISING' edge 
  attachInterrupt(digitalPinToInterrupt(COSPin), encoder_isr, RISING);

  // set 2nd interrupt service routine to ZeroPin and 'HIGH' level 
  attachInterrupt(digitalPinToInterrupt(ZeroPin), zero_detection_isr, HIGH);
}


void loop() {
  // Detect Encoder Stop
  if (encoder_oldpos == encoder_position) encoder_state= ENC_STOP;

  // output encoder incremental and status
  Serial.print("Encoder position: ");
  Serial.print(encoder_position);
  Serial.print(", Encoder state: ");
  
  if (encoder_state==ENC_CLOCKWISE_ROTATION) {
    Serial.println("Clockwise Rotation");
        
  } else if (encoder_state==ENC_COUNTERCLOCKWISE_ROTATION) {
    Serial.println("Counter-Clockwise Rotation");
    
  } else {
    Serial.println("Stop");  
  }
  
  encoder_oldpos = encoder_position;
  
  delay(500);
}


void encoder_isr() {
  
  if  (digitalRead(SINPin) == LOW) {
    // clockwise rotation
    encoder_state=ENC_CLOCKWISE_ROTATION;
    encoder_position++;
  } else {
    //counter-clockwise rotation
    encoder_state=ENC_COUNTERCLOCKWISE_ROTATION;
    encoder_position--;    
  } 
}


void zero_detection_isr() {
  // detect pulse on zero channel
  encoder_position = 0;
}

Schematics

Wiring diagram
Wiring dfs60 7neymqxoua

Comments

Similar projects you might like

Measure LUX with Arduino Using BH1750

Project tutorial by afsh_ad

  • 11,246 views
  • 0 comments
  • 4 respects

Exploring Encoders - Step Trackers for Motors

Project tutorial by SciJoy

  • 4,171 views
  • 3 comments
  • 9 respects

How to Use Modbus with Arduino

Project tutorial by hwhardsoft

  • 17,480 views
  • 5 comments
  • 20 respects

Up to Three RS485 Busses on One Arduino

Project tutorial by hwhardsoft

  • 3,884 views
  • 0 comments
  • 6 respects

XBee Arduino Interfacing

Project tutorial by Fouad_Roboticist

  • 1,327 views
  • 4 comments
  • 5 respects

Sqlite µLogger

Project tutorial by arundale

  • 1,034 views
  • 1 comment
  • 6 respects
Add projectSign up / Login