TMC2209 stepping extremely slow

I have been struggling to get my stepper to actually move at a decent clip speed. It is supposed to step at a speed that is relative to a 0-1023 input. After days of help on discord and debugging I have finally got the driver to step the damn stepper but i'v gotten nowhere on the speed other then people saying you need to get rid of microsteps even though im set at 16. my code is as follows. I am unsure if something in the code is off or not. I do know that in the map functions if the input is 1023 then the motor should be going quicker than it does

const uint8_t MEGA_EN = 4;
const uint8_t EN_PIN = 5;
const uint8_t DIR_PIN = 2;
const uint8_t STEP_PIN = 3;
const uint8_t UP_PIN = A0;
const uint8_t DOWN_PIN = A1;

uint8_t upSpeed;
uint8_t downSpeed;
uint8_t upInput;
uint8_t downInput;

void setup() {
  pinMode(EN_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(MEGA_EN, INPUT);
  pinMode(EN_PIN, OUTPUT);
  //Serial.begin(115200);
}

void loop() {
    digitalWrite(EN_PIN, !digitalRead(MEGA_EN));
    upInput = analogRead(UP_PIN);
    downInput = analogRead(DOWN_PIN);


  //Serial.print(" UP_PIN");
  //Serial.print(upInput);
  //Serial.print("   DOWN_PIN   ");
  //Serial.println(downInput);


  if (analogRead(upInput) > 40) {
    upSpeed = map(analogRead(upInput), 0, 1023, 5000, 5);
    digitalWrite(DIR_PIN,LOW);
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(upSpeed);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(upSpeed);
  }
  if (analogRead(downInput) > 40) {
    downSpeed = map(analogRead(downInput), 0, 1023, 5000, 5);
    digitalWrite(DIR_PIN, HIGH);
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(downSpeed);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(downSpeed);
  }

}

If the input is 1023, the upSpeed/downSpeed will be 5us and the stepper motors will be asked to perform 100,000 steps per second, I think.

I suspect that no normal mechanical motor can achieve that. I'm not sure most Arduino could either. What model of Arduino are you using?

You should develop your code in even smaller steps.

This means:
using a testcode that has a fixed speed in a range that is known that almost any stepper-motor can rotate at this speed.

If you want more detailed advice you have to post more details about

  • your stepper-motor
  • how do you power your stepper-motor voltage max current of your power-supply?
  • to what coil-current is the TMC2209 adjusted?
  • a picture of how you have things wired together

did you damage your TMC2209 through voltage-spikes??

  • answering the question if you connected / disconnected the motorwires while power was switched on because this causes high voltage spikes that can damage the TMC2209-driver

You should always switch power off before connecting / disconnecting the motorwires

This is a simple demo-code that creates 1 pulse per millisecond.
at 1/16 steps this should make the stepper-motor rotate at

200 * 16 / 1000 * 60 = 192 rpm

const uint8_t MEGA_EN = 4;
const uint8_t EN_PIN = 5;
const uint8_t DIR_PIN = 2;
const uint8_t STEP_PIN = 3;
const uint8_t UP_PIN = A0;
const uint8_t DOWN_PIN = A1;

unsigned long stepDelay = 500;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup Start");
  pinMode(EN_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(MEGA_EN, INPUT);
  pinMode(EN_PIN, OUTPUT);

  // don't know what level is needed to enable
  // choose the correct one
  //digitalWrite(EN_PIN, LOW); 
  //Serial.println("EN_PIN, LOW");

  //digitalWrite(EN_PIN, HIGH);
  //Serial.println("EN_PIN, HIGH");
}

void loop() {

  Serial.println("DIR_PIN, LOW");
  digitalWrite(DIR_PIN, LOW);
  for (int i = 0; i < 32000; i++) {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(stepDelay);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(stepDelay);
  }

  Serial.println("DIR_PIN, HIGH");
  digitalWrite(DIR_PIN, HIGH);
  for (int i = 0; i < 32000; i++) {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(stepDelay);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(stepDelay);
  }
}

You create one step per loop cycle. So stepping speed depends on your loop cycle time, not (only) on your delayMicroseconds. The analogRead() function needs considerable time.

And this is wrong:

    upInput = analogRead(UP_PIN);
...
if (analogRead(upInput) > 40) {
    upSpeed = map(analogRead(upInput), 0, 1023, 5000, 5);

The second and third analogRead tries to read from a pin that is shurely not existing ( the pin number you use is the result of the first analogRead - but that's not a pin number ).

almost forgot

welcome to the arduino-forum.
well done posting your code as a code-section in your very first posting.

The following as not at all meant as "beating on you" it is meant as advice to proceed faster.
Maybe my assumptions are wrong. If they are wrong I apologise for beeing wrong.

Well if it took you days to get the steper-motor working at all my guessing is:

very ineffective communication.

Of course I haven't read this discord conversation but if you did it similar to how you do

  • just for entertainment - chatting on WhatsApp, SnapChat or something similar I am very sure it was ineffective.

In programming and in electronic a lot of details are important.
You need quite a lot knowledge to know which details are really important and which not.
Hence you have to be precise and detailed to get things working.

I'm pretty sure that you agree and will follow the way how to solve your problem mimimum 200 minutes faster.
This requires to invest 20 minutes of your precious time to read how to speedup solving your problems.

Directly after registering you got presented informations how to speed up solving your problem.
You should really read it.

best regards Stefan

What RPM are you looking for?

Sorry for the late reply here. So basically i'm using pin A0 and A1 to receive an input from a mega 2560 that is either from 0-255 this program then i guess maps those inputs from a 0-1023 range. That range is then supposed to control the speed for the motors with the downSpeed and Upspeed variables. I am extremely new to coding, I can basically only define basic variables. This is not my code it is somebody elses code that I, with the help of others modified. As of yesterday I have new code that communicates in UART but I believe is still very limited.

This is a new post for my previous post about getting my nano to control a stepper driver. I have included UART control in this program but I believe the loop portion is still fundamentally flawed. Basically the nano is getting control commands from a Mega2560 that runs specific firmware. The nano get an enable input on pin 4 which is then relayed to pin 5. The enable needs to be set High as default unless it is driven low by the pin 4. Pin A0 and Pin A1 are also inputs from a mega that range from 0-255 to tell the driver whether or not it needs to clockwise or counterclockwise and the speed is determined by the 0-255. It then maps that range to 0-1023 which is guess is what the driver can read. There is a damper built in in the loop at set at 30. unless either input is driven to more than 30 then the input is then driven.

Keep in mind this is technically not my code as I know very little about coding at all and can only define variables. I have used compare and contrast skills to setup the UART part of the code. After setting that up i believe that I need more parts in this code now. I would like to add a delay on bootup before sending the config over UART to the driver. I also think that is somebody decides to change the microstep values in the code on their own personal setup then the delays will be different per the microstep setting. I have no idea how to geet around this in code but I believe it could be done with somebody who has more knowledge than I do.

#include <TMCStepper.h>
#include <SoftwareSerial.h>

const uint8_t MEGA_EN = 4;
const uint8_t EN_PIN = 5;
const uint8_t DIR_PIN = 2;
const uint8_t STEP_PIN = 3;
const uint8_t UP_PIN = A0;
const uint8_t DOWN_PIN = A1;

uint8_t upSpeed;
uint8_t downSpeed;
uint8_t upInput;
uint8_t downInput;

#define SW_TX 7
#define SW_RX 8
#define DRIVER_ADDRESS 0b00
#define R_SENSE 0.11f

SoftwareSerial SoftSerial(SW_RX, SW_TX);
TMC2209Stepper TMCdriver(&SoftSerial, R_SENSE, DRIVER_ADDRESS);

void setup() {
  pinMode(EN_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(MEGA_EN, INPUT);
  pinMode(EN_PIN, OUTPUT);
  Serial.begin(115200);
  SoftSerial.begin(115200);

  TMCdriver.begin();
  TMCdriver.toff(5);
  TMCdriver.rms_current(100);
  TMCdriver.microsteps(16);

  TMCdriver.en_spreadCycle(false);
  TMCdriver.pwm_autoscale(true);

}

void loop() {
    digitalWrite(EN_PIN, !digitalRead(MEGA_EN));
    upInput = analogRead(UP_PIN);
    downInput = analogRead(DOWN_PIN);


  Serial.print(" UP_PIN");
  Serial.print(upInput);
  Serial.print("   DOWN_PIN   ");
  Serial.println(downInput);
  Serial.print("  MEGA_EN  ");
  Serial.print("EN_PIN  ");

  if (analogRead(upInput) > 40) {
    upSpeed = map(analogRead(upInput), 0, 1023, 10000, 100);
    digitalWrite(DIR_PIN,LOW);
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(upSpeed);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(upSpeed);
  }
  if (analogRead(downInput) > 40) {
    downSpeed = map(analogRead(downInput), 0, 1023, 10000, 100);
    digitalWrite(DIR_PIN, HIGH);
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(downSpeed);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(downSpeed);
  }

}

Why did you start a new topic for the same subject ?

1 Like

because I couldn't find the edit button on the orignal post and I can't delete the orignal post either

You did not need to find an edit button. All you needed to do was to reply to your own topic

I will merge the two topics

DONE

The mega those pins are connected to sends a PWM signal to the nano which would be a 0-255 value. the mega uses its own specific firmware that I know nothing about but its called mobiflight.

I have spent some time learning but I am still at the very beginning of knowing anything complicated I have working on this for going on a week now and I only have just gotten UART to communicate. As far as getting into something as complicated as this I was given a code that was supposed to just work but it doesn't in my case so I was kinda forced into having to figure this out.

.

.

so please spend more time on learning

You should post this code as a code-section

No it is not a value in the sense of digits. It is a longer or shorter pulse-length that changes between 0,00V and 5,00V for a longer or shorter time

This one of two dozen places where you have not yet enough knowledge
The 0% to 100% dutycycles relate to 0 up to 255

The microcontroller-world is NOT superstandardised like USB-devices.

You have to take care of a lot more details than just

"does the plug fit into the socket?"

You have to know more about the details.

as you have experiences now:
either you replicate an original project with each and every dammed detail beeing the ultra-hyper-exact the same
or
it doesn't work.
Because the micrcontroller-world is not superstandardised.

If you want to make a deviating hardware work this needs a quite a lot knowledge
Either inside your head
or
by posting all the details to the forum so other can have a very close look and thoroughly deep analysis

I have replicated everything but the type of driver I am using. the guide calls for the TB6600 but that thing is so noisy its useless. so I switched to a TMC2209. I also am attempting to change the guide in a sense that they want to use standalone mode on the driver and I want to use UART shouldn't be that much of a change fundamentally. I managed to get UART working in the code with very little help. as far as the numbers are concerned I understand that the values are not coming in as numbers they are coming in as a waveform in the form of a voltage but I don't know what the voltage is the each and every PWM cycle. I have most of the electrical knowledge in my head but I don't have alot of the coding knowledge in my head. I also am not very good at writing.

So basically this would have to be digitalRead? ChatGPT says you can use analogread because PWM is just a rapidly changing voltage. which is basically what an analog signal is?

#include <TMCStepper.h>
#include <SoftwareSerial.h>

// Pin Definitions
#define A0_PIN A0
#define A1_PIN A1
#define DIR_PIN 2
#define STEP_PIN 3
#define ENABLE_PIN_CONTROL 4
#define ENABLE_PIN_DRIVER 5
#define RX_PIN 7
#define TX_PIN 8

// TMC2209 Settings
#define R_SENSE 0.11f // Match to your driver's R_Sense value
#define CURRENT 900 // Motor current in mA
#define MICROSTEPS 8 // Update to 8 microsteps
#define THRESHOLD 40 // Minimum threshold for movement

// Serial communication
SoftwareSerial softSerial(RX_PIN, TX_PIN);
TMC2209Stepper driver(&softSerial, R_SENSE, 0b00);

void setup() {
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(ENABLE_PIN_CONTROL, INPUT);
  pinMode(ENABLE_PIN_DRIVER, OUTPUT);
  
  // Default to disabled state
  digitalWrite(ENABLE_PIN_DRIVER, HIGH);

  // Start the serial communication
  Serial.begin(115200);
  softSerial.begin(115200);

  // TMC2209 Driver configuration
  driver.begin();
  driver.toff(5);
  driver.blank_time(24);
  driver.rms_current(CURRENT);
  driver.microsteps(MICROSTEPS); // Set to 8 microsteps
  driver.en_spreadCycle(false); // Disable spreadCycle

  // Optional configurations, commented out for later use
  // driver.TCOOLTHRS(0xFFFFF); // 20bit max
  // driver.semin(5);
  // driver.semax(2);
  // driver.sedn(0b01);
  // driver.sg_stall_value(0);

  Serial.println("TMC2209 initialized successfully.");
}

void loop() {
  int a0Value = analogRead(A0_PIN); // Read PWM signal on A0
  int a1Value = analogRead(A1_PIN); // Read PWM signal on A1
  bool enableSignal = digitalRead(ENABLE_PIN_CONTROL);

  if (enableSignal == LOW) {
    digitalWrite(ENABLE_PIN_DRIVER, LOW); // Enable stepper
  } else {
    digitalWrite(ENABLE_PIN_DRIVER, HIGH); // Disable stepper
    return; // Exit the loop early if stepper is disabled
  }

  if (a0Value > THRESHOLD && a1Value > THRESHOLD) {
    // Both inputs active, remain stationary
    return;
  }

  int speed;
  bool direction;

  if (a0Value > THRESHOLD) {
    speed = map(a0Value, THRESHOLD, 1023, 0, 1023);
    direction = false; // One direction
  } else if (a1Value > THRESHOLD) {
    speed = map(a1Value, THRESHOLD, 1023, 0, 1023);
    direction = true; // Opposite direction
  } else {
    // Neither input active enough, remain stationary
    return;
  }

  digitalWrite(DIR_PIN, direction);
  
  // Calculate delay between steps
  int stepDelay = map(speed, 0, 1023, 2000, 50); // Adjust the range as needed
  
  // Step the motor
  digitalWrite(STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(STEP_PIN, LOW);
  delayMicroseconds(stepDelay);
}

I have done my best in getting chat GPT to spit some kind of altered code out and this is what I get.

Apparently this needs to be repeated:

You cannot use ChatGPT to write code that you are not capable of writing yourself.

ChatGPT is really good at coming up with answers that look good. Not so good at coming up with answers that are actually correct. You're wasting your time with it. Unless you're already proficient in what you're asking it about, you can't tell when it's just made stuff up!

1 Like

ok so what i'm getting out of these responses is don't even bother you don't know shit yet. is this pretty what this is going to devolve into. I need to go take a college couse on c++ at which point I can start asking question?

I don't think this is really jumping over my head I think this is just some basic controlling a stepper i'm not trying to put a man on venus here.

I'm going to believe an actual person but none of my questions are being answered. I asked whether to use digitalread but IDK if that got glossed over.

So this is a detail-question that can be answered and will be answered

digitalRead() delivers either HIGH or LOW
nothing inbetween.

So for reading in a switch-position beeing on or off digitalRead() is the function to use.

digitalRead() can't be used for a "analog" signal = a voltage that can change from 0,0V up in small steps to 5.0V