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

Library not generating steps on Arduino Nano ESP32 #254

Closed ham-a7 closed 2 months ago

ham-a7 commented 2 months ago

I am using an Arduino Nano ESP32 and a TMC2130 motor driver to drive a NEMA 17 stepper motor. I am controlling the motor with a step and direction pin (the enable pin is ignored). The problem is that the ESP32 appears to not be outputting any pulses from the step pin. I have tried versions 0.30.0 and 0.28.4 of the library from the Arduino library manager. Also the same problem on 0.30.12 on from Platformio. I have attached my firmware below. I program the TMC2130 registers with SPI, then I setup the stepper object and then try to move the motor in the main loop.

The library appears to think it is outputting steps as the position attribute is updated as expected (the firmware prints "Current position 0" and "Current position 300" to the serial monitor) however the motor does not move. I measure 0V DC with a voltmeter when I try to measure the voltage on the step pin while the library says it is moving suggesting no steps are being output.

The motor turns when I manually pulse the step pin without the library (see the commented out code in the main loop below). I also measure 1.6V DC voltage on the step pin suggesting steps are successfully being generated during manual pulsing (1.6V DC is expected from 3.3V logic). I have also tried digital Pins 10, 9 and 6 with the same result - no steps output with the library but I can manually pulse the step pin to move the motor.

I have managed to get the library to work on an Arduino Nano Classic with the same hardware and firmware (using pins 9 or 10 for steps).

The fact that the hardware works without the library and that I can get the library to work with the Nano Classic suggests that I have configured the library incorrectly for the ESP32. I have read the readme for the library and also the markdown documentation here however I am not sure what I might have done wrong.

Am I missing some important configuration for using the library with an Arduino Nano ESP32?

Thanks for your help.

#include <FastAccelStepper.h>
#include <SPI.h>

//TMC2130 registers
#define WRITE_FLAG     (1<<7) //write flag
#define READ_FLAG      (0<<7) //read flag
#define REG_GCONF      0x00
#define REG_GSTAT      0x01
#define REG_IHOLD_IRUN 0x10
#define REG_CHOPCONF   0x6C
#define REG_COOLCONF   0x6D
#define REG_DCCTRL     0x6E
#define REG_DRVSTATUS  0x6F
#define COOLTHRS       0x14
#define REG_PWNCONF    0x70
#define REG_TPWMTHRS   0x13

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

#define dirPinStepper    20   // Connect to the correct pin
#define stepPinStepper   6   // Make sure this is an OC1A/OC1B pin (Pin 9 or 10)
#define CS_X_PIN   4 

uint8_t tmc_write(uint8_t cmd, uint32_t data, int motor_CS_pin){
  // Write to TMC2130 registers.
  uint8_t s;
  digitalWrite(motor_CS_pin, LOW);
  s = SPI.transfer(cmd);
  SPI.transfer((data>>24UL)&0xFF);
  SPI.transfer((data>>16UL)&0xFF);
  SPI.transfer((data>> 8UL)&0xFF);
  SPI.trnsfer((data>> 0UL)&0xFF);
  digitalWrite(motor_CS_pin, HIGH);
  return s;
  }

void setup_motor_driver(int motor_CS_pin){
  //set TMC2130 config
  tmc_write(WRITE_FLAG|REG_GCONF, 0b100000101UL, motor_CS_pin); //voltage on AIN is current reference
  tmc_write(WRITE_FLAG|REG_IHOLD_IRUN, 0b1000000010000UL, motor_CS_pin); //IHOLD=0x10, IRUN=0x10
  tmc_write(WRITE_FLAG|REG_PWNCONF, 0b0001010000010010000000, motor_CS_pin);
  tmc_write(WRITE_FLAG|COOLTHRS, 0b1000000000000, motor_CS_pin);
  tmc_write(WRITE_FLAG|REG_COOLCONF, 0b000001110000000000000000, motor_CS_pin); // Set stall threshold value.
  tmc_write(WRITE_FLAG|REG_CHOPCONF,   0x05008008UL, motor_CS_pin); //  8 microsteps, MRES=0, TBL=1=24, TOFF=8
  }

