1

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.

0 Answers0