Stepper Motor speed increases on its own

dfrenkel
Posts: 12
Joined: Sun Jul 22, 2018 1:52 pm

Stepper Motor speed increases on its own

Postby dfrenkel » Wed Aug 11, 2021 7:20 am

In order to run a stepper motor, I am using an Arduino library (AccelStepper) that's been ported to ESP-IDF

Normally, it pulses GPIO 13 at a rate of 500 pulses per second.

However, after a period of time (maybe 30-60 minutes), the ESP32 decides to change it on its own to 50,000 pulses per second! Again, completely on its own.

The strangest part of this is that I cannot figure out why this suddenly changes. But if I reset the device, it goes back to normal. Then 1 hour later, it automatically changes again to a similar number, around 40,000 per second.

I used an oscilloscope to verify that the ESP32 does in fact send all pulses, but just extremely fast.

My code is below, but I suspect the issue to be in the AccelStepper port I am using. https://github.com/sdobz/AccelStepper-e ... tepper.cpp

However, the port works great for an hour, so I cannot even figure out what to do. I'll looked all through it and it works great in Arduino

I have spent close to 40 hours trying to figure this out, and it is one of the strangest issues I've ever had. Where is this ghost that's changing things!

Can anyone point me in a direction, I am so desperate for an answer. Thank you


Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_system.h"
#include "esp_spi_flash.h"

#include "driver/uart.h"
#include "driver/gpio.h"

#include "AccelStepper.h"
#include "TMCStepper.h"

#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"

#define MOTOR_UART_NUM UART_NUM_2
#define RXD2_PIN GPIO_NUM_16
#define TXD2_PIN GPIO_NUM_17
#define BUF_SIZE 1024

#define STEP_PIN GPIO_NUM_13
#define DIR_PIN GPIO_NUM_14
#define ENABLE_PIN GPIO_NUM_27

#define STALLGUARD GPIO_NUM_2
#define BUTTON1 GPIO_NUM_23
#define BUTTON2 GPIO_NUM_34

#define SERIAL_PORT_2    Serial2    // TMC2208/TMC2224 HardwareSerial port
#define DRIVER_ADDRESS   0b00       // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE          0.10f      // R_SENSE for current calc.  

volatile long move_to_position = 0;
volatile bool run_motor = false;

xQueueHandle gpio_evt_queue = NULL;

AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
TMC2209Stepper driver(MOTOR_UART_NUM, R_SENSE, DRIVER_ADDRESS);


void MotorTask( void *pvParameters );
TaskHandle_t MotorTaskTask;

//Interrupts
void IRAM_ATTR button1start(void *arg)
{
   move_to_position = 0;
   run_motor = true;
}

void IRAM_ATTR button2start(void *arg)
 {
   move_to_position = 500;
   run_motor = true;
 }

void motor_uart_init(void)
{
  printf("Loading UART\n");
  uart_config_t uart_config = {
      .baud_rate = 115200,
      .data_bits = UART_DATA_8_BITS,
      .parity = UART_PARITY_DISABLE,
      .stop_bits = UART_STOP_BITS_1,
      .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
      .source_clk = UART_SCLK_APB,
  };
  uart_driver_install(MOTOR_UART_NUM, BUF_SIZE * 2, 0, 0, NULL, 0);
  uart_param_config(MOTOR_UART_NUM, &uart_config);
  uart_set_pin(MOTOR_UART_NUM, TXD2_PIN, RXD2_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}

void ISR_init(void)
{
  gpio_pad_select_gpio(STALLGUARD);
  gpio_set_direction(STALLGUARD, GPIO_MODE_INPUT);

  gpio_pad_select_gpio(BUTTON1);
  gpio_set_direction(BUTTON1, GPIO_MODE_INPUT);

  gpio_pad_select_gpio(BUTTON2);
  gpio_set_direction(BUTTON2, GPIO_MODE_INPUT);

  gpio_pad_select_gpio(STEP_PIN);
  gpio_set_direction(STEP_PIN, GPIO_MODE_OUTPUT);

  gpio_pad_select_gpio(DIR_PIN);
  gpio_set_direction(DIR_PIN, GPIO_MODE_OUTPUT);

  gpio_pad_select_gpio(ENABLE_PIN);
  gpio_set_direction(ENABLE_PIN, GPIO_MODE_OUTPUT);

  gpio_set_intr_type(STALLGUARD, GPIO_INTR_POSEDGE);
  gpio_set_intr_type(BUTTON1, GPIO_INTR_NEGEDGE);
  gpio_set_intr_type(BUTTON2, GPIO_INTR_NEGEDGE);


  //create a queue to handle gpio event from isr
  gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));

  //install gpio isr service
  gpio_install_isr_service(0);

  //hook isr handler for specific gpio pin

  gpio_isr_handler_add(BUTTON1, button1start, (void *)BUTTON1);
  gpio_isr_handler_add(BUTTON2, button2start, (void *)BUTTON2);
}

