Hello there! , I’m having a little problems programming this encoder with arduino, i’m doing it manually (without a library) but it is not the best way to get the data.
I want to know if anyone of you have used it with Arduino or if you know how to get accurate data from the device, i need to obtain speed from a shaft. Your help is welcome ! Thanks!!
Best regards from Chile!
There are many ways to do it; the best solution depends on the specific application:
a) are you trying to measure speed or position?
b) do you care about direction?
c) how fast will you be spinning the encoder, and
d) what’s the CPR of the encoder?
Arduino Playground has some pretty well developed pages with code.
Need to start with Ether’s questions, how many pulse/rev and what RPM rate you are looking to sense. Looks like many of the solutions use interrupts, which may be limited on the Arduino, so you may have significant limitations on rate it can process.
There are several approaches you may consider, below is one I have used.
Using one channel of the encoder attached to one of the external interrupts and the other to a digital input. Use the interrupt service routine to determine the direction.
Each tick of the encoder will also represent a distance of travel or amount of rotation of a shaft. With those values known, you can calculate RPM and/or distance.
As mentioned by tr6scott, the Arduino may be somewhat limited on the maximum rate it can manage, so keep that in mind. How fast your Arduino can process interrupts will be directly related to how tightly you code your ISR.
Here is a piece of code I used to control the motor’s rate. The motor directly drove the encoder. I use the Servo library to drive the motor because the signal generated is the same as the speed controller uses.
/**********************************************************
* Quadrature Encoder code using Interupt 0 (Dig pin 2) to *
* trigger ISR and accumulate count in variable "Accum" *
*controlling servo(motor) on D9. *
**********************************************************/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created
const int COUNTPERREV = 128; // Encoder count per revolution
const int LOOPDELAY = 100; //ms to delay the loop ie. 100 is 100ms
const int TARGETRPM = 1; // for testing, this establishes the RPM target RPM
long lastAccum =0; // Holds the Accum count from the previous sample
int B = 5; // Phase B pin connection
int pos = 90; // variable to store the servo position
int desiredcount = (COUNTPERREV/TARGETRPM)/(1000/LOOPDELAY); // sets desired loop count
int errorAccum = 0; //this is added to neutral to position(drive) the servo(motor)
volatile long Accum = 0; // Accumulator for total count
int rate = 0; //measured # of counts per sample period
void setup(void)
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
pinMode (B, INPUT); // Phase B pin type
attachInterrupt (0, ISR0, RISING); // Interupt 0 calls "ISR0"
Serial.begin(115200); // connect to the serial port
}
void loop (void)
{
GetRate();
errorAccum += (desiredcount - rate); // adds difference between the desired count and the actual,
// , the rate error, to be used to correct the motor speed
myservo.writeMicroseconds(1500 + errorAccum); // send servo(motor) control pulse
Serial.print (" errorAccum is ");
Serial.println (errorAccum);
delay(LOOPDELAY); // waits the number of ms defined by LOOPDELAY
}
void ISR0(void)
{
if (digitalRead(B) == HIGH)
{
Accum ++ ;
}
else
{
Accum -- ;
}
}
void GetRate (void)
{
long samplediff;
samplediff = (Accum - lastAccum); // Creates the counts since last sample
lastAccum = Accum; // Saves the count for the next loop
rate = (int) samplediff; // Cast the sample to an int and sets rate
}