ESP32 PWM 'hiccups' when controlling DC motor with SimpleDCMotor

Hello,

I’m using SimpleDCMotor to control a 12V DC motor, via a 2_PWM H-bridge, using an ESP32-S2 microcontroller (An Adafruit Feather). An AS5600 encoder is providing feedback.

It’s all working wonderfully (including the AS5600!), so thank you to everyone involved in such an awesome library.

My problem, however, us that the DC motor occasionally ‘hiccups’ … this looks like an unexpected velocity spike when I use motor.monitor(). It appears entirely at random whilst I’m controlling the motor using the ‘dc-velocity’ example code.

The simplest scenario I can create that replicates this bug, is if I create a new code sketch that “manually” PWMs the motor (see code below):

void loop() {
  if (micros() - prevMicros >= interval) {
    prevMicros = micros();
    motorPinState = !motorPinState;
    digitalWrite(motorPin, motorPinState);
  }
}

With this code running, the motor experiences a velocity spike / hiccup regularly every 2 seconds, like clockwork. The spikes are identical to the ones I see when using the SimpleDCMotor library.

If I change the code to this, the spikes/hiccups disappear:

void loop() {
  analogWrite(motorPin, 128);
}

I’ve ruled out other potential causes of the problem:

  1. Not the DC power supply – it is powerful enough with a generous safety factor. I can replicate the same bug using different power supplies, and even a battery.
  2. Not Encoder problems and Not SimpleFOC library problems – I can replicate the bug with the very simple PWM code above.

My theory is that the ESP32-S2 is doing something in the background that is interrupting the code, causing a particular pulse in the PWM scheme to be too long, causing the velocity to increase momentarily. I’ve tried disabling the watchdog timer (which I really don’t want to do), but the behaviour remains.

A complicating factor is that I see that the ESP32-S2 doesn’t have MCPWM, and only a single core. Could this be a root cause, and if I replace my board with a ‘normal’ ESP32, might the problem go away?

Has anyone here experienced this problem with the ESP32-S2, and might you have any other suggestions? Thank you!

PS. I’ll try to get a Serial.plotter screenshot of the voltage spikes later today, and post here.

Here’s a screenshot from the Arduino IDE’s Serial Plotter, showing the target velocity in blue, and the actual velocity in orange (both in radians per second). The firmware is using SimpleDCMotor to ramp the velocity up and down. The sudden spike downwards in velocity reported by the encoder is clearly visible.

Again, I do not believe this is a problem with the encoder or the library - the symptoms are represented in the very simple PWM code above.

Hi @aranFish ,

Glad to hear that it is working in principle!

I wonder if the glitch coincides with the rollover of the micros() counter? Would you be able to check that somehow?

The velocity control needs a feedback loop, and has to calculate the PID to get the output, so it needs to do more than just analogWrite().

But if you used open loop mode then the DCDriver isn’t doing anything more really than setting the PWM. You could compare to see if open loop mode also has the problem?

Hi @runger, thanks for your reply and suggestions.

I believe an unsigned long using micros() should roll over every 71.6 minutes (2^32–1 microseconds), so I don’t think it should be a rollover - that’s a lot longer than the ~2 second time period between spikes I’m experiencing with my very simple manual PWM code example.

Good idea with the open loop - I’ll try that out and report back.

Interestingly, I powered my DC motor with an off-the-shelf speed controller, but left the encoder wired up to my ESP32 running SimpleDCMotor to get the Serial Plotter output. I saw the same occasional hiccups! So at least I’m not alone in experiencing this problem :slight_smile:

You’re right, it can’t be the micros overflow then…

The fact that it would happen also with the other speed controller would indicate that it isn’t to do with the driver or PWM level of things. Perhaps it’s more of an issue with the sensor and/or its driver?

Thinking on it a bit more, the velocity is spiking downwards, but seemingly not below zero - in terms of the code that would happen if the position remained the same, or the time interval became long compared to the position change.

In terms of the ESP32s built in functions interfering, there are build flags you could use to run your code on the other core if your MCU is dual core… because I think there are some background tasks which can interfere with the real time operations.

Thanks for the continued thoughts on the matter @runger.

I think the ESP32-S2 is single core. Playing with build flags is a good next step - I need to bring up Visual Studio and PlatformIO on my laptop, and I’ll have a play. I’ve been using the Arduino IDE only so far.

For now, I’ve had to hand over the motor electronics to my friend to integrate with the rest of the machine. He’s reported that the hiccups do not interfere with the operation of the machine, so that’s good, but in general I’d like to find a fix for this, next time I get my hands on the electronics.

I’m not quite following where the problem is coming from. It’s not surprising that you’d get interruptions in your manual PWM test code, but as far as I know, all the SimpleFOC hardware-specific implementations use hardware PWM. So if analogWrite works, then it should work.

See if you can figure out which implementation of _writeDutyCycle2PWM is being used. Some of the hardware-specific files have a #pragma that prints “SimpleFOC: compiling for x” to the log when doing a clean build, but esp32_mcu.cpp does not. But it’s all MCPWM code, so I think the #if defined(SOC_MCPWM_SUPPORTED) up top would blank it out and fall back to generic_mcu.cpp. But that uses analogWrite, so I don’t know why it would behave any differently when you call analogWrite directly.

Thanks @dekutree64 , when I have my next opportunity to get back on the project, I’ll take a look inside the library files and see what I can dig up. I will also obtain a drop-in ESP32 replacement board, to replace the ESP32-S2 board that I’m using, so I can start using MCPWM too.

To clarify a little bit:

The ESP32 chips will fall back to LEDC driver if MCPWM is not available. That’s not quite as good as MCPWM but still much better than analogWrite…

For the DC motor, LEDC should be fine.

The glitch we’re investigating occurs also with other drivers in combination with the SimpleFOC sensor, so I don’t think we’re looking at problems in the PWM output but rather in the sensor input or velocity calculations.