void setup(void)
{ 
  printf("Starting Setup\n");
  driver.begin();
  driver.pdn_disable(true);
  driver.mstep_reg_select(true);
  driver.toff(4);
  driver.blank_time(24);
  driver.I_scale_analog(false);
  driver.internal_Rsense(false);
  driver.rms_current(300); 
  driver.SGTHRS(30);
  driver.microsteps(0);//
  driver.TCOOLTHRS(300);
  driver.TPWMTHRS(0);
  driver.semin(0);
  driver.shaft(true);  
  driver.en_spreadCycle(false);
  
  stepper.setMinPulseWidth(3);
  stepper.setEnablePin(ENABLE_PIN);
  stepper.setPinsInverted(false, false, true);
  stepper.disableOutputs();

  xTaskCreatePinnedToCore(
      MotorTask
      , "MotorTask"
      , 1024 * 4
      , NULL
      , 5
      , &MotorTaskTask
      , 1);
}


extern "C" void app_main(void)
{
    printf("Loading\n");
    motor_uart_init();
    ISR_init();
    setup();
    printf("Load Complete\n");
}

void feedTheDog()
{
  // feed dog 0
  TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; // write enable
  TIMERG0.wdt_feed=1;                       // feed dog
  TIMERG0.wdt_wprotect=0;                   // write protect
  // feed dog 1
  TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; // write enable
  TIMERG1.wdt_feed=1;                       // feed dog
  TIMERG1.wdt_wprotect=0;                   // write protect
}

void move_motor(void)
{
  printf("Acceleration: %f\n", stepper.getAccel());
  printf("Max Speed: %f\n", stepper.getMaxSpeed());
  printf("CurrentPosition: %li\n", stepper.currentPosition());

  stepper.setAcceleration(300);
  stepper.setMaxSpeed(500);
  
  stepper.moveTo(move_to_position);
  printf("Current Position: %li\n", stepper.currentPosition());
  printf("Target Position: %li\n", stepper.targetPosition());
  stepper.enableOutputs();

    while (stepper.currentPosition() != stepper.targetPosition())
    {
      stepper.run();
      feedTheDog();
    }

  stepper.disableOutputs();
  printf("Moved To New Position: %li\n", stepper.currentPosition());

}

void MotorTask(void *pvParameters) // Motor Task
{
  (void)pvParameters;
  printf("MotorTask\n");

  for (;;)
  {
    if (run_motor == true)
    {
      printf("Begin MotorTask\n");
      move_motor();
      printf("End MotorTask\n");
      run_motor = false;
    }
    else
    {
      vTaskDelay(10); 
    }
  }
}

User avatar
fasani
Posts: 195
Joined: Wed Jan 30, 2019 12:00 pm
Location: Barcelona
Contact:

Re: Stepper Motor speed increases on its own

Postby fasani » Wed Aug 18, 2021 1:25 pm

Looks like a very hairy issue.
But can't you add some output parameters via Serial and leave it connected, just to see if you can detect what is changing automatically?
Since it's a component port that comes from Arduino, the part that calls my attention is that they are using esp_timer_get_time() instead of the Arduino millis() (Or whatever is using)
But I would start researching from there and dumping some stuff to the Serial. Eventually it just get's off gradually and you don't have to wait one hour to see the motor going crazy. That's my 0.2 cents, another important thing will be to compare the Arduino CPP with the original Arduino library, and check if there is something obviously wrong.
Also maybe it's interesting to make your own controller using MCPWM. But I really do not have experience using Trinamic drivers, I just know some printers use them, and they are really silent :)
epdiy collaborator | http://fasani.de Fan of Espressif MCUs and electronic design

Who is online

Users browsing this forum: Google [Bot] and 255 guests