ASM (Part 2) - Trinamic Motion Control using Arduino

Table of contents

ASM (Part 2) - Trinamic Motion Control using Arduino

Abstract

In this tutorial I will explain how to control the Trinamic Motor Controller using Arduino. I used SPI protocol for communicating with Trinamic Motor Controller board and I tested both velocity and position mode for running the stepper motor.

Introduction

In my project I need to control the stepper motor very precisely based on the sensor value. So, the motor needs to control by custom program or firmware. The Landungsbruecke board came with a preloaded firmware that is good for testing, experimenting and tuning of the motor driver but not for a custom application. For satisfying my requirement I need to write my own code and run it in the ARM Cortex - M4 based GigaDevice GD32F425VGT6, the MCU of the Landungsbruecke board. I have no previous experiment on working with GigaDevice MCU. So, I want to develop and test the code in Arduino first before writing the code for GD32F425VGT6 MCU. It helps me to better understand and debug my code. After developing a working code I will modify it for GD32F425VGT6 MCU. 

The TMC5272 Trinamic Motor Controller has an extensive datasheet and user manual. But writing a program by reading a device datasheet is very tedious and time consuming and requires advance understanding on both software and hardware. Rather it is always easy to start with a sample code without writing from scratch. Fortunately, TMC5272 has official C code for Arduino platform and supports both SPI and UART protocol. I downloaded the code from the GitHub and modified the code by removing unnecessary parts for me. 

Connecting with Arduino

The TMC5272 motion controller supports both SPI and UART. The C code I downloaded implemented both the protocol. I connected an Arduino MEGA with the TMC5272 board following the configuration shown in the code. The connection is as follows:

Arduino Mega Pins
TMC5272 Eval Board Pins
51 MOSI 32 SPI1_SDI
50 MISO 33 SPI1_SDO
52 SCK 31 SPI1_SCK
53 SS 30 SPI1_CSN
GND 23 CLK16 -> use internal
23 DIO 19 nSleep
GND 2 GND
+5V 5 +5V_USB
27 iRefR2 35 IREF_R2
29 iRefR3 36 IREF_R3
31 uartMode 20 USEL

For initial testing I did not change any connection. The following photo shows my connection between Arduino and TMC5272 Eval board:

image

Running Motor in Velocity Mode

I directly uploaded the code provided by Analog Devices for the TMC5272 Motion Controller. The motor was started to rotate at a moderate speed and I was very happy to see because that happened without any difficulties. Watch the short video below:

Running in Position Mode

The demo code was written for driving the motor in velocity mode and in the video the motor is running in velocity mode. But for my project I need to control the motor in position mode and I want to control the TMC5272 using SPI. So, I removed all the code related to UART to make it clean. Then I made the necessary configuration on the code to drive the motor in position mode. I initialized the RAMPMODE register with zero for activating position mode as per the datasheet recommendation. 

image

Then I set the maximum velocity and acceleration in VMAX and AMAX register respectively. I wrote the target position to M0_XTARGET register and expected to run the motor. But unfortunately it was not working. I read the related registers to understand what was the problem. The registers value was as expected.  

image   

I initialized the M0_VSTART and M0_VSTOP according to the datasheet but still not working. I set V1, V2, D1, D2 but nothing special was happening. So, I disconnected the TMC5272 Eval board from Arduino and connected to the Landungsbrucke board again for further understanding and monitoring all the related registers. Soon, I realized that I need to set a value for M0_DMAX register for running the motor in position mode. I again reconnect the Arduino board with the TMC5272 and set the DMAX value. The motor was running as expected. The code snippet for running the motor in position mode was follows:

initMotorOne(IC_ID);
  
  //tmc5272_rotateMotor(IC_ID, 0, 0x00005000);
 
  tmc5272_writeRegister(IC_ID, TMC5272_RAMPMODE, 0x0); //set position mode  
  tmc5272_writeRegister(IC_ID, TMC5272_VSTART(0), 0); //set maximum valocity
  tmc5272_writeRegister(IC_ID, TMC5272_VSTOP(0), 10); //set maximum valocity
  tmc5272_writeRegister(IC_ID, TMC5272_TVMAX(0), 0); //disable jerk reduction
  tmc5272_writeRegister(IC_ID, TMC5272_AMAX(0), 50000); //set maximum acceleration
  tmc5272_writeRegister(IC_ID, TMC5272_VMAX(0), 100000); //set maximum valocity
  tmc5272_writeRegister(IC_ID, TMC5272_DMAX(0), 1000); //set maximum deacceleration
  tmc5272_writeRegister(IC_ID, TMC5272_D2(0), 1); 
  tmc5272_writeRegister(IC_ID, TMC5272_XACTUAL(0), 0); //clear actual position
  tmc5272_writeRegister(IC_ID, TMC5272_XTARGET(0), 500000); //set a target position
  delay(10000);
  tmc5272_writeRegister(IC_ID, TMC5272_XTARGET(0), 0); //return to home position

