TMC2208 Stepper Drivers as replacement to A4988 trouble

Hello,
I am using a version of an Arduino CNC board that is found here to drive 4 wheels on a small wheeled robot. The shield came with A4988 stepper drivers and I got them to work fine, however the motors were much louder than intended so I went searching for another driver and found the TMC2208. I saw that the pin-outs were the same as long as the boards themselves aligned the enable pins on the shield.

The problem however seems to be in the code though. I am using the Accelstepper library in my code and everything works fine with the A4988 driver board. When I swapped just the boards, nothing happened in my program. I went looking on the TMCStepper library git to try and find some help. I managed to at lease get the steppers working using a version of the 'Simple' example. I tried to take out as much as possible while still being able to move the motors so that I could use it in my actual program. I still am not having any luck.

When I run this program

#include <TMCStepper.h>

#define EN_PIN           8 // Enable
#define DIR_PIN1         5 // Direction
#define STEP_PIN1       2 // Step
#define DIR_PIN2         6 // Direction
#define STEP_PIN2       3
#define DIR_PIN3         7 // Direction
#define STEP_PIN3       4
#define DIR_PIN4         13 // Direction
#define STEP_PIN4       12

#define SW_RX1            55 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX1            60 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define SW_RX2            56 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX2            61
#define SW_RX3            57 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX3            62
#define SW_RX4            58 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX4            63

#define R_SENSE 0.11f // Match to your driver

TMC2208Stepper driverX(SW_RX1, SW_TX1, R_SENSE);
TMC2208Stepper driverY(SW_RX1, SW_TX1, R_SENSE);
TMC2208Stepper driverZ(SW_RX1, SW_TX1, R_SENSE);
TMC2208Stepper driverA(SW_RX1, SW_TX1, R_SENSE); // Software serial

