This start-up guide explains how to connect your Raspberry Pi 3 to the TMC5160-BOB – the breakout board of the brand new TMC5160. We’ll be using the internal Motion Controller and +3V3 logic supply for the TMC5160. The wiring will be limited to the basic functionality to communicate via SPI. The usage of the TRINAMIC’s API – TMC-API – is minimizing the software effort.
Preparation
In this tutorial we are using a fresh Raspbian Stretch System (Version November 2017 – Release date 2017-11-29) with the latest updates:
sudo apt update sudo apt upgrade
Download and install the bcm2835 library. Note XXX is a placeholder for the latest version. For this guide version “1.52” was used. In this case, XXX is replaced by “1.52”. You can check the latest version by scrolling to the bottom of the following page: http://www.airspayce.com/mikem/bcm2835/
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-XXX.tar.gz tar zxvf bcm2835-XXX.tar cd bcm2835-XXX ./configure make sudo make check sudo make install
Create a project folder and download the latest TMC-API. Note X.XX is a placeholder for the latest version. For this guide version “3.02” was used. In this case, X.XX is replaced by “3.02”. You can check the latest version by scrolling to the bottom of the following page: https://www.trinamic.com/support/software/access-package/
mkdir ~/TMC_EXAMPLE cd ~/TMC_EXAMPLE wget https://www.trinamic.com/fileadmin/assets/Products/Eval_Software/TMC-API_Release_vX.XX.zip unzip TMC-API_Release_vX.XX.zip mv TMC-API_Release_vX.XX TMC-API
Wiring
The wiring is very simple. You will need 8 jumper wires. As a reference you can use the TMC5160-BOB_datasheet_Rev1.0.pdf. You will find the signals that are on each pin.
Signal | Raspberry Pi 3 | TMC5160-BOB |
VCC_IO | GPIO02 (3) | VCC_IO (1) |
GND | GND (39) | GND (2) |
SPI Chip select (CS) | SPI0 CE0 N (24) | CSN (3) |
SPI CLK | SPI0 SCLK (23) | SCK (4) |
MOSI | SPI0 MOSI (19) | SDI (5) |
MISO | SPI0 MISO (21) | SDO (6) |
TMC5160 CLK | GPIO04 (7) | CLK (8) |
TMC5160 DRV_ENN | GPIO03 (5) | DRV_ENN (9) |
Raspberry Pi Code
An example code to initialize the TMC5160 is shown below. These files need to be placed in the same project folder as the TMC-API, in this case into ~/TMC_EXAMPLE. First, +3.3V is supplied to VCC_IO, the driver stages are enabled by pulling down DRV_ENN and the internal clock is used by pulling down CLK16. Afterwards, the TMC5160 is initialized and a simple move to position cycle is executed. The sequence will rotate a 200 full stepper motor 10 revolutions clockwise and 10 revolutions counterclockwise – depending on the wiring of the stepper motor. Please refer to the TMC5160 datasheet or the TMCL-IDE as a reference for the different registers.
You can also download the source files directly with your Pi:
cd ~/TMC_EXAMPLE wget http://blog.trinamic.com/wp-content/uploads/2018/01/TMC5160_TMCAPI_EXAMPLE.tar.gz tar zxvf TMC5160_TMCAPI_EXAMPLE.tar.gz
#include <stdio.h> #include <wiringPi.h> #include <bcm2835.h> #include "SPI_TMC.h" // Include the IC(s) you want to use #include "TMC-API/tmc/ic/TMC5160/TMC5160.h" #define MOTOR0 0 // Motor 0 void resetMotorDrivers(uint8 motor); int main(int argc, char **argv) { if (!bcm2835_init()) return 1; wiringPiSetupGpio(); // Initiate SPI bcm2835_spi_begin(); bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // MSB first bcm2835_spi_setDataMode(BCM2835_SPI_MODE3); // SPI Mode 3 bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256); // 1 MHz clock bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // define CS pin bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // set CS polarity to low /***** TMC5160-BOB Example *****/ pinMode(2, OUTPUT); digitalWrite(2, HIGH); // Apply VCC_IO voltage to Motor 0 pinMode(3, OUTPUT); digitalWrite(3, LOW); // Use internal clock pinMode(4, OUTPUT); digitalWrite(4, LOW); // Enable driver stage resetMotorDrivers(MOTOR0); // MULTISTEP_FILT=1, EN_PWM_MODE=1 enables stealthChop tmc5160_writeInt(MOTOR0, TMC5160_GCONF, 0x0000000C); // TOFF=3, HSTRT=4, HEND=1, TBL=2, CHM=0 (spreadCycle) tmc5160_writeInt(MOTOR0, TMC5160_CHOPCONF, 0x000100C3); // IHOLD=8, IRUN=15 (max. current), IHOLDDELAY=6 tmc5160_writeInt(MOTOR0, TMC5160_IHOLD_IRUN, 0x00080F0A); // TPOWERDOWN=10: Delay before power down in stand still tmc5160_writeInt(MOTOR0, TMC5160_TPOWERDOWN, 0x0000000A); // TPWMTHRS=500 tmc5160_writeInt(MOTOR0, TMC5160_TPWMTHRS, 0x000001F4); // Values for speed and acceleration tmc5160_writeInt(MOTOR0, TMC5160_VSTART, 1); tmc5160_writeInt(MOTOR0, TMC5160_A1, 5000); tmc5160_writeInt(MOTOR0, TMC5160_V1, 26843); tmc5160_writeInt(MOTOR0, TMC5160_AMAX, 5000); tmc5160_writeInt(MOTOR0, TMC5160_VMAX, 100000); tmc5160_writeInt(MOTOR0, TMC5160_DMAX, 5000); tmc5160_writeInt(MOTOR0, TMC5160_D1, 5000); tmc5160_writeInt(MOTOR0, TMC5160_VSTOP, 10); tmc5160_writeInt(MOTOR0, TMC5160_RAMPMODE, TMC5160_MODE_POSITION); while(1) { // put your main code here, to run repeatedly: printf("Reply of TMC5160: 0x%08x\n", tmc5160_readInt(MOTOR0, TMC5160_XACTUAL)); tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x0007D000); //XTARGET = 512000 -> 10 revolutions with micro step = 256 delay(12000); printf("Reply of TMC5160: 0x%08x\n", tmc5160_readInt(MOTOR0, TMC5160_XACTUAL)); tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x00000000); //XTARGET=0 delay(12000); } // End SPI communication bcm2835_spi_end(); bcm2835_close(); return 0; } void resetMotorDrivers(uint8 motor) { if(!tmc5160_readInt(MOTOR0, TMC5160_VACTUAL)) { digitalWrite(2, LOW); // Apply VCC_IO voltage to Motor 0 delay(10); digitalWrite(2, HIGH); // Apply VCC_IO voltage to Motor 0 delay(10); } }
/* * SPI_TMC.h * * Created on: 12.01.2018 * Author: MN */ #ifndef SPI_TMC_H #define SPI_TMC_H #include "TMC-API/tmc/helpers/API_Header.h" void initSPI(void); // TMC5160 SPI wrapper void tmc5160_writeDatagram(uint8 motor, uint8 address, uint8 x1, uint8 x2, uint8 x3, uint8 x4); void tmc5160_writeInt(uint8 motor, uint8 address, int value); int tmc5160_readInt(u8 motor, uint8 address); // General SPI functions void tmc40bit_writeInt(u8 motor, uint8 address, int value); int tmc40bit_readInt(u8 motor, uint8 address); #endif /* SPI_TMC_H */
#include <bcm2835.h> #include "SPI_TMC.h" // TMC5160 SPI wrapper void tmc5160_writeDatagram(uint8 motor, uint8 address, uint8 x1, uint8 x2, uint8 x3, uint8 x4) { int value = x1; value <<= 8; value |= x2; value <<= 8; value |= x3; value <<= 8; value |= x4; tmc40bit_writeInt(motor, address, value); } void tmc5160_writeInt(uint8 motor, uint8 address, int value) { tmc40bit_writeInt(motor, address, value); } int tmc5160_readInt(u8 motor, uint8 address) { tmc40bit_readInt(motor, address); return tmc40bit_readInt(motor, address); } // General SPI decription void tmc40bit_writeInt(u8 motor, uint8 address, int value) { char tbuf[5]; tbuf[0] = address | 0x80; tbuf[1] = 0xFF & (value>>24); tbuf[2] = 0xFF & (value>>16); tbuf[3] = 0xFF & (value>>8); tbuf[4] = 0xFF & value; bcm2835_spi_writenb (tbuf, 5); } int tmc40bit_readInt(u8 motor, uint8 address) { char tbuf[5], rbuf[5]; int value; // clear write bit tbuf[0] = address & 0x7F; bcm2835_spi_transfernb (tbuf, rbuf, 5); value =rbuf[1]; value <<= 8; value |= rbuf[2]; value <<= 8; value |= rbuf[3]; value <<= 8; value |= rbuf[4]; return value; }
TARGET_EXEC ?= TMCAPI_EXAMPLE BUILD_DIR ?= ./bin CC = gcc CXX = g++ # C Fags CFLAGS += -Wall CFLAGS += -g LDFLAGS += -lbcm2835 LDFLAGS += -lwiringPi # define the C source files SRCS += main.c SRCS += SPI_TMC.c # used functions from TMC_API SRCS += TMC-API/tmc/helpers/Debug.c #SRCS += TMC-API/tmc/ic/TMC2130/TMC2130.c #SRCS += TMC-API/tmc/ic/TMC2208/TMC2208.c #SRCS += TMC-API/tmc/ic/TMC2224/TMC2224.c #SRCS += TMC-API/tmc/ic/TMC2660/TMC2660.c #SRCS += TMC-API/tmc/ic/TMC5130/TMC5130.c SRCS += TMC-API/tmc/ic/TMC5160/TMC5160.c #SRCS += TMC-API/tmc/ic/TMC4330/TMC4330.c #SRCS += TMC-API/tmc/ic/TMC4331/TMC4331.c #SRCS += TMC-API/tmc/ic/TMC4361/TMC4361.c #SRCS += TMC-API/tmc/ic/TMC4361A/TMC4361A.c #SRCS += TMC-API/tmc/ic/TMC4670/TMC4670.c #SRCS += TMC-API/tmc/ic/TMC4671/TMC4671.c #SRCS += TMC-API/tmc/ic/TMC4672/TMC4672.c #SRCS += TMC-API/tmc/ic/TMCC160/TMCC160.c #SRCS += TMC-API/tmc/ic/TMC5041/TMC5041.c #SRCS += TMC-API/tmc/ic/TMC5062/TMC5062.c #SRCS += TMC-API/tmc/ic/TMC5072/TMC5072.c OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) DEPS := $(OBJS:.o=.d) $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) $(CC) $(OBJS) -o $@ $(LDFLAGS) # assembly $(BUILD_DIR)/%.s.o: %.s $(MKDIR_P) $(dir $@) $(AS) $(ASFLAGS) -c $< -o $@ $(LDFLAGS) # c source $(BUILD_DIR)/%.c.o: %.c $(MKDIR_P) $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ $(LDFLAGS) # c++ source $(BUILD_DIR)/%.cpp.o: %.cpp $(MKDIR_P) $(dir $@) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ $(LDFLAGS) .PHONY: clean clean: $(RM) -r $(BUILD_DIR) -include $(DEPS) MKDIR_P ?= mkdir -p
Compiling and running the code
Use the following command to compile the code.
cd ~/TMC_EXAMPLE make
Now you are able to execute this example.
sudo ~/TMCAPI_test/bin/TMCAPI_EXAMPLE
Be aware that the motor runs as soon as you execute the program.