void setup_stealth(int motor_CS_pin){
  delay(500);
  tmc_write(WRITE_FLAG|REG_GCONF,      0b100000101UL, motor_CS_pin); //voltage on AIN is current reference
  tmc_write(WRITE_FLAG|REG_IHOLD_IRUN, 0b1000000000000UL, motor_CS_pin); //IHOLD=0x10, IRUN=0x10
  tmc_write(WRITE_FLAG|COOLTHRS, 0b0000000000000, motor_CS_pin);
  tmc_write(WRITE_FLAG|REG_TPWMTHRS, 0b00000000000000000000, motor_CS_pin);
}

void setup() {
  pinMode(stepPinStepper, OUTPUT);
  digitalWrite(stepPinStepper, LOW);
  pinMode(CS_X_PIN, OUTPUT);
  digitalWrite(CS_X_PIN, HIGH);
  delay(1000);
  Serial.begin(9600);
  delay(1000);

  //init SPI
  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000UL, MSBFIRST, SPI_MODE3));
  Serial.println("Setup drivers");
  setup_motor_driver(CS_X_PIN);
  setup_stealth(CS_X_PIN);

  //init stepper
  engine.init();
  stepper = engine.stepperConnectToPin(stepPinStepper);
  delay(1000);
  if (stepper) {
    stepper->setDirectionPin(dirPinStepper);
    stepper->setSpeedInHz(500); // Adjust as necessary
    stepper->setAcceleration(500); // Adjust as necessary
    stepper->moveTo(300); // Move to position 1000
  }
}

void loop() {
  // digitalWrite(stepPinStepper, HIGH);
  // delayMicroseconds(300);
  // digitalWrite(stepPinStepper, LOW);
  // delayMicroseconds(300);
  if (stepper) {
    if (!stepper->isRunning()) {
      long position = stepper->getCurrentPosition();
      Serial.print("Current Position: ");
      Serial.println(position);
      if (position == 300) {
        stepper->moveTo(0);
      } else {
        stepper->moveTo(300);
      }
    }
  }
}
gin66 commented 2 months ago

Please check this. I assume, that‘s the issue.

Besides, the arduino library manager is broken. Latest version is 0.30.12

ham-a7 commented 2 months ago

OK thank you, I have managed to get it to work. The correct pin definitions are:

#define dirPinStepper    20   // Pin D20 on Nano ESP32
#define stepPinStepper   9   // Pin D6 on Nano ESP32
#define CS_X_PIN   4 // Pin D4 on Nano ESP32

Though I find this quite confusing as it only works if the step pin is defined as the native ESP32 GPIO while the CS and direction pins have to be defined as the Nano digital pin. Is there something in the library that means the step pin has to be defined as the native ESP32 GPIO pin?

It would make sense to me if everything stuck to one convention or if you could choose your convention as opposed to a mix. I have been using the "By Arduino Pin (Default)" Pin Numbering Scheme in the Arduino IDE. Switching to "By GPIO Number (Legacy)" forces everything to the ESP32 GPIO pin number.

gin66 commented 2 months ago

Happy to hear, that you have been able to make it work. So enjoy FastAccelStepper on Arduino nano esp32. Please ensure to use the latest 0.30.12 instead of the arduino library manager provided „latest“ version.

ham-a7 commented 2 months ago

I still seem to be having problems with pin definitions for the Nano ESP32. I am trying to control 4 motors: X, Y, Z and R. I can control X, Y and R fine but when I add the definition for the Z motor, the motors stop working. They all work fine individually which suggests I am trying to share pins between motors. I am using different pin numbers for each motor however.

Confusingly, I can only get X, Y and R to work when I define their step pins as the GPIO pin number of the ESP32 chip but their direction and chip select pins as their Arduino Nano pin number (using the "Arduino Nano Pin Numbering (default)" pin numbering scheme). I tried just using the ESP32 GPIO pin numbers for all of the pins with the "By GPIO Number (legacy)" scheme but it did not work.

Can you please clarify what pin definitions I should use?

My pin numbers are in the table below. I have been using Arduino's pinout diagram for the pin numbers. I have also attached my code pin definitions and the code that moves the motors.

Signal Nano Pin ESP32 GPIO Pin
X Step D10 21
X Dir D18 2
X CS D8 17
Y Step D9 18
Y Dir D19 3
Y CS D7 10
Z Step D6 9
Z Dir D20 4
Z CS D4 7
R Step D5 8
R Dir D21 11
R CS D17 1

Pin definitions:

