Quadrature interference

I have a Pololu 12v gearmotor with quadrature encoder powered from one of their motor controllers and an Arduino reading the encoder output.

I had been testing this setup with the motor/encoder connected directly with short (~8") leads and had no problems getting a reliable encoder reading. Now I'm building out the enclosure and hooking up the motor via Cat5 cable (motor > jack > Cat5 cable > jack > Arduino/driver).

After wiring this up and testing the system again, I'm getting unusable readings at low speeds (jumping around 10-20,000 steps in the time it should go under 1,000) which get more accurate as the speed increases. By around 50% speed it appears to be reading accurately. Also, turning the motor shaft by hand with the motor driver off, I can accurately read individual steps.

The cable wiring is:
Pair 1: motor V+ (x2)
Pair 2: motor V- (x2)
Pair 3: encoder A / encoder B
Pair 4: encoder +5V / GND

Am I getting interference from the PWM motor signal running alongside the encoder output? If so, is there any way to prevent/fix that, or do I just have to separate them?

Thanks for any advice,
Max

Please post your code, it might be a SW problem...

I'm fairly sure it's outside interference. Code has been working fine, only change was how the motor/encoder is wired to the driver/arduino. This is for a motorized turntable, where the Arduino runs the motor driver via serial and reads the encoder output to function as a closed-loop servo.

I just tried it again with the Arduino disconnected from the motor driver. Setting the driver to a very low output (too low for the gearmotor to turn), I can cause the position to rapidly change by tens of thousands of counts without the encoder moving at all, so the motor driver output is causing the unwanted counts. I've checked all the wiring, and there's no shorts across the motor power/encoder lines.

On the Arduino, I'm using a single interrupt to get 1/4 of full quadrature resolution (17,711 counts/rev in this system). Adapted from one of the examples in the Playground.

Interrupt handler excerpt:

#define PIN_INTERRUPT 0
#define PIN_ENCODER_B 3
long _position;
boolean _encoderBSet;

void setup()
{
  attachInterrupt(PIN_INTERRUPT, doEncoder, RISING);
}

void doEncoder()
{
  _encoderBSet = digitalReadFast(PIN_ENCODER_B); // read encoder B channel
  
  _position += _encoderBSet ? -1 : 1;
}

Sounds like you are using 1 cable for both motor control and encoder feedback. At low speed you are probably inducing a bunch of noise on the encoder lines. You need to separate(and shielding would help) the encoder and motor wiring. At higher speed the signal to the motor is cleaner and less noise is induced on the encoder wires.

Aside from the fact you are running a motor load on undersize wire (26AWG), twisted pair does not work effectiely for noise immunity on single ended loads/sources, its designed for transformer coupled balanced lines, ie no ground references. Ground potentials between motor housing and the motor power return also travel over your encoder ground which is then superimposed on the encoder signals at the recieve side. Optoisolate the encoder outputs at the arduino end. Drive the photoemitter via a suitable limiting resistor, and pull up the phototransistor collector from the arduino's local 5V supply.

What you're seeing is probably caused by capacitance between the encoder wires and the motor wires coupling the PWM signal to the encoder lines. The simplest fix is to use 2 separate cables. Otherwise, the following may help:

  1. Don't use 1 pair for motor +ve and a different pair for motor -ve. Put the +ve and -ve in a single pair. Then connect 2 such pairs in parallel.

  2. Connect a decoupling capacitor at the encoder end of the cable between its +5v and ground connections.

  3. At the Arduino end, connect a resistor between each encoder output and the corresponding Arduino pin, and a capacitor between the Arduino pin and ground. Suitable values might be 10K, and 100pF to 1nF (find the minimum capacitance that makes it work reliably, then double it). Check the the rpm reading is still correct at max rpm.