TMC26XStepper library - can't set current - possible SPI transfer issue

How's it going? This might be the wrong thread to ask this question, but hopefully someone knows about the Trinamic TMC2660 motor control chip. I am using the Mega 2560 for my project.

To start, here is the constructor for motor control:

TMC26XStepper tmc26XStepper = TMC26XStepper(200,CS,DIR,STEP,350);

All internal parameters for the chip are set via SPI. The 350 mA is the parameter to set the current that will flow through the motor coils. For mechanical reasons, I need to increase the current in order to get the motor to drive without jittering. (It's a 1.3 Amp Lin Engineering motor).

In the TMC26XStepper library (github - Trinamic), there is a function void setCurrent(unsigned long current). It seems that this can be called at any point in the program (and at best, probably not when the motor is actually running.)

When the constructor is created, setCurrent(350) is called. When I need to run the motor (for a specific scenario), I would like to set the current to 600 mA. I am unable to do so. Even when I try to set the current to 350, my program stops working. In the setup() function, the motor is driven once before the loop()function begins. It has no problem doing so.

I will show you the code, and the error (after debugging) occurs during an SPI transfer.

#include "Vial_Control.h"
#include "Arduino.h"
#include <TMC26XStepper.h>

TMC26XStepper tmc26XStepper = TMC26XStepper(200,CS,DIR,STEP,350);
// CS - 46, DIR - 44, STEP - 45

/** this function sets the initial motor settings....in relation to the current, these may be irrelevant, but you never know.  I call this in `setup()` **/

void Vial_Control::vialBegin()
{
	tmc26XStepper.setSpreadCycleChopper(2,24,8,6,0);
	tmc26XStepper.setMicrosteps(32);
	tmc26XStepper.setStallGuardThreshold(8,0);
	tmc26XStepper.start();		
	digitalWrite(direction, HIGH);	
}

/** This is the function I use to drive the motor, which can happen at any point in time during the program lifecycle.  I wish to set the current before the drive occurs. **/

void Vial_Control::selection()
{
	tmc26XStepper.setCurrent(600);
	// delay(1000) - I tried seeing if this would help, it didn't.
	moveMotor();
}

In order to keep this post from getting longer, here's the Github link to the TMC26XStepper library:
https://github.com/trinamic/TMC26XStepper

The important functions to look at in relation to my issue are

void setCurrent(unsigned long current)

and

inline void send262(unsigned long datagram)

send262 is the last function in the .cpp file.

Here's a step-by-step list of events before the error.

  1. I initiate a drive in the motor.
  2. void selection() is called.
  3. tmc26XStepper.setCurrent(600) is called.
  4. All procedures in that function run smoothly, until the end, when...
  5. the first send262(...) gets called after if (started) is evaluated.
  6. Debugging it, I find that

i_datagram = SPI.transfer((datagram >> 16) & 0xff);

gets "stuck".

Is there something that would cause the SPI transfer to get hung up like that? If you need more information, I will provide it.

Thank you,
Anthony

How are you providing power to this motor? A schematic would be useful (even a picture of a hand drawn one). The Arduino can only deliver 500ma so you might be causing the power to sag which creates all sorts of odd and strange behavior

I have a 12V input going to the TMC2660 chip (which is part of a separate smaller card that handles more power than an Arduino), and when a specific current is set via firmware, the motor is driven accordingly.
The only thing I use the Arduino for, in relation to the motor chip, is for PWM control (Direction, Step, CS).

However, in that constructor function for TMC26XStepper, I changed my initial max current setting to 800 mA. The motor turns a lot better, but gets very warm.

So my idea is to only drive more current into the motor when I need the motor to turn, and the let the holding current stay very low in comparison. 350 mA has been great so far.

My issue is that, after initialization, I am unable to set another maximum current due to some SPI conflict. Even if I set the maximum current to lower or equal to the original.

I attached a schematic, the TMC2660 circuit is on the right side. I don't know how much that will help though.

I only see CS/Direction/Step signals. Does your Arduino share a common ground with this circuit. It needs to or you could very well have poor SPI transmissions

I have the 3 SCK, MOSI, and MISO lines going to 13, 11, 12, respectively. Underneath my Arduino Mega board I hard wire those lines to 52, 51, 50, respectively. (IGNORE that the SCK and CS lines are wired incorrectly on the schematic, this is not what I have currently on my prototype board.)

And yes they share a common ground.

But do you have it grounded? You need to have a wire from the Arduino ground connected to your other board with the TMC2660 chip so everything is at a common ground reference

I made a custom board that I press right onto the Mega...it looks like the mega with all the black header connectors. On that custom board I have 2 inner layers for power and ground. The 2 ground pins on large bus on the mega get connected to my custom board, which has vias that are connected to that large ground plane. The TMC2660 chip also is connected to that ground plane.

Solved the problem: in short, set the correct SPI bits!

I probably should have mentioned I was using the Arduino as a Slave in conjunction with LabView (acting as the master).

What was happening was this:

  1. TMC26XStepper global object is created, in which setCurrent(...) function runs smoothly.

  2. After that, setup() runs, in which I set the SPCR:

    pinMode(SS, INPUT);
    pinMode(MISO, OUTPUT);
    pinMode(MOSI, INPUT);
    pinMode(SCK, INPUT);
    SPCR = (1 << SPIE) | (1 << SPE) | (0 << MSTR);
  1. When I run setCurrent(...) again, I never changed those bits to account for the role change of the Arduino (going from Slave to master).

  2. So before I set the current, I changed the bits to what I saw in the serial print during the initial TMC26XStepper object creation:

    digitalWrite(SS, HIGH);    // pull chip high before proceeding
    pinMode(SS, OUTPUT);     // change the role of the Arduino for the SPI lines
    pinMode(MISO, INPUT);
    pinMode(MOSI, OUTPUT);
    pinMode(SCK, OUTPUT);
    SPCR = (0 << SPIE) | (1 << SPE) | (1 << MSTR) | (1 << SPR0);

    tmc26XStepper.setCurrent(800);
    resetHome(val);   // this makes the motor turn via PWM.
    tmc26XStepper.setCurrent(350);  // original low current to prevent heating
    SPCR = (1 << SPIE) | (1 << SPE) | (0 << MSTR) | (0 << SPR0);  // switch to Slave mode
    pinMode(SS, INPUT);  
    pinMode(MISO, OUTPUT);
    pinMode(MOSI, INPUT);
    pinMode(SCK, INPUT);

And with that, things are working. Thanks nonetheless for your help, blh64