DesignSpark Electrical Logolinkedin
Menu Search
Ask a Question

15 Jan 2019, 14:35

Quadrature Encoder Basics Part 2: Practice

After learning a few things about the quadrature encoders in the previous article – Encoder Basics – let's try to detect the signals they emit!

What you will need:

  • Stepper or DC Motor with incremental quadrature encoder
  • 8-pin encoder connector cable
  • Arduino board (in this case we are using Arduino UNO R3)
  • LCD Screen to display results (in this example Sainsmart 4x20 chars)
  • Breadboard and Dupont cables

First of all, we will need to strip one side of the 8-pin encoder cable.

Now that we have a clear image of the 8 pin cables we should identify them. If you are using an igus encoder cable they are as following:

A and B channels on White and Green
A/ and B/ inverted channels on Brown and Yellow (used for filtering)
Index channel N and N/ on Pink and Blue (emits one signal per rotation of the motor used for homing)
Ground on Grey
VCC on Red (5VDC)

We know that the Arduino UNO has a 5VDC output pin and that should be adequate to power the encoder, of course using an external power supply adds stability and less fluctuation but let's keep it as simple as possible.

Wiring the encoder to the Arduino UNO

As stated above the connections will be as following:

Encoder – Arduino

VCC Red 5V
GND Grey GND
CH B Green Pin 2 (important as we will use the pin as an external interrupt)
CH A White Pin 4 

 

LCD Screen – Arduino

VCC Red 5V
GND Green GND
SDA Blue A4
SCL Purple A5


And here is a block diagram:

After connecting the Arduino to the PC, open the Arduino IDE with a new sketch.

From the menu bar select: Tools > Board > Arduino Genuino UNO (or your respective board). And from the same tab, the port that you have your Arduino connected to.

Writing the code

Let's explain some basic parts of the code. We will first include the libraries needed:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

Display the home screen on the LCD for 1500ms:

 lcd.home ();
  lcd.print("Encoder Tester.");  // Print a message to the LCD.
  lcd.setCursor( 0, 3);//Set the cursor to line 3 (first line is line 0)
  lcd.print("Please plug encoder.");
  delay(1500);

Attach the RISING interrupt:

 attachInterrupt(0, runEncoder1, RISING );  
// encoder pin on interrupt 0 >>(pin 2 on arduino)

Because of the nature of the LCD whenever a character is printed, it stays on the LCD until is overwritten by another character (including space). The count of steps will increment and decrement 500 ticks per motor rotation.

So if the motor moves forward half rotation the LCD will print 250 steps and if the motor moves backwards for half rotation the ticks decrement to 0-ticks but the LCD will actually show 150 as last two numbers were printed but not refreshed.

To solve this  "bug", we will refresh the LCD by printing spaces every time that the value of the character decreases.

 lcd.setCursor ( 8, 2 );        // go to the 2nd line
  lcd.print(Pos1, DEC);  
   if (Pos1 < 100000) lcd.print(" ");
  if (Pos1 < 10000) lcd.print(" ");
  if (Pos1 < 1000) lcd.print(" ");
if (Pos1 < 100) lcd.print(" ");
if (Pos1 < 10) lcd.print(" "); 
                 

  lcd.setCursor ( 0, 3 );        // go to the fourth line
  lcd.print("                    ");

Last but not least, we should set the interrupts routine:

void runEncoder1()
{
 if (digitalRead(encoder1PinA) == digitalRead(encoder1PinB))   
   encoder1Pos++;    // count up if both encoder pins are HIGH on pin change interrupt
 else                                       
   encoder1Pos--;    //count down if pins are HIGH and LOW
}

Having in mind the encoder sequence from the datasheet:

In a clockwise (positive) rotation, if we attach the interrupt to channel A, the interrupt will be triggered by the HIGH signal. The Arduino will check if channel B is HIGH as well, which is not, and the Arduino will record -1 encoder steps which is wrong.

So the interrupt should be attached to channel B, when channel B goes HIGH, Arduino will check channel A which will be also HIGH and it will recond +1 encoder steps.

If the motor moves counter-clock wise, thus the sequence is reversed, when channel B goes HIGH and triggers the interrupt, Arduino will check channel A which will be LOW and it will register -1 encoder steps.

How are these signals used in automation projects?

With low-end generic controllers, we would command the stepper motor to move one rotation which equals 200 motor steps. Only channels A and B are used.

After the command was sent and completed by the motor, we would check if the encoder steps are on 500.

If a command of 200 motor steps is sent and we get 500 encoder steps feedback, motion was completed successfully.

If on the other case we get less encoder steps, it means that motor lost some steps due to excessive load, obstacles etc. thus we will instruct the motor to be disabled (de-energised) and an error to be emitted through a red LED for example.

With high end controllers like the igus D1 Dryve, channels A, B are used for feedback, N can be used for homing if needed,  A/, B/ and N/ for filtering.

With the D1 Dryve when a motor with an encoder is used, we can enable closed loop.

Closed loop is a field-oriented control with sinusoidally commutated current-vector control meaning that the motor current is controlled on the go using the live feedback from the encoders in relation to the load.

For example, if the load increases the controller will increase the supplied current to the motor and vice versa. This eliminates the posibility of losing steps thus losing position which is a main problem when using stepper motors.

Here are pictures of the completed project:

More information about the motor and the D1 Dryve controller?
www.igus.co.uk/dryve

More information about encoders?
Encoder Basics

Full Code?
(Look at the attachments below.)

In a new series of articles, I will start exploring motor controllers for various types of motors and the different control modes they have.

Thank you for reading, please comment your thoughts/ questions at the comment section!

A.B.

Downloads

Electro-mechanical background with interest in motion control and automation, DC, EC, Steppers! Low Cost Automation Engineer at igus, UK.

15 Jan 2019, 14:35

Comments

June 20, 2019 07:23

thanks again Mr. bit for sharing,
I wrote a code attached to this comment, in order to count pulses channel A and B will send to us; however, when I change the direction of the motor, pulses will still increasing. My code is so similar to yours as you can check.

0 Votes

June 20, 2019 07:23

Hello Mr. Bit,
Thank you for your article, it was really helpful for me.
When do you release new articles about the controllers of motor?
Do you have any articles about controlling the position and velocity of a dc motor encoder with PID controller?
wish you the best.

0 Votes

March 5, 2019 09:13

Thanks for this nice article. I had implemented an encoder application that measures approximately 12cm of movement for a painting cylinder machine. I had interfaced an 2x16 character lcd. But since the lcd's are requring timing delays I think its better to use seven segment displays.

0 Votes

April 2, 2019 08:51

@isoturco Thank you for the comment. You are right in industrial applications I wouldn't use this for the reasons you stated. (refresh delays) This is for exhibition purposes only. 8-digit displays are in most cases easier to configure as well.

January 29, 2019 08:55

some encoders have a serial output channel, S+,S-, be useful to know how that works! I'd guess a short pulse for a cw step, and a longer one for the other direction.
Thanks for reading, regs Dave.

0 Votes

April 2, 2019 08:51

@DSpond Thank you for the comment! I am not sure but maybe is based on the same principle. If you have a look on the encoder sequence diagram in the article, isolate channel A and B. The same principle is used when two-channel hall sensors are used for positioning. If the rising sequence is B- A - B the the motion is CCW and vice-versa. I hope I answered your question.!

January 16, 2019 08:39

Thanks for sharing!

0 Votes

January 21, 2019 10:26

@Joanna1 Thank you for your comment!