SPI to Trinamic Drivers behaving silly

Hi everyone,

I have 4 trinamic TMC5160-BOB stepper drivers that need parameterisation over SPI.

The returned 40bit datagram is meant to have some status bits and data bits from the previous write action. See page 22 and 23 of the attached Datasheet.

Using the Uno I just get 0xFFFFFFFFFF.

Using the Mega and the same code I get 0x followed by a mirror of what I wrote. Funny thing is even having the incorrect SS pins (forgot to swap comment in code) I get the same result as when using the right SS pin assignments. (Even if I pull the connected SS pins high and pull low pins meant for Uno I get identical result, as in SS is being performed on unconnected pins so no comms could be happening because connected SS lines are pulled high in this example mistake)

The code is based on that released by the OEM of the slave devices in an example where they use the Mega. That is where I got the datagram operations and delay values. See below:

#include "SPI.h"

/* 
  const int chipX = 40 ; //Mega pins
  const int chipY = 41 ;
  const int chipZ = 42 ;
  const int chipA = 43 ;
*/

const int chipX = 3 ; //Uno pins
const int chipY = 4 ;
const int chipZ = 5;
const int chipA = 6 ;

const int enablePin = 2 ;
const int Ss = 10 ; //pin not used but Arduino SPI webpage says AVR platforms must have this set as output to prevent hardware going into slave mode 

SPISettings settingsA(2000000, MSBFIRST, SPI_MODE3);

void setup() {

  pinMode(chipX, OUTPUT) ;
  pinMode(chipY, OUTPUT) ;
  pinMode(chipZ, OUTPUT) ;
  pinMode(chipA, OUTPUT) ;
  pinMode(enablePin, OUTPUT) ;
  pinMode(Ss, OUTPUT) ;

  digitalWrite(enablePin, LOW) ;
  digitalWrite(chipX, HIGH) ;
  digitalWrite(chipY, HIGH) ;
  digitalWrite(chipZ, HIGH) ;
  digitalWrite(chipA, HIGH) ;

  /* SPI.setBitOrder(MSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    SPI.setDataMode(SPI_MODE3); */

  Serial.begin(9600);
  SPI.begin();

  sendDataX(0x00 | 0x80, 0x0000000C) ; //  TMC5160_GCONF, 0x0000000C
  sendDataX(0x6C | 0x80, 0x140100C3) ; //  TMC5160_CHOPCONF, 0x140100C3
  sendDataX(0x10 | 0x80, 0x00081F0A) ; //  TMC5160_IHOLD_IRUN, 0x00081F0A
  sendDataX(0x11 | 0x80, 0x0000000A) ; //  TMC5160_TPOWERDOWN, 0x0000000A
  sendDataX(0x13 | 0x80, 0x000001F4) ; //  TMC5160_TPWMTHRS, 0x000001F4
  Serial.print("\n");
  sendDataY(0x00 | 0x80, 0x0000000C) ; //  TMC5160_GCONF, 0x0000000C
  sendDataY(0x6C | 0x80, 0x140100C3) ; //  TMC5160_CHOPCONF, 0x140100C3
  sendDataY(0x10 | 0x80, 0x00081F0A) ; //  TMC5160_IHOLD_IRUN, 0x00081F0A
  sendDataY(0x11 | 0x80, 0x0000000A) ; //  TMC5160_TPOWERDOWN, 0x0000000A
  sendDataY(0x13 | 0x80, 0x000001F4) ; //  TMC5160_TPWMTHRS, 0x000001F4
  Serial.print("\n");
  sendDataZ(0x00 | 0x80, 0x0000000C) ; //  TMC5160_GCONF, 0x0000000C
  sendDataZ(0x6C | 0x80, 0x140100C3) ; //  TMC5160_CHOPCONF, 0x140100C3
  sendDataZ(0x10 | 0x80, 0x00081F0A) ; //  TMC5160_IHOLD_IRUN, 0x00081F0A
  sendDataZ(0x11 | 0x80, 0x0000000A) ; //  TMC5160_TPOWERDOWN, 0x0000000A
  sendDataZ(0x13 | 0x80, 0x000001F4) ; //  TMC5160_TPWMTHRS, 0x000001F4
  Serial.print("\n");
  sendDataA(0x00 | 0x80, 0x0000000C) ; //  TMC5160_GCONF, 0x0000000C
  sendDataA(0x6C | 0x80, 0x140100C3) ; //  TMC5160_CHOPCONF, 0x140100C3
  sendDataA(0x10 | 0x80, 0x00081F0A) ; //  TMC5160_IHOLD_IRUN, 0x00081F0A
  sendDataA(0x11 | 0x80, 0x0000000A) ; //  TMC5160_TPOWERDOWN, 0x0000000A
  sendDataA(0x13 | 0x80, 0x000001F4) ; //  TMC5160_TPWMTHRS, 0x000001F4
  Serial.print("\n");
  sendDataX(0x00 | 0x80, 0x0000000C) ; //  TMC5160_GCONF, 0x0000000C
  sendDataX(0x6C | 0x80, 0x140100C3) ; //  TMC5160_CHOPCONF, 0x140100C3
  sendDataX(0x10 | 0x80, 0x00081F0A) ; //  TMC5160_IHOLD_IRUN, 0x00081F0A
  sendDataX(0x11 | 0x80, 0x0000000A) ; //  TMC5160_TPOWERDOWN, 0x0000000A
  sendDataX(0x13 | 0x80, 0x000001F4) ; //  TMC5160_TPWMTHRS, 0x000001F4
}