#define STEP_X_PIN   21   
#define DIR_X_PIN   18    
#define CS_X_PIN   8 

#define STEP_Y_PIN   18   
#define DIR_Y_PIN   19    
#define CS_Y_PIN   7 

#define STEP_Z_PIN   9   
#define DIR_Z_PIN   20    
#define CS_Z_PIN   4 

#define STEP_R_PIN   8   
#define DIR_R_PIN   21    
#define CS_R_PIN   17 

Stepper initialisation:

  // Init steppers
  engine.init();
  Xstepper = engine.stepperConnectToPin(STEP_X_PIN);
  Ystepper = engine.stepperConnectToPin(STEP_Y_PIN);
  Zstepper = engine.stepperConnectToPin(STEP_Z_PIN);
  Rstepper = engine.stepperConnectToPin(STEP_R_PIN);

  if (Xstepper) {
    Xstepper->setDirectionPin(DIR_X_PIN);
    Xstepper->setSpeedInHz(150000); 
    Xstepper->setAcceleration(150000);
  }

  if (Ystepper) {
    Ystepper->setDirectionPin(DIR_Y_PIN);
    Ystepper->setSpeedInHz(150000); 
    Ystepper->setAcceleration(150000); 
  }

  if (Zstepper) {
    Zstepper->setDirectionPin(DIR_Z_PIN);
    Zstepper->setSpeedInHz(150000); 
    Zstepper->setAcceleration(150000); 
  }

  if (Rstepper) {
    Rstepper->setDirectionPin(DIR_R_PIN);
    Rstepper->setSpeedInHz(150000); 
    Rstepper->setAcceleration(150000); 
  }

Motor control code:

void move_motors(){
    Xstepper->moveTo(X_demand_position);
    Ystepper->moveTo(Y_demand_position, true);
    Zstepper->moveTo(Z_demand_position, true);
    Rstepper->moveTo(R_demand_position, true);
}
gin66 commented 2 months ago

FastAccelStepper assumes, the pin numbers for step and dir to be the gpio-values as espressif32 is using it. The mess happening on Arduino Nano esp32 can not be fixed by the lib developers. If this „legacy“ setting fixes this mess in a correct way, I cannot tell.

Sorry I cannot help you further, just advise to make sure to use the latest lib version from github. Not the outdated version as is delivered by Arduino library manager. Best to switch to platformio.

gin66 commented 2 months ago

The rmt-driver uses a less complex setup of the esp32 hw modules. This driver can be selected with the second parameter to connectToStepperPin()

ham-a7 commented 2 months ago

OK thanks for your help. I am using the latest version on Platformio. I managed to get it to work by adding the DRIVER_RMT setting to each stepper's engine.stepperConnectToPin(STEP_X_PIN, DRIVER_RMT) definition. I defined the Step pins as the GPIO pins on the ESP32 chip however I defined the Direction and Chip Select pins as the Arduino Nano pin numbers. It would not work if I defined the direction pin as the GPIO pin on the espressif32 as you suggested. Why is that?

It is very frustrating, why do the correct pin values change with a different driver setting? There appears to be no logic to it. Is it an issue with the Arduino Nano ESP32?

gin66 commented 2 months ago

The issue from my perspective: Arduino Nano esp32 has an incompatible pin numbering, just to get nice numbers on board level. If they are not able to make the sw-sdk right, they should not have created that mess. Now indirectly requesting the library makers to waste their own time to adjust to their messed-up setup is crazy.

ham-a7 commented 2 months ago

OK is the Library not compatible with the Arduino Nano ESP32?

gin66 commented 2 months ago

The library is compatible with ESP32, ESP32S2, ESP32S3, ESP32C3. Out there is a plethora of boards using those derivates and it just works. Therefore the compatibility with Arduino Nano esp32 is given on uC-level, too. Now the maker of Arduino Nano esp32 has messed up and included a layer of incompatibility. They claim the legacy mode shall be compatible. If you say, the legacy mode is still not working, then apparently the legacy mode is broken. This is not an issue of the library. So the maker of the Arduino Nano esp32 should fix it.

So you can file a bugreport with them.

ham-a7 commented 2 months ago

I see, I am inclined to think I am doing something wrong before I submit a bug report to Arduino.

Do you think I could have configured something incorrectly or I have done something else incorrectly? Thanks for your help.