Go Down

Topic: help with encoder not working on high speed (Read 2296 times) previous topic - next topic


I have a 12V DC motor from Faulhaber with an encoder with 16 pulses/rotation. What i am trying to do is to control the position of the motor using a potentiometer, and also controlling the speed of it.
The problem is that the positioning works(with the encoder and pid library) only for pwm values under 70. Over that value the arduino simply crashes and the motor keeps rotating at high speed without reading anything from the encoder.
I tested the motor without the encoder readings and it works fine at any speed or direction. When I try to use the encoder, something goes wrong.
The code is:

#include <PID_v1.h>
#include <Encoder.h>
int sensorValue = 0;
int outputValue = 0;
int k;
long positionLeft  = -999;
Encoder myEnc(3, 2); 
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
//PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
PID myPID(&Input, &Output, &Setpoint,2,0,0, DIRECT);
  void setup() {
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);


setPwmFrequency(9, 1);
//initialize the variables we're linked to
  Input = 0;
  Setpoint = 0;

  //turn the PID on
  myPID.SetOutputLimits(-75, 75);                                                      //over 75 the encoder can't read anymore


void loop() {
  sensorValue = analogRead(A0);
  Input = positionLeft;
  Setpoint= sensorValue;

Can you give any suggenstions about what could cause the encoder to not read at high speed?? (I am using Arduino Uno, a driver with L298 H bridge and the encoder channels are using the 2 and 3 interrupt pins on Arduino).
Thanks in advance.


part numbers? datasheet?  We can't guess these.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]


Sorry for not posting this information. The motor is http://www.faulhaber-group.com/uploadpk/EN_2342_CR_DFF.pdf, has a 1:23 reduction rate, and has a built-in encoder http://www.faulhaber-group.com/uploadpk/EN_IE2-16_DFF.pdf with 16 lines/revolution.
edit: I have tested the motor with a simple program (working in one direction while modifying the PWM from a potentiometer) with the encoder library and the serial readings reveald that at pwm speeds around the value of 66 the serial is reading very slowly (even at 115200 band), and when the PWM is over 70, Arduino crashes(it doesen't respond to any commands other than reset, and the serial port is also frozen).
It must be something to do with the fact that Arduino can't keep up with the readings at high speed, but how can I solve this issue?


Is the encoder connected to the motor shaft or the output shaft?

What I suspect is that the encoder is sending too many pulses to the Arduino and causing a stack overflow. Once that happens the program is completely lost.

For high speeds you will have to learn to program in assembly language and all the other challenges involved with that endevor.


Where did you get the Encoder library from? I can't tell what is going on without seeing the code for it.

Please use code tags when posting code.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.


The encoder is connected to the motor shaft. It seems that programming in assembly is far too complicated for me.
The library for encoder is Encoder.h from http://www.pjrc.com/teensy/td_libs_Encoder.html and I used the Basic example to make the readings.
The code for the encoder readings with the PWM control from a potentiometer is:

Code: [Select]
#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(2, 3);
//   avoid using pins with LEDs attached
int potpin = A0;
int potpin2=A1;
int k,k2;

void setup() {
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);

long oldPosition  = -999;

void loop() {

if (k>800) {
if (k<300) {

  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;


Any suggestions about how I can read the encoder on high speeds? Without any hardware implications maybe, only from soft...
Can a better Arduino(Mega) do the trick? Or another board with better processor?


As long as you are using the ArduinoIDE you are going to get about the same performance from any of the various "compatible" boards. They all run at 16 - 20 Mhz and execute 1 instruction per clock, the only difference is available memory.

The only way to gain speed may be to go to assembly language. Assembler is only complicated until you have used it a bit. Arduino is only complicated until you have used it a bit. The difference is that in the Arduino environment ( C, C++ ) a lot of stuff is done for you and that stuff comes with certain assumptions. Because of those assumptions there is a certain amount of overhead that libraries add to make them behave well together. That "stuff" that makes the pieces parts play well together is not always needed, but it is there because the folks that wrote the libraries and such have no idea how you might want to use/abuse the code. In Assembler you get to make those descisions. I wrote some code for a Step/Direction stepper driver using, first the Uno and then an ATtiny2313. Original code was in Arduino and I got it down to 1200 bytes. I then did it in assembly. The Assembly version is 88 bytes and I know it could be 86, but those 2 bytes are just dummy data and don't affect execution. Smaller programs execute faster. Fewer instructions equals less time.


So you are saying that I should aim to modify the encoder library using assembly? And this should  solve my problem? I can find there some instructions that I don't need or can I implement something else to reduce the encoder counts with assembly language?
Thanks for info. 


Did someone say assembly?


I know this is an old post but...

Don't display your position with every change.  println takes up a lot of processor effort.  What I do is run an interrupt for the encoder reading, and then in the main loop display position ever 200 ms.

Code: [Select]

  Read a rotary encoder using interupts
  Encoder common <-> ground
  ENCODER0_PINA <-> pin 2
  ENCODER0_PINB <-> pin 4


#define ENCODER0_PINA 2
#define ENCODER0_PINB 4

volatile int ENCODER0_pos = 0;

void setup() {
  digitalWrite(ENCODER0_PINA, HIGH);     // Turn on pullup resistor
  digitalWrite(ENCODER0_PINB, HIGH);     // Turn on pullup resistor
  attachInterrupt(0, doEncoder, CHANGE);  // Encoder pin on interrupt 0 (pin 2)


void loop() {

   Serial.println (ENCODER0_pos,DEC);

void doEncoder() {
  /* If PINA and PINB are both high or low -> Moving Forward
                                      else -> Moving Backward
  if (digitalRead(ENCODER0_PINA) == digitalRead(ENCODER0_PINB)) {
    ENCODER0_pos ++;
  } else {
    ENCODER0_pos --;


The encoder "library" you are using actually has an optimized assembly version. 
From the web page:
Code: [Select]

// This optional setting causes Encoder to use more optimized code,
// It must be defined before Encoder.h is included.
#include <Encoder.h>

Try that and see if you can get higher than 70.

The ISR for this encoder library is doing a lot of work, even the asm version. I'd suggest looking for an encoder library or function with less overhead.

Go Up