-
Driving Stepper Motors with the new TMC5160 by using TRINAMIC’s API on a Raspberry Pi
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 3 GPIO Header – Source: https://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-3-model-b-gpio-40-pin-block-pinout
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=10, 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
lt; -o $@ $(LDFLAGS)
# c source
$(BUILD_DIR)/%.c.o: %.c
$(MKDIR_P) $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -clt; -o $@ $(LDFLAGS)
# c++ source
$(BUILD_DIR)/%.cpp.o: %.cpp
$(MKDIR_P) $(dir $@)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -clt; -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 ~/TMC_EXAMPLE/bin/TMCAPI_EXAMPLE
Be aware that the motor runs as soon as you execute the program.
Related Pages
TRINAMIC Technology Access Package -TMC-API
Related
February 19, 2018 / Mario Nolten / 65
Categories: Code Snippet, Open Source Hardware, Products, Software, Tutorial
Tags: Raspberry Pi, TMC5160, TMC5160-BOB
Win a BQ Witbox Go! Your Project in Motion with Powerful Prototypes
Comments are currently closed.
65 thoughts on “Driving Stepper Motors with the new TMC5160 by using TRINAMIC’s API on a Raspberry Pi”
Hello Mario,
Very nice example.
Will this API compile on Beaglebone or will work with Arduino either?
How about reading encoder pulses by this BOB module – any code is available in API?
And last question: how 5160-BOB is comparable to 2660-BOB – I mean about reading encoder pulses for close loop and also about powering stepper with 2.8A/phase?
Best regards
Hi Radek,
yes, you can use this API also on a Beaglebone. You probably need to adapt the SPI function for the Beaglebone. On an Arduino it is not so easy to use. The Arduino IDE does not allow to have a folder structure as we have in our API.
For reading encoder pulses, you can directly connect the encoder to the TMC5160-BOB and read out the pulses from TMC5160_XENC. By setting the prescaler it shows directly the encoder position in microstep.
The TMC2660-BOB is a bit different. The TMC2660 is a plain driver IC (without integrated motion controller as the TMC5160 has) so you need to apply step/dir pulses to drive the motor and the encoder has to be connected directly to the MCU. For this we have no API code for a Raspberry Pi or Beaglebone, since it is for both crucial to have a realtime OS.
Best regards,
Mario
Mario,
Thank you for valuable information.
This is a very interesting product. I needed some time to break through the documentation. At the beginning I will try to run in mode 2 with an external application and without collecting the signal from the encoder. Then I will try mode 1 and encoder. One more question: if two motion controllers are used for controlling axes X/Y (amateur laser cutter), then both of them must be addressed separately or is there some form of communication between them and the code can be simplified? Will I find the answer to this problem in the API or do I have to implement it myself? In addition, is there any documentation how to electrically connect several axes in such a system using 5160 so that the motion controllers cooperate?
Best regards
Radek
Radek,
for controlling multiple axis / ICs, each one of them has to be addressed seperately. The API is currently working with 1 motor but it should be pretty easy to extend it to 2 or 3 axis. You should be able to reuse most of the code for the additional axis. The API is in continous progress and multiple axis control is on the agenda.
Best regards,
Mario
Mario,
I will try to do it then. I would like to make SPI communication using PRU on BBB. I will see how it will go. I do not know just what I can gain from SPI communication. Step/Dir is working very nice at PRU at this moment with BeagleG code from Henner Zeller for example or Replicape project (they using TMC2100 on a cape for BBB -they also use SPI but only for some chipset configuration). Is the use of SPI can improve something here or is it better to stay at TMC2660 with step/dir commands and save some bucks? What do you think?
Best regards
Radek
Radek,
using step/dir is probably more straight forward since the firmware is already written for this. For using the internal motion controller you would need to adapt it. BTW: You can also use the TMC5160 in step/dir to have all benefits like higher currents, stealthChop2™, differential current sensing, etc. In this case you only need the SPI to configure the run current, chopping mode (spreadCycle™ or stealthChop2™).
Best regards,
Mario
Mario,
Yes, and this is the reason why I will probably stay with TMC5160. It has all the newest features compacted into one small chip, so for me is very versatile.
Thank you again and I let you know about the effects.
Either way, good job with this API.
Best regards and have a good weekend.
Radek
Mistake: In the table Signal – Raspberry Pi 3 – TMC5160-BOB
SPI Chip select (CS) should be pin 24 on the Raspberry Pi
Marco, thanks for the comment.
It is corrected now.
Hi,
I’m interested in using the TMC5160 for CNC electronics, the dcStep feature is very interesting from a cnc milling perspective when milling through materials like metal.
However dcStep appears to be an open loop system and I don’t think you can use an encoder at the same time.
If someone wanted to use the motion control system to vary the speed based on the load (dcStep)
keep multiple axis such as an x and y in sync as the speed varies (I think DCIn / DCO)
but also use a closed loop encoder to verify the position
which would be the best way to do this?
I’m wondering if several TMC5160’s with the DCIN / DCO pins hooked up to keep things in sync with dcStep
and also a TMC4361A (or an Arm controller chip) to keep track of the encoder inputs / position?
Hi Richard,
yes, you are right, dcStep is an openLoop feature. Since you already have encoders assembled to your motors a combination of TMC4361 + TMC5160 is a very good solution. Here is a short guide how you can connect the TMC4361-BOB with a TMC5160-BOB:
http://blog.trinamic.com/2018/04/09/realtime-motor-and-motion-control-with-a-raspberry-pi-without-a-realtime-os/
The TMC4361 has an integrated sync pin which allows to syncronize several axis. Besides this the TMC4361 allows full closed control.
Best regards,
Mario
Hi,
let me thank you first for this tutorial.
I found a mistake: I’m pretty shure the last command should not be “sudo ~/TMCAPI_test/bin/TMCAPI_EXAMPLE”, but instead “sudo ~/TMC_EXAMPLE/bin/TMCAPI_EXAMPLE”
Sincerely
Ivo
Thanks Ivo.
Hi,
how can the A (rms or max) for the motor be set on this board? Do I have to change some resistor on the pcb or can I do it via a TMCL command? Could not find any info on this.
Sincerely,
Lucas
Hi Lucas,
you can change the motor current by changing the IHOLD (current at standstill) and IRUN.
// IHOLD=8, IRUN=15 (max. current), IHOLDDELAY=6
tmc5160_writeInt(MOTOR0, TMC5160_IHOLD_IRUN, 0x00080F0A);
Best regards,
Mario
Am i right to assume that the same commands used to configure tmc2130 should work for this IC (want to use it without the motion controller). I know tmc2660 uses different registers but it seems tmc5160 uses the same ones as tmc2130. Is this correct? Don’t want to destroy them while trying :).
Hello
I have the following combination:
Landungsbrücke-> TMC4361_eval-> TMC5160_eval
Does the firmware of the Landungsbrücke have to be renewed?
Best regards
Benno
Hi Benno,
this combination is currently not supported by our TMCL-IDE because the TMC5160 needs to be selected as driver, not motion controller. We are currently working on a version that supports this.
Best regards,
Mario
Hi,
yes, the TMC5160 uses the same commands as the TMC2130 plus some additional ones.
Best regards,
Mario
Hi Mario,
thank you very much. Sorry that I still have to ask:
In the datasheet it says phase-current A is 2.8 (RMS), so for what is 8 standing for and for what is 15 standing for? Are these mapped numberspaces? Where can more information about those commands be found and what set number is giving what amp?
Best regards
Thanks Mario,
finally found it in the datasheet “TMC5160 DATASHEET (Rev. 1.06 / 2018-JUN-06)” on page 74. So do I understand it (?), when IRUN=31 is put, it takes 32/32 of the max A, e.g. 2.8A(RMS) for the tmc5160-BOB. If e.g. IRUN=15 it takes 16/32 of it, that would be 1.4A(RMS)? Does it work in that way?
Best regards,
Lucas
Hi Lucas,
this is correct.
Best regards,
Mario
I’m developing with a 5130-bob, is there anything similar to this for the 5130? Or can I use this example and just change the includes to use 5130.h instead of 5160.h?
I’m running it from a Raspberry Pi.
Hi Iain,
you can basically use the same code, include the 5130.h instead and rename tmc5160_writeInt(..) accordingly. For the TMC5130 you might want to use a slightly different configuration for GCONF.
Best regards,
Mario
Thanks, I’ve got the 5130-bob driving a stepper quite nicely after fixing GCONF (basically 04 instead of 0C),however I notice that Your code is pretty basic and only supports a single motor (as mentioned above). I need to support multiple motors (at least 2, preferably 3 or 4),, which physically the pi is quite able to do.
Are you likely to be changing the underlying packages (broadcom driver and wiringpi are both used in the code above).
Can you give me any idea of the likely timescale for a multi motor version!
Hi Ian,
for supporting more than 1 motor you can simply change the code for the function “void tmc40bit_writeInt(u8 motor, uint8 address, int value)”. E.g. add a switch case and define an unique CS for each motor.
As you mentioned this is a very basic example. An example for more than one motor would be great but is currently not planned.
Best regards,
Mario
Dear Mario
We are trying to run this example with no success. The TMC5160_XACTUAL register reads the value that was written on the TMC5160_XTARGET register but the stepper motor does not move whatsoever. We have tried different power supplies, different motors and different raspberry boards. Could you give us a hint on how to debug this?
Hi Christian,
please make sure that DRV_ENN (9) on the TMC5160-BOB is at low level and that TMC5160_CHOPCONF is initialized properly.
Best regards,
Mario
Hallo Mario,
ich habe ein Problem mit meinem TMC5160 EVAL. Ich habe dies über einen USB-Dongle direkt über SPI angeschlossen. Nun bin ich dabei die Register zu beschreiben und auszulesen. Die Kommunikatzion funktioniert auch soweit, ABER das Problem ist, wenn ich zu Beginn Register auslese, anschließend irgendwelche Register beschreibe und nun zB XACTUAL auslesen möchte, ein Pseudo-Wert angezeigt wird. Auch wenn das Register beim AUslesen nach dem fahren ein anderes ist, wird der gleiche Pseudo-Wert angezeigt. Woran kann das liegen? dies kommt mir sehr komisch vor
Beste Grüße
Hi Florian,
am besten ist es hierfür unser Support System zu nutzen – der blaue Bubble, der sich auf jeder Seite befindet.
Viele Grüße,
Mario
Hello!
Thanks for the delightful tutorial. I would like to integrate the TMC5160 in an existing project utilizing the STEP/DIR interface – as far as I understand it, the STEP/DIR interface is easily enabled by desoldering R2. Is here also an example for setting the necessary parameters (mainly current and microsteps, plus some Trinamic-specific settings) with a simple microcontroller via SPI in Arduino style?
Yours Wolfi
Hi Wolfi,
we currently have no example that is using step/dir.
Best regards,
Mario
I’ve written a very basic driver in python for the 5130 using the SPI interface, this is a lot easier to setup and run than the C code example and should be simple to adapt to other chips (like the 5160) that use the same interface technique.
It is available at https://github.com/pootle/tripipy
Hi,
thank you for sharing your Python code. I think this can be very helpful.
Great Work!
Best regards,
Mario
Hello!
I want to use 2 tmc5160 to drive 2 motors by SPI. The motors should drive the same speed at the same time, but should be able to power of or drive individual.
Now my questions:
-should i better use a master and 2 independent slaves or a star connection(SPI)?
-if i use 2 independent slaves i have to select by CS where i want to read and write and always use motor0 like your example, right?
-if i want to drive in star connection and
#define MOTOR0 //and
#define MOTOR1
will the TMCs become their label (MOTOR0/ MOTOR1) because their interconnection or or how does that operate?
-Can i readily #define MOTOR1 or what i have to respect in exept for the hardware connection?
Best regards,
Rhom
Hello,
why do you use wiringPi instead of bcm2835_gpio_write to set the gpios?
BR
Roman
Hi Roman,
when I created this example there were some issues using bcm2835_gpio_write with the Raspberry Pi 3. This library was not updated yet.
Best regards,
Mario
Hi Rohm,
it is better to use independent CS for both ICs because this gives you more felxibility. You will also have to extend the functions void tmc40bit_writeInt(u8 motor, uint8 address, int value) and int tmc40bit_readInt(u8 motor, uint8 address) e.g. with an if, else if to define the the IOs / CS which are linked to which motor.
Best regards,
Mario
Hello Mario,
thank you for your advice.
I use an independent CS for each IC and the other GPIOS (MOSI; MISO; CLK; DRV_ENN; VCC) are linked, but it doesnt work.
Can you explicate why i have to extend the functions?
Is not only the CS relevant to ensure a correct communication?
…
bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // define CS pin
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // set CS polarity to low
bcm2835_spi_chipSelect(BCM2835_SPI_CS1); // define CS pin
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, LOW); // set CS polarity to low
…
Then i initialize the Motor settings (CHOPCONF etc.) for each Controller/ IC.
…
while(1)
{
bcm2835_spi_chipSelect(BCM2835_SPI_CS0;
printf(“Reply of TMC5160: 0x%08x\n”, tmc5160_readInt(MOTOR0, TMC5160_XACTUAL));
tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x0007D000);
bcm2835_spi_chipSelect(BCM2835_SPI_CS1;
printf(“Reply of TMC5160: 0x%08x\n”, tmc5160_readInt(MOTOR0, TMC5160_XACTUAL));
tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x0007D000);
delay(12000);
}
…
The first looping flow let the motors drive but then they are in “hold”.
After the first drive they stay in hold even if i execute the code again.
Iam desperate and dont make any progress, i will be deeply grateful for your help and any solutions!
BR
Hi,
this is of course possible as well.
My idea was to modify this here – same has to be done in the read function:
// 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;
if(motor == 0) bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
else if(motor == 1) bcm2835_spi_chipSelect(BCM2835_SPI_CS1);
bcm2835_spi_writenb (tbuf, 5);
}
This way you can use tmc5160_writeInt(MOTOR0, TMC5160_GCONF, 0x0000000C); and tmc5160_writeInt(MOTOR1, TMC5160_GCONF, 0x0000000C);
Best regards,
Mario
Hi,
After connecting encoder’s ABN to TMC5160 BOB board and setting the encoder register, how am i able to position directly to encoder positions since XTARGET is the only one register i could found to manipulate position in RAMPMODE0(position mode).
I set ENCMODE = 0x72C and ENC_CONST to 198608 since my encoder’s resolution is 16000; however, sometimes is seems to have some step loss between XCTUAL and X_ENC. Is there any extra setting need to be done?
Hi Darren,
thank you for your interest in our products.
The TMC5160 provides a simple encoder interface / decoder. It does not have any closed-loop control logic implemented. This needs to be done in the higher level, e.g. your MCU or using a TMC4631.
Simplest way is doing it in software by comparing XACTUAL and X_ENC. When there is a deviation greater than a specific value just set XACTUAL to the value of X_ENC. Since both values are constantly changing while the motor is rotating this should be done at standstill, e.g. after a position command to see if the motor actually reached the target position.
Best regards,
Mario
Incase someone needs it for arduino:
#include
#include “SPI.h”
#define MOTOR0 0 // Motor 0
#define TMC5160_GCONF 0x00
#define TMC5160_CHOPCONF 0x6C
#define TMC5160_IHOLD_IRUN 0x10
#define TMC5160_TPOWERDOWN 0x11
#define TMC5160_TPWMTHRS 0x13
#define TMC5160_VSTART 0x23
#define TMC5160_A1 0x24
#define TMC5160_V1 0x25
#define TMC5160_AMAX 0x26
#define TMC5160_VMAX 0x27
#define TMC5160_DMAX 0x28
#define TMC5160_D1 0x2A
#define TMC5160_VSTOP 0x2B
#define TMC5160_RAMPMODE 0x20
#define TMC5160_MODE_POSITION 0x0
#define TMC5160_XTARGET 0x2D
#define TMC5160_XACTUAL 0x21
#define TMC5160_VACTUAL 0x22
#define CS_PIN 10 //chip select
#define MOSI_PIN 11 //SDI/MOSI (ICSP: 4, Uno: 11, Mega: 51)
#define MISO_PIN 12 //SDO/MISO (ICSP: 1, Uno: 12, Mega: 50)
#define SCK_PIN 13 //CLK/SCK (ICSP: 3, Uno: 13, Mega: 52)
#define EN_PIN 2 //enable (CFG6)
int tmc40bit_readInt(uint8_t motor, uint8_t address);
void tmc40bit_writeInt(uint8_t motor, uint8_t address, int value);
void tmc5160_writeInt(uint8_t motor, uint8_t address, int value);
int tmc5160_readInt(uint8_t motor, uint8_t address);
void setup() {
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
pinMode(MOSI_PIN, OUTPUT);
digitalWrite(MOSI_PIN, LOW);
pinMode(MISO_PIN, INPUT);
digitalWrite(MISO_PIN, HIGH);
pinMode(SCK_PIN, OUTPUT);
digitalWrite(SCK_PIN, LOW);
Serial.begin(9600); //init serial port and set baudrate
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
// 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=10, IRUN=15 (max. current), IHOLDDELAY=6
tmc5160_writeInt(MOTOR0, TMC5160_IHOLD_IRUN, 0x00080800);
// 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, 50000);
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);
tmc5160_writeInt(MOTOR0, TMC5160_RAMPMODE, 2);
//tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x7FFFFFFF);
}
void loop() {
// // put your main code here, to run repeatedly:
// // put your main code here, to run repeatedly:
// Serial.print(“Reply of TMC5160: “);
// Serial.println(tmc5160_readInt(MOTOR0, TMC5160_XACTUAL));
// tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x0007D000);
// //tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0xFFFFFFFF);
// //XTARGET = 512000 -> 10 revolutions with micro step = 256
//
// delay(12000);
//
// Serial.print(“Reply of TMC5160: “);
// Serial.println(tmc5160_readInt(MOTOR0, TMC5160_XACTUAL));
// tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x00000000); //XTARGET=0
//
// delay(12000);
}
void tmc5160_writeDatagram(uint8_t motor, uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4)
{
int value = x1;
value <<= 8;
value |= x2;
value <<= 8;
value |= x3;
value <>24));
SPI.transfer(0xFF & (value>>16));
SPI.transfer(0xFF & (value>>8));
SPI.transfer(0xFF & value);
digitalWrite(CS_PIN, HIGH);
}
int tmc40bit_readInt(uint8_t motor, uint8_t address)
{
int value;
// clear write bit
SPI.transfer(address & 0x7F);
value =SPI.transfer(0x00)&0xFF;
value <<= 8;
value |= SPI.transfer(0x00)&0xFF;
value <<= 8;
value |= SPI.transfer(0x00)&0xFF;
value <<= 8;
value |= SPI.transfer(0x00)&0xFF;
return value;
}
Hello,
In the TMC5160 Datasheet, Section 3.3MOSFETs and Slope Control, it is indicated that the DRVSTRENGTH parameter should be adapted to gate drive resistor value / Mosfet Miller charge. The BOB has a 22Ohm gate resistor, yet as far as I can see in your example, the DRVSTRENGTH is still at its default setting of 2 (GD Resistor < or = to 7.5Ohm).
Can you explain this?
Kind Regards.
Jason
Hi Jason,
for this example I kept using the reset defaults values which is technically total fine. Usually you want to have as fast as possible slopes to achieve low switching times and to minimize switching losses. The downside of fast switching slopes / high gate current is the EMV behavior. Since this is just a maker example it is not tuned to fit any EMV standards.
Best regards,
Mario
Hello,
The datasheet of TMC5160 describes two error flags s2vs & s2g.
Does these error flag represent Short between motor coils and VS/GND OR short between coils their self ?
Hi Osprey,
the error flags describe short between motor coils and VS/GND.
Best regards,
Mario
@ Irfaane,
Your Arduino Code is incomplete, can you post it please?
That will be very helpful.
I need to connect five of these to a raspberry pi, will that be possible? And is there an easy way to make them work like a 3D Printer = Marlin Firmware?
Hi Mikkel,
Yes, that works in theory. You can use 5 chip select signals to use the same SPI channel.
Please have a look to these application notes:
https://www.trinamic.com/fileadmin/assets/Support/Appnotes/AN035-CNC_motion_with_ramp_generator.pdf
https://www.trinamic.com/fileadmin/assets/Support/Appnotes/AN046-Adapting_step_dir_cnc_firmware_for_ramp_generators.pdf
Hope this information is helpful.
Best regards,
Lars
Hello,
We have purchased the TMC5130, TMC5160 and TMC5161 BOB for evaluation and will decide which best fits our needs, then purchase more. I’ve setup the TMC5160 as shown on here connected to a Raspberry Pi 3B+. After I run make and execute the example all I get is “Reply of TMC5160: 0x0d2000a0, then Reply of TMC5160: 0x0000000, then Reply of TMC5160: 0xba2d00ad which repeats line after line until I Ctl-C out.
I’m not a programmer, so please dumb down to my level if you have any suggestions or ideas what’s going on.
I also would like to run the TMC5130A BOB and TMC5161 BOB to compare the results and behavior, so any suggestions on how to do this with the same relative code is appreciated, but 1st I need to get the TMC-5160 working!!
Thanks in advance,
Best,
Mike
Hi Mike,
did you connect external power / motor power (24V) to the TMC5160-BOB?
Best regards,
Mario
Hi Mario,
I replied earlier but it didn’t get posted.
Yes, I have power but it’s 12v, is this a problem? The motor is a NEMA 17 400 step 2.8a motor. I’ve used this motor at 12v volts with 1 or 1.4a amp current limit with a A4988, DVR8825, & Pololu Tic-500 (MPS6500 chip) all successfully runing from the RPi 3B. I’ve even coding my own control in Python with the Tic-500.
I can’t get the TMC-5160, nor the TMC-5130 to operated at all, even rewired the setup 2 or 3 times with same result. I just rewired the TMC-5160 again and ran the code shown here (with 04 correction indicated) and same result with the inital “Reply of TMC-5160: 0x0d2000a0, then 0x00000000, then never ending sting of 0x7a2d00ad. I ctrl out and reran and the never ending string became 0x02a2d00ad.
Please help as I’m lost as to what to do now!
Best,
Mike
Hi Mike,
can you send / link a picture of wiring?
Best regards,
Mario
Hi Mario! Is there any reason to use a Watterott SilentStepStick based on TMC5160 instead of TMC5160-BOB, assuming that we control it with a RPi? Would a TMC5160-BOB have more functions which the SilentStepStick doesn’t have (like encoder inputs)?
Hi Mihai,
yes, you are right the BOB has more functionality / more pins routed to the connector than the SilentStepStick. Therefore it has also larger form factor. The TMC5160-BOB has also an enabled Motion Controller, while the SilentStepStick only supports step/dir.
Best regards,
Mario
Hello! i have a compiler problem with stretch, Debug.c is not in TMC-API …
yours
wolfi
Hi Wolfi,
you are right Debug.c is not part of the API anymore. You can use an older version e.g. V3.01 or just remove this line from the Makefile:
SRCS += TMC-API/tmc/helpers/Debug.c
Best regards,
Mario
is it not possible to use the TMC5160 in step/direction mode and still have the encoder functionality ?
Hi,
when using step/dir the motion controller is completely shut-off. This includes the encoder interface.
Best regards,
Mario
Ok, so figured out how to make the tutorial work again with latest software versions. First you comment out the SRCS += TMC-API/tmc/helpers/Debug.c in the Makefile as Mario suggests.
If you did create the TMC-API folder through the renaming of the downloaded folder, i.e. followed the guide. Do the following.
1) Change path in the Makefile from SRCS += TMC-API/tmc/ic-TMC5160/TMC5160.c should be changed to SRCS += TMC-API/TMC-API/tmc/ic-TMC5160/TMC5160.c.
2) Change path in main.c from #include “TMC-API/tmc/ic/TMC5160/TMC5160.h” to “TMC-API/TMC-API/tmc/ic/TMC5160/TMC5160.h”
3) Change path in SPI_TMC.h from #include “TMC-API/tmc/helpers/API_Header.h” to #include “TMC-API/TMC-AP/tmc/helpers/API_Header.h”
Notice in all three cases and extra /TMC-API/ was added to move down a level in the folder structure. Hope this helps!
Hello,
i have two Questions regarding the wiring:
1. Why are you using GPIO2 (physical 3) and not physical 1 (3.3V) for VCC_IO? GPIO2 belongs to I2C
2. CLK input is wired to GPIO4 (7) in wiring Table, shouldn’t this be GPIO3 (5), the I2C Clock?
3. You are using internal TMC5160 clock, why are you wiring CLK at all to rasperry clock
Thanks!
Hi gernstl,
there was no reason to pick a specific GPIO. This guide is meant as a getting started so that you don’t have to start from the scratch. Of course there are many different ways how you can connect our TMC5160.
To 1: You can also hardwire it to +3V3. I connected it to an GPIO because this gives an easy way to reset the IC. A hardware reset can be done by toggling VCC_IO.
To 2: CLK needs ideally a 16MHz input. As there was no easy way to provide this from the Raspberry Pi, I simply set the GPIO to LOW. Alternatively, you can just hardwire it to GND.
To 3: You are right this is not necessarily needed.
Best regards,
Mario
Hi,
I would like to ask if it is possible to daisy chain on the same SPI bus:
3 x TMC2130
3 x TMC5160
Thank you
Hi Frank,
yes, this is possible.
Best regards,
Mario