gin66 / FastAccelStepper

A high speed stepper library for Atmega 168/328p (nano), Atmega32u4, Atmega 2560, ESP32, ESP32S2, ESP32S3, ESP32C3 and Atmel SAM Due
MIT License
282 stars 67 forks source link

Inconsistent Pulse Output on ESP32 #240

Closed Samthecoolman closed 3 months ago

Samthecoolman commented 3 months ago

Howdy,

While playing around with the fastAccel library I found that I was getting inconsistent step outputs from my ESP32 dev board. Switching to different dev boards results in the same issue, have not tested on AVR.

Using a scope to probe the step output I can verify this issue is not my servo motor (Yellow is step output, blue is enable): scope

I only have a moderate understanding of Cpp so I am sure there could be an issue with my code, however after spending countless hours trying to debug I have no clue where to proceed from here.

Here is the snippit of my code (Modified example sketch);

#include "FastAccelStepper.h"

// As in StepperDemo for Motor 1 on AVR
//#define dirPinStepper    5
//#define enablePinStepper 6
//#define stepPinStepper   9  // OC1A in case of AVR

// As in StepperDemo for Motor 1 on ESP32
#define dirPinStepper 18
#define enablePinStepper 26
#define stepPinStepper 19

FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *stepper = NULL;

void setup() {
  Serial.begin(115200);
  engine.init();
  stepper = engine.stepperConnectToPin(stepPinStepper);
  if (stepper) {
    stepper->setDirectionPin(dirPinStepper);
    stepper->setEnablePin(enablePinStepper);
    stepper->setAutoEnable(true);

    // If auto enable/disable need delays, just add (one or both):
    stepper->setDelayToEnable(50);
    stepper->setDelayToDisable(50);

    stepper->setSpeedInHz(5000);  
    stepper->setAcceleration(100000);

  }
}

void loop() {

  stepper -> moveTo(1600);
  while(stepper -> isRunning()) {Serial.println(stepper->getCurrentPosition());}
  delay(50);

  stepper -> moveTo(0);
  while(stepper -> isRunning()) {Serial.println(stepper->getCurrentPosition());}
  delay(50);

}

Any help would be greatly appriciated!

gin66 commented 3 months ago

Your code looks good and the result is surprising.

Questions:

Samthecoolman commented 3 months ago

Thanks for the quick reply!

Something else that is interesting is that after running for ~30 minutes the steps become consistant?

gin66 commented 3 months ago

could you please upgrade to 0.30.10 ? Even the Changelog does not list a related issue, it is better to use the latest version.

Samthecoolman commented 3 months ago

Upgraded my version and the inconsistancy appears to have been resolved, however there is slight drift in setpoints over time. I am waiting on some level shifters to arrive, so missed steps here could be chalked up to my servo needing 5 instead of 3.3 volts.

gin66 commented 3 months ago

sounds good and thanks for support.

With an esp32 you could use a free pulse counter using stepper-> attachToPulseCounter((7). This allows to verify, if pulses are lost on uC side or not. expectation is: no pulses lost

Samthecoolman commented 3 months ago

Had some time to continue working on this project and the issue is still present; attatching a pulse counter verifies that steps were lost during movement, inconsistency is present in both directions. Code is here:

#include "FastAccelStepper.h"

// As in StepperDemo for Motor 1 on AVR
//#define dirPinStepper    5
//#define enablePinStepper 6
//#define stepPinStepper   9  // OC1A in case of AVR

// As in StepperDemo for Motor 1 on ESP32
#define dirPinStepper 18
#define enablePinStepper 26
#define stepPinStepper 19

FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *stepper = NULL;

void setup() {
  Serial.begin(115200);
  engine.init();
  stepper = engine.stepperConnectToPin(stepPinStepper);
  if (stepper) {
    stepper->setDirectionPin(dirPinStepper);
    stepper->setEnablePin(enablePinStepper);
    stepper->setAutoEnable(true);

    // If auto enable/disable need delays, just add (one or both):
    stepper->setDelayToEnable(50);
    stepper->setDelayToDisable(50);

    stepper->setSpeedInHz(5000);  
    stepper->setAcceleration(10000);
    stepper-> attachToPulseCounter(7);

  }
}

void loop() {

  stepper -> moveTo(1600);
  while(stepper -> isRunning()) {Serial.println(stepper->getCurrentPosition());}
  Serial.println(stepper -> readPulseCounter());
  delay(500);

  stepper -> moveTo(0);
  while(stepper -> isRunning()) {Serial.println(stepper->getCurrentPosition());}
  Serial.println(stepper -> readPulseCounter());
  delay(500);

}
gin66 commented 3 months ago

Sorry to hear that. I have set up an esp32 with a digital scope connected and I cannot reproduce your issue with either example code.:

FastAccelStepper uses mcpwm/pcnt module for the first six allocated steppers and then rmt module. The mcpwm/pcnt combo uses a feedback loop: mcpwm generates steps and pcnt counts those. The theory is, that the pcnt-module gets input from the actual pin. So any noise on the pin could lead to wrong counts. To verify this, please try:

If this does not help, then it will get tricky.

Samthecoolman commented 3 months ago

Using rmt module seems to fix it, I will do some more testing to verify stability.

Thanks for the help!