DC Motor with 48CPR Encoder

I currently have a setup with a 6V, 120RPM DC Motor with a 48CPR Quadrature Encoder (from Pololu). The motor has a 75:1 gearbox.

How do I go about decoding the signals from the encoder, so that I can determine RPM (from the driveshaft) along with the amount of revolutions the drive shaft has done? I've been researching ways to do this for days and have found nothing of use!

I have calculated that I am getting 864 counts per SECOND from the encoder, so 432 counts per second on EACH CHANNEL...

Hope someone can help!

Hey dude,

I'd have a read on quadrature encoders first so you have a basic understanding of how it works - it's pretty simple really.

http://playground.arduino.cc/Main/RotaryEncoders

I have a sketch that you'll be able to modify and use as a starting point. It's based on an example I found online. It uses interrupts to count the pulses.

My code is a distance counter so it counts the pulses, and when it gets to 477 pulses it increments my distance counter by 1 (for me, that's 1cm).

For you, this means you need to work out how many pulses you have per revolution and plug this number instead of 477.

The code uses volatile long data type for the pulse count, which is able to go negative meaning it will track backwards rotation as well as long as it doesn't overflow before making a count.
To count RPM, you need to count the pulses over a time period.

Note that I use a serial LCD so you can strip all that stuff out. I think it feeds serial data too at the moment:

/* Rotary encoder with attachInterrupt

Counts pulses from an incremental encoder and put the result in variable counter. 
Taking also into account the direction and counts down when the rotor rotates in 
the other direction.

This code is used attachInterrupt 0 and 1 which are pins 2 and 3 moust Arduino.
For more information about attachInterrupt see:
http://arduino.cc/en/Reference/AttachInterrupt
 
created 2014
by Ben-Tommy Eriksen

https://github.com/BenTommyE/BenRotaryEncoder
 
*/
#include <LiquidCrystal_I2C.h>
#include <Wire.h>


LiquidCrystal_I2C	lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack

// Encoder connect to digitalpin 2 and 3 on the Arduino.

volatile long counter = 0;  //This variable will increase or decrease depending on the rotation of encoder
int rotations = 0;

void setup() {
  
  lcd.begin (16,2); // for 16 x 2 LCD module

  lcd.setBacklightPin(3,POSITIVE);
  lcd.setBacklight(HIGH);
  Serial.begin (9600);
  //Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, RISING);
  
  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
  attachInterrupt(1, ai1, RISING);
}

void loop() {
  // Send the value of counter
if (counter>=477) {
      rotations++;
      counter=0;
    } 
    
if (counter<=-477) {
      rotations--;
      counter=0;
    }
    
  Serial.println (counter);
  lcd.setCursor(0,0);
  lcd.print(counter);
  lcd.setCursor(0,1);
  lcd.print(rotations);
  //lcd.clear(); //clear display
}

void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if(digitalRead(3)==LOW) {
    counter++;
  }else{
    counter--;
  }
}

void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if(digitalRead(2)==LOW) {
    counter--;
  }else{
    counter++;
  }
}

In terms of hardware, hook the signal wires up to your Interrupt pins 0 and 1 (check which ones they are on your board), and run a pullup resistor for each (20k is ok).

Thank you very much, that code has actually worked really well! I've modified it to suit my setup and it does exactly what I need it to :slight_smile: many thanks for the help!

Glad to hear it. Good luck!