void loop() {
  // put your main code here, to run repeatedly:
}

void sendDataX(unsigned long address, unsigned long datagram)
{
  delay(100);
  uint8_t stat;
  unsigned long i_datagram;
  SPI.beginTransaction(settingsA);
  digitalWrite(chipX, LOW);
  delayMicroseconds(10);
  stat = SPI.transfer(address);
  i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram) & 0xff);
  digitalWrite(chipX, HIGH);
  SPI.endTransaction();
  Serial.print("X: ");
  PrintHex40(stat, i_datagram);
  //Serial.print("\n");
  Serial.print(" from register: ");
  Serial.println(address, HEX);
}

void sendDataY(unsigned long address, unsigned long datagram)
{
  delay(100);
  uint8_t stat;
  unsigned long i_datagram;
  SPI.beginTransaction(settingsA);
  digitalWrite(chipY, LOW);
  delayMicroseconds(10);
  stat = SPI.transfer(address);
  i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram) & 0xff);
  digitalWrite(chipY, HIGH);
  SPI.endTransaction();
  Serial.print("Y: ");
  PrintHex40(stat, i_datagram);
  //Serial.print("\n");
  Serial.print(" from register: ");
  Serial.println(address, HEX);
}

void sendDataZ(unsigned long address, unsigned long datagram)
{
  delay(100);
  uint8_t stat;
  unsigned long i_datagram;
  SPI.beginTransaction(settingsA);
  digitalWrite(chipZ, LOW);
  delayMicroseconds(10);
  stat = SPI.transfer(address);
  i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram) & 0xff);
  digitalWrite(chipZ, HIGH);
  SPI.endTransaction();
  Serial.print("Z: ");
  PrintHex40(stat, i_datagram);
  //Serial.print("\n");
  Serial.print(" from register: ");
  Serial.println(address, HEX);
}

void sendDataA(unsigned long address, unsigned long datagram)
{
  delay(100);
  uint8_t stat;
  unsigned long i_datagram;
  SPI.beginTransaction(settingsA);
  digitalWrite(chipA, LOW);
  delayMicroseconds(10);
  stat = SPI.transfer(address);
  i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram) & 0xff);
  digitalWrite(chipA, HIGH);
  SPI.endTransaction();
  Serial.print("A: ");
  PrintHex40(stat, i_datagram);
  //Serial.print(i_datagram,HEX);
  //Serial.print("\n");
  Serial.print(" from register: ");
  Serial.println(address, HEX);
}

