I am writing some code to count the U/V/W encoder signals from a BLDC eScooter motor. The encoder signals from my motor seem to be rather noisy, which I can see on my digital analyzer. However, my code works as expected on the Teensy 3.5 chip, seeing the encoder fire signals in the expected order with no transient signals. However, when I changed to the Teensy 4.1 chip, I found that I get transient signals that are duplicating a previously fired signal or a signal out of order. My motor encoders are at 5v, so I use a level shifter to bring them down to 3.3 to connect to the Teensy 4.1 pins. Is there something about the Teensy 4.1 that would cause it to be more susceptible to noise?
Here are the major excerpts of my code:
The interrupt handlers for the V and W encoders look exactly the same, only the variable names are changed to protect the innocent. If you want to see the full source, you can find it here.
I took the step of running the encoder signals through a schmitt trigger, and that helped by cleaning up the signal somewhat. But on the Teensy 4.1 I still get some number of transients.
Any advice or insight appreciated.
-Mark
Here are the major excerpts of my code:
Code:
//// pin assignments
// Teensy 3.5/4.0/4.1 - These assignments work across all versions
const uint8_t PWM_SPEED_PIN(2);
const uint8_t BRAKE_PIN(3);
const uint8_t MOTOR_DIR_PIN(4);
const uint8_t LED_BUILTIN_PIN(13);
const uint8_t U_ENCODER_SIGNAL_PIN(14); // yellow - Ha - U
const uint8_t V_ENCODER_SIGNAL_PIN(15); // blue - Hb - V
const uint8_t W_ENCODER_SIGNAL_PIN(16); // green - Hc - W
const uint8_t BUTTON_PIN(23);
volatile int32_t tickCount;
volatile int32_t uCount;
volatile int lastUVal;
volatile int32_t vCount;
volatile int lastVVal;
volatile int32_t wCount;
volatile int lastWVal;
volatile char lastEncoder;
...
pinMode(U_ENCODER_SIGNAL_PIN, INPUT);
lastUVal = digitalRead(U_ENCODER_SIGNAL_PIN);
attachInterrupt(U_ENCODER_SIGNAL_PIN, countUTick, CHANGE);
pinMode(V_ENCODER_SIGNAL_PIN, INPUT);
lastVVal = digitalRead(V_ENCODER_SIGNAL_PIN);
attachInterrupt(V_ENCODER_SIGNAL_PIN, countVTick, CHANGE);
pinMode(W_ENCODER_SIGNAL_PIN, INPUT);
lastWVal = digitalRead(W_ENCODER_SIGNAL_PIN);
attachInterrupt(W_ENCODER_SIGNAL_PIN, countWTick, CHANGE);
/**
Interrupt handler for the U encoder signal.
**/
void countUTick() {
// Read the current signal value
int val = digitalRead(U_ENCODER_SIGNAL_PIN);
// Check for an encoder fault
bool encoderFault = (lastEncoder == 'U') || // Last encoder was this one
(lastEncoder == 'W' && motorContext.motorDirection) || // Last encoder was W, but going forward
(lastEncoder == 'V' && !motorContext.motorDirection); // Last encoder was V, but going reverse
//if (encoderFault) {
DebugMsgs.notification().print("U ").print(lastUVal).print(' ').print(val).print(' ')
.print(lastEncoder).println(encoderFault ? " *" : "");
//}
// If there is a fault, don't record a tick.
if (encoderFault) { return; }
int increment = (lastEncoder == 'W') ? 1 : -1;
uCount += increment;
tickCount += increment;
lastEncoder = 'U';
lastUVal = val;
}
The interrupt handlers for the V and W encoders look exactly the same, only the variable names are changed to protect the innocent. If you want to see the full source, you can find it here.
I took the step of running the encoder signals through a schmitt trigger, and that helped by cleaning up the signal somewhat. But on the Teensy 4.1 I still get some number of transients.
Any advice or insight appreciated.
-Mark
Last edited by a moderator: