Motor Encoder Readings appear noisy

Board: ESP32S3 Devkit-C
Motor: 6.3:1 Metal Gearmotor 37Dx65L mm 12V with 64 CPR Encoder (Helical Pinion) from Pololu
Motor Controller: TB67H420FTG Dual/Single Motor Driver Carrier

I'm reading the encoder of a DC motor to calculate its speed for a PID algorithm. However, the speed calculation was very noisy, and it seems this is due to a noisy reading of the motor encoder. Attached is a photo of the reading from the Arduino IDE Serial Plotter, and a photo of the oscilloscope showing a correct reading (but at a different point in time) measured at the ESP32 pins

Below is the test code, which is purely the motor encoder observation. Note I am not using the interrupt for this demonstration:

#include <stdio.h>
#include <math.h>

#define ENCA 8     // motor encoder out A
#define ENCB 9     // motor encoder out B
volatile int pos_i = 0;  // position received from motor encoder

void IRAM_ATTR readMotorEncoder() {
  // Read encoder B when ENCA rises
  int b = digitalRead(ENCB);
  int increment = 0;
  if (b > 0) {
    // If B is high, increment forward
    increment = 1;
  } else {
    // Otherwise, increment backward
    increment = -1;
  }
  pos_i = pos_i + increment;
}

void setup() {
  Serial.begin(9600);  // Initialise the serial monitor
  pinMode(ENCA, INPUT);  //encoder
  pinMode(ENCB, INPUT);  //encoder

  //attachInterrupt(ENCA, readMotorEncoder, RISING);
}

void loop() {
  int testForB = digitalRead(ENCB);
  int testForA = digitalRead(ENCA);
  Serial.print("encA:");
  Serial.print(testForA);
  Serial.print(",");
  Serial.print("encB:");
  Serial.println(testForB);
}

Please post a link to encoder datasheet.

Maybe you should think about something a little less slow.

1 Like

I'm unable to locate the datasheet, but Pololu - 6.3:1 Metal Gearmotor 37Dx65L mm 12V with 64 CPR Encoder (Helical Pinion) explains the operation of the encoder quite well

Sure, I see the same issue at baud rate = 115200, which is what I am using normally.

Pololu states a 5volt Hall sensor supply (3.5volt minimum).
How did you solve that with your ESP processor.
Leo..

There is a separate supply for other modules.

12v battery->5v regulator for encoder, motor controller, and ESP32, which has its own regulator to 3v3. The board also includes a logic level shifter to bring 5v encoderOut to 3v3.

I attempted to debounce the two pins reading the encoder using 0.1uF decoupling caps.

However this lead to the serial monitor no longer functioning when the ESP32 is placed back onto the perfboard.

Yes but not well enough. Try and add 10k pullup to the encoder reading pins of the controller. An easy way is to delare the pins as INPUT_PULLUP, not only INPUT.

Cool suggestion, I have not head of INPUT_PULLUP but I looked into it and I will give it a try.

Voltage divider (resistors) or I2C level shifter (designed for I2C).
Are the hall sensors open collector?

For hall effect sensors with open collector you normally don't use level shifters.
Power the sensor from 5volt, and connect it to a pin with INPUT_PULLUP. Nothing else.
Leo..

I still cannot find a datasheet for the exact motor controller on this exact motor, but pololu also sells these encoders: Pololu - Magnetic Encoder Pair Kit with Top-Entry Connector for Micro Metal Gearmotors, 12 CPR, 2.7-18V
which mention this Hall-effect latch IC: https://www.ti.com/product/DRV5013?utm_source=google&utm_medium=cpc&utm_campaign=asc-sens-null-44700045336317194_prodfolderdynamic-cpc-pf-google-wwe_int&utm_content=prodfolddynamic&ds_k=DYNAMIC+SEARCH+ADS&DCM=yes&gad_source=1&gclid=Cj0KCQiAwvKtBhDrARIsAJj-kTg0mpGUESqN5uhxzX0s8tnGgTVFaLPYE4YOu7sKBZXKBtsmDFKUf2UaAhk5EALw_wcB&gclsrc=aw.ds
which appears to be open-drain. I need the logic-level shifter as 5v is too much for the IO pins of my board.

Open collector/drain means that the output of the sensor is like a switch to ground.
It has no switch to VCC, so there can never be 5volt on the output.

You must provide that output voltage yourself, with an external resistor to whatever voltage you want it to output. So a pull up resistor to 3.3volt gives you a 3.3volt logic signal.

The processor has these "pull up resistors" built-in, so why not use them.
If you select that with code (INPUT_PULLUP), then you don't need external resistors.

So don't use level shifters. Just use pinMode (sensorPin, INPUT_PULLUP);
Leo..

1 Like

Ah I see. The motor encoder specifies a Vcc (3.5-20V), so still actually above the limit, which is again why I chose to use 5v and shift down.

Update:
I think the issue lies in the Logic Level Shifter: https://www.sparkfun.com/products/12009
This is a bidirectional shifter that features internal pullup resistors. Currently all the inputs appear floating. I tried to add pulldown resistors of various values to the output, which helped on breadboard, but actually not on my perfboard. Adding INPUT_PULLUP as was suggested did not work. I also tried INPUT_PULLDOWN as that was what I was trying on the logic level shifter, but no dice.

Should be sold as an I2C level shifter, not as a level shifter.
Did you remove that, and connect the sensor directly to the ESP pin.
Are there any pull up resistors on that motor board.
Leo..

Thanks for the advice. I am now connecting the encoderOUT directly to esp32 IO pins configured to INPUT_PULLUP. The reading is better, but not perfect. What I mean is that perhaps 50% of each ENCB edge occurs right after an ENCA edge, and 50% of the time an edge will randomly appear, independent of the other.

How long is the wiring between sensors and ESP, and are the wires twisted.
Did you check amplitude of the pulse with your scope, and is it about 3.3volt.
If so, and it's clean, then the rest of your problem is code.
Leo..

Yes, wires are twisted, around 1.5ft. Amplitude at 3v3. Currently going over code, and seting up some test. Thank you.

Start with increasing that Serial.begin to at least 115200.
Leo..