void setup() {
  pinMode(EN_PIN, OUTPUT);
  pinMode(STEP_PIN1, OUTPUT);
  pinMode(DIR_PIN1, OUTPUT);
  pinMode(STEP_PIN2, OUTPUT);
  pinMode(DIR_PIN2, OUTPUT);
  pinMode(STEP_PIN3, OUTPUT);
  pinMode(DIR_PIN3, OUTPUT);
  pinMode(STEP_PIN4, OUTPUT);
  pinMode(DIR_PIN4, OUTPUT);
  digitalWrite(EN_PIN, LOW);      // Enable driver in hardware

  driverX.begin();
  driverY.begin();
  driverZ.begin();
  driverA.begin();                //  SPI: Init CS pins and possible SW SPI pins
                                  // UART: Init SW UART (if selected) with default 115200 baudrate

  driverX.microsteps(16);          // Set microsteps to 1/16th

}
void loop() {
  // Run 5000 steps and switch direction in software
  for (uint16_t i = 5; i>0; i++) {
    digitalWrite(STEP_PIN1, HIGH);
    digitalWrite(STEP_PIN2, HIGH);
    digitalWrite(STEP_PIN3, HIGH);
    digitalWrite(STEP_PIN4, HIGH);
    delayMicroseconds(160);
    digitalWrite(STEP_PIN1, LOW);
    digitalWrite(STEP_PIN2, LOW);
    digitalWrite(STEP_PIN3, LOW);
    digitalWrite(STEP_PIN4, LOW);
    delayMicroseconds(160);
  }

the motors just continuously spin, so I know that the drivers actually work.

My main code is below.

#include <AccelStepper.h>
#include <TMCStepper.h>


const int stepperCount = 4;
AccelStepper BLStepper(AccelStepper::DRIVER, 2, 5);
AccelStepper FLStepper(AccelStepper::DRIVER, 3, 6);
AccelStepper FRStepper(AccelStepper::DRIVER, 4, 7);
AccelStepper BRStepper(AccelStepper::DRIVER, 12, 13);

#define R_SENSE 0.11f

// define pins numbers
#define stepX_PIN      2
#define dirX_PIN       5
#define stepX_RX      55
#define dirX_TX       60

#define stepY_PIN      3
#define dirY_PIN       6
#define stepY_RX      56
#define dirY_TX       61

#define stepZ_PIN      4
#define dirZ_PIN       7
#define stepZ_RX      57
#define dirZ_TX       62

#define stepA_PIN      12
#define dirA_PIN       13
#define stepA_RX      58
#define dirA_TX       63

#define enPin_PIN         8

TMC2208Stepper driverX(stepX_RX, dirX_TX, R_SENSE);
TMC2208Stepper driverY(stepY_RX, dirY_TX, R_SENSE);
TMC2208Stepper driverZ(stepZ_RX, dirZ_TX, R_SENSE);
TMC2208Stepper driverA(stepA_RX, dirA_TX, R_SENSE);


//Front left wheel
//const int stepX_PIN = 2;
//const int dirX_PIN  = 5;

//Front right wheel
//const int stepY_PIN = 3;
//const int dirY_PIN  = 6;

//Back left wheel
//const int stepZ_PIN = 4;
//const int dirZ_PIN  = 7;

//Back right wheel
//const int stepA_PIN = 12;
//const int dirA_PIN  = 13;
//const int enPin_PIN = 8;


char split = ':';         //this is the character that would be used for seperating the different parts of your commands
                          //the syntax for commands would be:   command:value1:value2

int listSize = 5;                                     //the amount of commands in the list
String commands[] = {"hello", "add", "sub", "YMOV", "XMOV"};     //the list of every command name


void setup()
{
  Serial.begin(115200);     //sets the data transfer rate for the serial interface
                          //9600 is good for basic testing, but should be as high
                          //as possible for both devices
  FRStepper.setMaxSpeed(300);
  FRStepper.setAcceleration(200);
  BRStepper.setMaxSpeed(300);
  BRStepper.setAcceleration(200);
 
  FLStepper.setMaxSpeed(300);
  FLStepper.setAcceleration(200);
  BLStepper.setMaxSpeed(300);
  BLStepper.setAcceleration(200);

  pinMode(stepX_PIN, OUTPUT);
  pinMode(dirX_PIN, OUTPUT);
 
  pinMode(stepY_PIN, OUTPUT);
  pinMode(dirY_PIN, OUTPUT);
 
  pinMode(stepZ_PIN, OUTPUT);
  pinMode(dirZ_PIN, OUTPUT);

  pinMode(stepA_PIN, OUTPUT);
  pinMode(dirA_PIN, OUTPUT);

  pinMode(enPin_PIN, OUTPUT);

  digitalWrite(enPin_PIN, LOW);
  digitalWrite(dirX_PIN, HIGH);
  digitalWrite(dirY_PIN, HIGH);
  digitalWrite(dirZ_PIN, HIGH);
  digitalWrite(dirA_PIN, HIGH);
  //digitalWrite(stepX_PIN, HIGH);
  //digitalWrite(stepY_PIN, HIGH);
  //digitalWrite(stepZ_PIN, HIGH);
  //digitalWrite(stepA_PIN, HIGH);

  driverX.begin();
  driverY.begin();
  driverZ.begin();
  driverA.begin();

  FRStepper.setEnablePin(enPin_PIN);
  FLStepper.setEnablePin(enPin_PIN);
  BRStepper.setEnablePin(enPin_PIN);
  BLStepper.setEnablePin(enPin_PIN);

  FRStepper.enableOutputs();
  FLStepper.enableOutputs();
  BRStepper.enableOutputs();
  BLStepper.enableOutputs();

}

void loop()
{
  CommCheck();  //checks serial buffer for data commands
  runMotors();
 
}

void runMotors()
{

  if ((FLStepper.distanceToGo() != 0) || (FRStepper.distanceToGo() != 0) || (BLStepper.distanceToGo() != 0) || (BRStepper.distanceToGo() != 0))
  {
    FRStepper.enableOutputs();
    FLStepper.enableOutputs();
    BRStepper.enableOutputs();
    BLStepper.enableOutputs();
    FLStepper.run();
    BLStepper.run();
    FRStepper.run();
    BRStepper.run();
   
    if ((FLStepper.distanceToGo() == 0) && (FRStepper.distanceToGo() == 0))
    {
      CommConfirm();
    }
  }
 
  //if (movementComplete == true)
  //{
    //CommConfirm();
  //}
  //if (
  //if ((FLStepper.distanceToGo() == 0) || (FRStepper.distanceToGo() == 0) || (BLStepper.distanceToGo() == 0) || (BRStepper.distanceToGo() == 0))
  //{
    //CommConfirm();
  //}
}
void CommCheck()
{
  if(Serial.available())                    //checks to see if there is serial data has been received
  {
    //int len = Serial.available();           //stores the character lengh of the command that was sent
                                             //this is used for command parsing later on
                                           
    String command = Serial.readString();   //stores the command as a text string
    int len = command.length();
    //Serial.println(command);
    Serial.flush();
    //command.remove(len-2,1);                //removes characters added by the pi's serial data protocol
    //command.remove(0,2);
    //len -= 3;                               //updates the string length value for parsing routine

    int points[2] = {0, 0};                 //offset points for where we need to split the command into its individual parts
   
    for(int x = 0; x < len; x++)            //this loop will go through the entire command to find the split points based on
    {                                       //what the split variable declared at the top of the script is set to.
      //Serial.print("Char ");
      //Serial.print(x);
      //Serial.print("- ");
      //Serial.println(command[x]);
      if(command[x] == split)               //this goes through every character in the string and compares it to the split character
      {
        if(points[0] == 0)                  //if the first split point hasn't been found, set it to the current spot
        {
          points[0] = x;
        }
        else                                //if the first spot was already found, then set the second split point
        {                                   //this routine is currently only set up for a command syntax that is as follows
          points[1] = x;                    //command:datavalue1:datavalue2
        }
      }
    }
    CommParse(command, len, points[0], points[1]);      //now that we know the command, command length, and split points,
  }                                                     //we can then send that information out to a routine to split the data
}                                                       //into individual values.

void CommParse(String command, int len, int point1, int point2)
{
  //Serial.print("Command Length: ");
  //Serial.println(len);
  //Serial.print("Split 1: ");
  //Serial.println(point1);
  //Serial.print("Split 2: ");
  //Serial.println(point2);

 
  String com = command;                 //copy the full command into all 3 parts
  String val1 = command;                //this is needed for the string manipulation
  String val2 = command;                //that follow

  com.remove(point1, len - point1);     //each of these use the string remove to delete
  val1.remove(point2, len - point2);    //the parts of the command that aren't needed
  val1.remove(0, point1 + 1);           //basically splitting the command up into its
  val2.remove(0, point2 + 1);           //individual pieces
  val2.remove(val2.length()-1,1);

  CommLookup(com, val1, val2);    //these pieces are then sent to a lookup routine for processing
}


void CommLookup(String com, String val1, String val2)
{
 
  int offset = 255;                   //create a variable for our lookup table's offest value
                                      //we set this to 255 because there won't be 255 total commands
                                      //and a valid command can be offset 0, so it's just to avoid
                                      //any possible coding conflicts if the command sent doesn't
                                      //match anything.
                                     
  for(int x = 0; x < listSize; x++)   //this goes through the list of commands and compares
  {                                   //them against the command received
    if(commands[x] == com)
    {
      offset = x;                     //if the command matches one in the table, store that command's offset
    }
  }
 
  switch(offset)                //this code compares the offset value and triggers the appropriate command
  {
    case 0:                                 //essentially a hello world.                       |  Syntax: hello:null:null
      CommHello();                          //this activates the hello world subroutine        |  returns Hello!
      break;
    case 1:                                 //adds both values together and return the sum.    |  Syntax: add:value1:value2
      CommAdd(val1.toInt(), val2.toInt());  //this activates the addition subroutine           |  returns value1 + value2
      break;
    case 2:                                 //subtracts both values and return the difference  |  Syntax: subtract:value1:value2
      CommSub(val1.toInt(), val2.toInt());  //this activates the subtraction subroutine        |  returns value1 - value2
      break;
    case 3:
      yMovement(val1.toInt(), val2.toInt());
      break;
    case 4:
      xMovement(val1.toInt(), val2.toInt());
    default:                                        //this is the default case for the command lookup and will only
      Serial.println("Command not recognized");     //trigger if the command sent was not known by the arduino
      break;
  }
}


void CommHello()                               //each of these routines are what will be triggered when they are successfully processed
{
  Serial.println("Hello!");
  CommConfirm();
}

void CommAdd(int val1, int val2)
{
  Serial.println(val1 + val2);
  CommConfirm();
}

void CommSub(int val1, int val2)
{
  Serial.println(val1 - val2);
  CommConfirm();
}

void yMovement(int val1, int val2)
{
  if (val1 < 0) {
    //Serial.println("YMOVNEG");
    int yMoveNew = (val1 * (-20.72));
    //Serial.println(val1 * (-1));
    //delay(500);
   
    FRStepper.move(-yMoveNew);
   
    BRStepper.move(-yMoveNew);
   
    FLStepper.move(-yMoveNew);
   
    BLStepper.move(-yMoveNew);
  }

  else {
    //Serial.println(val1);
    int yMoveNew = (val1 * (20.72));
    //Serial.println(yMoveNew);
    //Serial.println(val1);
    //delay(500);
    FRStepper.move(yMoveNew);
   
    BRStepper.move(yMoveNew);
   
    FLStepper.move(yMoveNew);
   
    BLStepper.move(yMoveNew);
  }

}

void xMovement(int val1, int val2)
{
  if (val1 < 0) {
    //Serial.println(val1);
    int xMoveNew = (val1 * (-20.72));
    //Serial.println(xMoveNew);
    //Serial.println(val1 * (-1));
    //delay(1000);
    FLStepper.move(-xMoveNew);
   
    BLStepper.move(xMoveNew);

    FRStepper.move(xMoveNew);

    BRStepper.move(-xMoveNew);

    //delayMicroseconds(500);
  }

  else {

    int xMoveNew = (val1 * (20.72));
    //Serial.println(val1);
    //delay(1000);
    FLStepper.move(xMoveNew);

    BLStepper.move(xMoveNew);

    FRStepper.move(xMoveNew);

    BRStepper.move(xMoveNew);

    //delayMicroseconds(500);
   
  }
}
void CommConfirm()                                  
{                                                    
  Serial.println("Done");
  delay(750);
 
}

When I run my code, a Pi sends two values that equals step counts, however with the new drivers nothing happens. I tried also looking at and following the AccelStepper example on the git but I guess I have something wrong.

Any help would be appreciated.

Hi @plasticblaze
there are some differences between the drivers, I don't know how this would affect your project.
Differences are marked in red.
You will have to assess these differences.

RV mineirin

Yes I have seen that but I believe my issue lies in my program. Maybe where I'm setting up the drivers themselves through the accelstepper library vs. the tmcstepper library

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.