DaddyOh's Blog

Making, Cooking, Living

Reading Quadrature Encoders With mBuino Mbed

| Comments

PID Control Learning System Part 3

Introduction

As part of my efforts to learn about motor control and PID conrollers I needed to figure out how to read Quadrature Encoders so that I can measure and adjust motor speed. Using encoders I should be able to measure motor speed with greater precision and accuracy than would be possible from counting each output shaft rotation. And with the right encoders I should be able to measure the motor speed on a regular basis (say every 0.1 second) which makes the PID control simplier and more predictiable.

Rotary encoders are devices that count rotations either of the output shaft or if a geared motor, the primary motor shaft. You will find optical encodes that trigger when a light beam is interupted and magnetic encoders that trigger when a magnet passes close to a hall effect sensor.

Quadrature encoders are when there are two sensors on the same ring. Quadrature encoders provide several benefits:

  • Greater trigger resolution over single sensors, hence faster
  • Higher counts per rotation and this leads to greater precision and accuracy
  • The ability to know what the rotational direction is at any point in time

With the addition of a third sensor you can also measure the position of the wheel (or whichever part is rotating). Three sensors is a bit advanced and is not part of this blog post.

There are a lot of resources on the web talking about using encoders. For my purpose I just need some sample code that runs in an mbed device. The code below is designed for a mBuino platform. However it also runs on an NXP LPC1768 (with a few minor changes) and should be adaptable to all mbed platforms if they have enough pins available.

Geared Motors and Encoders

When the encoder is attached to the primary motor shaft of a reduction geared motor you can get very high output shaft resoultion from the encoders. Consider the motor I used from pololu which is stated to use a 30:1 reduction gear, with a maximum output shaft speed of 350 RPM. When using both sensors for the qaudrature encoder the motor triggers 64 times for each primary shart rotation.

Lets do the math for one output shaft rotation:

1 output rotation * 30 primary motor rotations / ourpur rotations  = 30 primary rotations / output shaft rotations
30 primary rotations * 64 triggers / rotation = 1920 triggers / output shaft rotation

The documentation on the motor I used states:

The quadrature encoder provides a resolution of 64 counts per revolution of the motor shaft when counting both edges of both channels.

This is important because most encoder libraries have a configuration setting for which encoding scheme to use.

This demonstration program used the mbed QEI library provides for X2 and X4 encoding. We need X4 since we are measuring both the rise and fall of the output traces for both sensors. The code sample shows how this all works.

I’m pretty new to using mbed and encoders so I validated the calculated motor speed (output shaft rotations per minute) using a hall effect sensor with a disc with a magnet on the output shaft. The good new is the values are identical. I guess that means I’m doing something right! You can see the setup in the pictures and video at the end of the post.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "mbed.h"
#include "QEI.h"
#include "USBSerial.h"
/*
  Using an mBuino mbed device (can use any mbed) and the mbed QEI Library
  
  Measure motor output shaft speed every ~0.1 second using
  a pololu quadrature encoder and motor
  
  License: Apache License, Version 2.0
  http://www.apache.org/licenses/LICENSE-2.0.html
  December 30, 2014
  Copyright: Eric F Palmer, 2014
  Email: eric [at] ericfpalmer [dot] [com]
   
  This code could be simplified but I have left it alone
  because it works and you have access to the delta values for
  further analysius and debugging
  
  See notes at the bottom of the file
  
*/

USBSerial pc;
QEI wheel (P0_13, P0_11, NC, 64, QEI::X4_ENCODING);
Timer t;
int startTimeUs, endTimeUs;
int deltaUs = 0;
int startPulse, endPulse;
int deltaPulse = 0;

float calcRpm(float deltaTimeSec, int deltaPulse){
    // motor ratio = 30 (different for different motors)
    // motor CPR = 64 (also may vary for different motors, encoder types) 
    return 60.0 * ((deltaPulse / deltaTimeSec) / (30.0 * 64.0));
}

int main() {
    startTimeUs = t.read_us();
    startPulse = wheel.getPulses();
    t.start();
    while(1){
        wait(0.1);
        endTimeUs = t.read_us();
        endPulse = wheel.getPulses();
        deltaUs = endTimeUs - startTimeUs;
        deltaPulse = endPulse - startPulse;
        pc.printf("%.1f\r\n",calcRpm(deltaUs/1000000.0, deltaPulse));
        wheel.reset();
        startPulse = wheel.getPulses();
        startTimeUs = t.read_us();
    }
}

/*
 Pololu 64 CPR qaudrature encode
 The motor I tested is http://www.pololu.com/product/1443
 RED motor power A up to 24V 
 BLK motor power B 
 GRN encode ground  
 BLU encoder Vcc 3.5 to 20V (using 5 V)
 YEL encoder output A (P0_13)
 WHT encoder output B (P0_11)
 
 
 */

Motor and bracket


Breadboard


Video Showing Motor Running

Test setup for measuring motor speed using quadrature encoders. See the related blog post and other video http://youtu.be/RdpVkhmFDRA http://daddyoh.us/blog/2015/01/02/reading-quadrature-encoders-with-mbuino-mebed/

Serial Output Showing RPM

Shows the calculated motor speed (RPM) for a test with an mBuino mbed device and a 30:1 pololu motor. See the related video http://youtu.be/ilo41DnuZrU and blog post. http://daddyoh.us/blog/2015/01/02/reading-quadrature-encoders-with-mbuino-mebed/

Now Go Make Something!

Comments