Table of contents
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.
Project
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:
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.
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.
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.zipReferences
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)