The full Arduino code is as follows. In the code a target position is set. After reaching the target position it takes 10 seconds delay and returns to the initial position again. In the loop() function actual position and target position are printed repeatedly. Supporting library files are attached in the zip file. 

/*******************************************************************************
* Copyright © 2023 Analog Devices Inc. All Rights Reserved.
* This software is proprietary to Analog Devices, Inc. and its licensors.
*******************************************************************************/

#include <SPI.h>

extern "C" {
#include "TMC5272_register_map.h"
#include "tmc5272.h"

}

/* 
 * Arduino Pins   Eval Board Pins
 * 51 MOSI        32 SPI1_SDI
 * 50 MISO        33 SPI1_SDO
 * 52 SCK         31 SPI1_SCK
 * 53 SS          30 SPI1_CSN
 * GND            23 CLK16 -> use internal 
 * 23 DIO         19 nSleep 
 * GND            2 GND
 * +5V            5 +5V_USB
 * 27 iRefR2      35 IREF_R2
 * 29 iRefR3      36 IRREF_R3
 * 31 uartMode    20 USEL/ for uart mode it should be HIGH
 */

#define IC_ID 0

int nSleep = 23;
int iRefR2 = 27;
int iRefR3 = 29;
int uartMode = 31;

void tmc5272_readWriteSPI(uint16_t icID, uint8_t *data, size_t dataLength) {
  digitalWrite(PIN_SPI_SS, LOW);
  delayMicroseconds(10);

  for (uint32_t i = 0; i < dataLength; i++) {
    data[i] = SPI.transfer(data[i]);
    Serial.println(data[i]);
  }

  delayMicroseconds(10);
  digitalWrite(PIN_SPI_SS, HIGH);
}

void setup() {
  Serial.begin(115200);

  // put your setup code here, to run once:
  pinMode(PIN_SPI_SS, OUTPUT);
  pinMode(nSleep, OUTPUT);
  pinMode(iRefR2, OUTPUT);
  pinMode(iRefR3, OUTPUT);
  pinMode(uartMode, OUTPUT);

  digitalWrite(PIN_SPI_SS, HIGH);
  digitalWrite(nSleep, LOW); // Disabling standby
  digitalWrite(iRefR2, LOW);
  digitalWrite(iRefR3, LOW);

  
  digitalWrite(uartMode, LOW);
  SPI.begin();
  SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE3));
  
  delay(10);
  
  //set resistance to 10K
  digitalWrite(iRefR2, HIGH);
  digitalWrite(iRefR3, HIGH);

  initMotorOne(IC_ID);
  
  //tmc5272_rotateMotor(IC_ID, 0, 0x00005000);
 
  tmc5272_writeRegister(IC_ID, TMC5272_RAMPMODE, 0x0); //set position mode  
  tmc5272_writeRegister(IC_ID, TMC5272_VSTART(0), 0); //set maximum valocity
  tmc5272_writeRegister(IC_ID, TMC5272_VSTOP(0), 10); //set maximum valocity
  tmc5272_writeRegister(IC_ID, TMC5272_TVMAX(0), 0); //disable jerk reduction
  tmc5272_writeRegister(IC_ID, TMC5272_AMAX(0), 50000); //set maximum acceleration
  tmc5272_writeRegister(IC_ID, TMC5272_VMAX(0), 100000); //set maximum valocity
  tmc5272_writeRegister(IC_ID, TMC5272_DMAX(0), 1000); //set maximum deacceleration
  tmc5272_writeRegister(IC_ID, TMC5272_D2(0), 1); 
  tmc5272_writeRegister(IC_ID, TMC5272_XACTUAL(0), 0); //clear actual position
  tmc5272_writeRegister(IC_ID, TMC5272_XTARGET(0), 500000); //set a target position
  delay(10000);
  tmc5272_writeRegister(IC_ID, TMC5272_XTARGET(0), 0); //return to home position
}

void loop() {
  
  int32_t value1 = tmc5272_readRegister(IC_ID, TMC5272_XACTUAL(0));
  int32_t value2 = tmc5272_readRegister(IC_ID, TMC5272_XTARGET(0));

  Serial.print("Received Data: ");
  Serial.print(value1);
  Serial.print("  ");
  Serial.println(value1);
  
  Serial.print(" from register: ");
  Serial.print(TMC5272_XTARGET(0), HEX);
  Serial.print("  ");
  Serial.println(TMC5272_XTARGET(0), HEX);
  delay(1000);
  
}

See the position mode demo video below for the above code:

Attachments

library_files.zip

References

1. TMC5272 Datasheet (https://www.analog.com/en/products/tmc5272.html)

2. TMC5272 User Guide (https://www.analog.com/media/en/technical-documentation/user-guides/tmc5272-eval-user-manual.pdf)

3. TMCL-C-Examples (https://github.com/analogdevicesinc/TMCL-C-Examples

Category : project