void PrintHex40(uint8_t stat, uint32_t data) // prints 40-bit data in hex with leading zeroes
{
  char tmp[16];
  uint16_t LSB = data & 0xffff;
  uint16_t MSB = data >> 16;
  sprintf(tmp, "0x%.2X%.4X%.4X", stat, MSB, LSB);
  Serial.print(tmp);
}

This is the serial feed (erroneous from Uno):

X: 0x0000000000 from register: 80
X: 0xFFFFFFFFFF from register: EC
X: 0xFFFFFFFFFF from register: 90
X: 0xFFFFFFFFFF from register: 91
X: 0xFFFFFFFFFF from register: 93

Y: 0xFFFFFFFFFF from register: 80
Y: 0xFFFFFFFFFF from register: EC
Y: 0xFFFFFFFFFF from register: 90
Y: 0xFFFFFFFFFF from register: 91
Y: 0xFFFFFFFFFF from register: 93

Z: 0xFFFFFFFFFF from register: 80
Z: 0xFFFFFFFFFF from register: EC
Z: 0xFFFFFFFFFF from register: 90
Z: 0xFFFFFFFFFF from register: 91
Z: 0xFFFFFFFFFF from register: 93

A: 0xFFFFFFFFFF from register: 80
A: 0xFFFFFFFFFF from register: EC
A: 0xFFFFFFFFFF from register: 90
A: 0xFFFFFFFFFF from register: 91
A: 0xFFFFFFFFFF from register: 93

And this is the serial feed using the Mega (with mega pin assignments uncommented and Uno commented out):

X: 0x0000000000 from register: 80
X: 0xEC140100C3 from register: EC
X: 0x9000081F0A from register: 90
X: 0x910000000A from register: 91
X: 0x93000001F4 from register: 93

Y: 0x800000000C from register: 80
Y: 0xEC140100C3 from register: EC
Y: 0x9000081F0A from register: 90
Y: 0x910000000A from register: 91
Y: 0x93000001F4 from register: 93

Z: 0x800000000C from register: 80
Z: 0xEC140100C3 from register: EC
Z: 0x9000081F0A from register: 90
Z: 0x910000000A from register: 91
Z: 0x93000001F4 from register: 93

A: 0x800000000C from register: 80
A: 0xEC140100C3 from register: EC
A: 0x9000081F0A from register: 90
A: 0x910000000A from register: 91
A: 0x93000001F4 from register: 93

My mind is about to explode

datasheet.pdf (924 KB)

Anyone? :frowning: :frowning: :frowning:

BHKent:
Anyone? :frowning: :frowning: :frowning:

DID YOU EVEN CHECK YOU WERE USING THE RIGHT SPI PINS???

https://www.arduino.cc/en/reference/SPI

MOSI | MISO | SCK | SS
Uno = 11 12 13 10
Mega = 51 50 52 53

Why is your address a unsigned long??

Isn’t it actually only 8 bit long??

void sendDataY(unsigned long address, unsigned long datagram)
{
  delay(100);
  uint8_t stat;
  unsigned long i_datagram;
  SPI.beginTransaction(settingsA);
  digitalWrite(chipY, LOW);
  delayMicroseconds(10);
  stat = SPI.transfer(address);
  i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
  i_datagram <<= 8;
  i_datagram |= SPI.transfer((datagram) & 0xff);
  digitalWrite(chipY, HIGH);
  SPI.endTransaction();
  Serial.print("Y: ");
  PrintHex40(stat, i_datagram);
  //Serial.print("\n");
  Serial.print(" from register: ");
  Serial.println(address, HEX);
}

@BHKent Did you get it right? Did it work?