I’m new to stepper motors (and electronics in general), so forgive me if this is obvious (or if I need to change how I post this).
My setup:
Stepperoline NMEA 17 stepper motor (https://www.omc-stepperonline.com/nema-17-bipolar-59ncm-84oz-in-2a-42x48mm-4-wires-w-1m-cable-connector-17hs19-2004s1)
TMC2209 stepper driver (BIGTREETECH-TMC2209-V1.2/TMC2209-V1.2-manual.pdf at master · bigtreetech/BIGTREETECH-TMC2209-V1.2 · GitHub)
I’m driving with a 15V power supply
HiLetgo ESP32 microcontroller (ESP-WROOM-32-Development-Microcontroller-Integrated/dp/B0718T232Z)
Powering ESP32 with USB power from laptop
I am not using any microsteps (turned off via UART control in code below). The below script moves the motor while left or right pedals are depressed and speed is controlled with a rotary encoder (and speed is displayed on an OLED screen). I have also tried moving a set number of steps or moving to a given step position, and all forms of rotation behave as described in the next paragraph (slow).
Speed control seems to work as expected up to about 80-130 steps/second, except that everything takes 2x longer than I expect to take place (at 100 steps/second I get ½ rotation in 2 seconds when I would expect 1 second). If I go over a speed of 80-130 steps/sec, the motor starts to jitter or skips steps. If I go over about 250 steps/second, it just vibrates and cannot move at all. Can anyone suggest what I might be doing wrong that prevents me from getting smooth motion over about 100 steps/second?
//define pin variables
const int cClockPed = 32;
const int ClockPed = 33;
const int dirPin = 27;
const int stepPin = 14;
const int dEncdrSpdDT=15;
const int dEncdrSpdCLK=2;
//general variables
volatile int SpeedSetting = 100; //initial speed setting, will modify with rotary encoder
long int OLEDtimer = 0;
#include <Wire.h> //for OLED
#include <Adafruit_GFX.h> //for OLED
#include <Adafruit_SH110X.h> //for OLED
#include <digitalWriteFast.h> //for digitalReadFast() function
#include <TMCStepper.h> //allows control of TMC2209 driver via UART
#include <AccelStepper.h>
//initialize AccelStepper
AccelStepper myStepper(1, stepPin, dirPin); //set up myStepper as stepper motor on AccelStepper (motor type 1)
//set up OLED
#define SCREEN_WIDTH 132 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SH1106G oled = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//UART control of TMC2209 stepper motor driver
#define SERIAL_PORT Serial2 // HardwareSerial port of ESP32
#define STALL_VALUE 255 // [0..255]
#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address
#define R_SENSE 0.11f // 0.11 for MKS TMC2209
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE, DRIVER_ADDRESS); //initialize UART control
//void to use rotary encoder to set speed
void IRAM_ATTR rotateSpeed(){
if(digitalReadFast(dEncdrSpdDT)==HIGH){//uses grounded rotary so high DT =clockwise
SpeedSetting = SpeedSetting + 10; //increment 10 steps/sec for each rotary dent
}else{
SpeedSetting = SpeedSetting - 10;}
}
void setup() {
//set up TMC2209 driver
SERIAL_PORT.begin(115200);//for UART to TMC2209
delay(200); //give time for serial port to initialize from previous line
driver.begin(); // Initialize driver
driver.toff(3); // Enables driver in software (number has to do with chopper configuration...5 is default, lower if you cannot get good top speed)
driver.microsteps(0); // Set microsteps for driver
driver.rms_current(1414); //set max RMS current (2A peak) for new Steperoline motor
driver.intpol(true); // Interpolate to 256 steps, smooth stepping even with 0 microsteps.
myStepper.setMaxSpeed(1000);
myStepper.setAcceleration(40);
//initialize OLED
oled.begin(0x3c, true); // Address 0x3C default
oled.setTextSize(2); // text size
oled.setTextColor(SH110X_WHITE); // text color
//define pins as outputs/inputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(cClockPed, INPUT_PULLUP);
pinMode(ClockPed, INPUT_PULLUP);
pinMode(dEncdrSpdCLK, INPUT_PULLUP);
pinMode(dEncdrSpdDT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(dEncdrSpdCLK), rotateSpeed, RISING); //hardware interrupt for rotary encoder uses rotateSpeed void below
}
void loop() {
//if left pedal pressed
while(digitalRead(cClockPed)==LOW){ //with input_pullup LOW = pressed
myStepper.setSpeed(-SpeedSetting);
myStepper.runSpeed();
myStepper.run();
}
//if right pedal pressed
while(digitalRead(ClockPed)==LOW){ //with input_pullup LOW = pressed
myStepper.setSpeed(SpeedSetting);
myStepper.runSpeed();
myStepper.run();
}
//update OLED (don't do every clock cycle as is time consuming)
if(millis() > OLEDtimer){ //only update 1x / second
updateOLED();
OLEDtimer = millis() + 1000;
}
}
void updateOLED(){
oled.clearDisplay(); // clear display
oled.setCursor(0, 1); // position to display
oled.print("Speed=");
oled.println(SpeedSetting);
oled.display();
}