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);
}
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.
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.
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..
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..
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..