Trinamic Blog

We transform digital information into physical motion.

 
  • Newsletter
  • Blog Ethics
  • Legal/Impressum
  • Main Website
Menu
  • Newsletter
  • Blog Ethics
  • Legal/Impressum
  • Main Website
  • Driving Stepper Motors with the new TMC5160 by using TRINAMIC’s API on a Raspberry Pi

    Trinamic's TMC5160-BOB setup

    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)

    TMC5160-BOB

     

    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 $< -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 ~/TMC_EXAMPLE/bin/TMCAPI_EXAMPLE

    Be aware that the motor runs as soon as you execute the program.

    Related Pages

    TMCL-IDE

    TMC5160

    TMC5160-BOB

    TRINAMIC Technology Access Package -TMC-API

    www.trinamic.com

    Share this:

    • Twitter
    • Facebook
    • LinkedIn
    • Pinterest
    • Print
    • Email

    Related

    February 19, 2018 / Mario Nolten / 60

    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

    60 thoughts on “Driving Stepper Motors with the new TMC5160 by using TRINAMIC’s API on a Raspberry Pi”

    • Radek says:
      March 12, 2018 at 11:47 am

      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

    • Mario Nolten says:
      March 15, 2018 at 1:55 pm

      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

    • Radek says:
      March 19, 2018 at 6:02 pm

      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

    • Mario Nolten says:
      March 23, 2018 at 2:57 pm

      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

    • Radek says:
      March 23, 2018 at 5:02 pm

      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

    • Mario Nolten says:
      March 23, 2018 at 6:15 pm

      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

    • Radek says:
      March 23, 2018 at 6:56 pm

      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

    • Marco says:
      April 3, 2018 at 8:07 pm

      Mistake: In the table Signal – Raspberry Pi 3 – TMC5160-BOB
      SPI Chip select (CS) should be pin 24 on the Raspberry Pi

    • Mario Nolten says:
      April 4, 2018 at 3:55 pm

      Marco, thanks for the comment.
      It is corrected now.

    • Richard says:
      April 27, 2018 at 10:39 pm

      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?

    • Mario Nolten says:
      April 30, 2018 at 8:03 am

      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

    • Ivo Ihlemann says:
      June 8, 2018 at 8:36 am

      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

    • Mario Nolten says:
      June 8, 2018 at 8:51 am

      Thanks Ivo.

    • Lucas says:
      June 14, 2018 at 11:48 am

      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

    • Mario Nolten says:
      June 14, 2018 at 12:56 pm

      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

    • Bosh says:
      June 20, 2018 at 6:14 pm

      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 :).

    • Benno says:
      June 21, 2018 at 7:09 am

      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

    • Mario Nolten says:
      June 21, 2018 at 10:14 am

      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

    • Mario Nolten says:
      June 21, 2018 at 10:16 am

      Hi,

      yes, the TMC5160 uses the same commands as the TMC2130 plus some additional ones.

      Best regards,
      Mario

    • Bahle Lucas says:
      June 21, 2018 at 5:14 pm

      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

    • Lucas says:
      June 21, 2018 at 5:23 pm

      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

    • Mario Nolten says:
      June 21, 2018 at 5:30 pm

      Hi Lucas,
      this is correct.
      Best regards,
      Mario

    • Iain says:
      July 31, 2018 at 11:43 am

      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.

    • Mario Nolten says:
      July 31, 2018 at 11:55 am

      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

    • Iain says:
      August 2, 2018 at 4:00 pm

      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!

    • Mario Nolten says:
      August 2, 2018 at 4:22 pm

      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

    • Cristian Huijse says:
      August 25, 2018 at 10:59 pm

      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?

    • Mario Nolten says:
      August 27, 2018 at 8:17 am

      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

    • Florian Becker says:
      August 28, 2018 at 7:35 am

      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

    • Mario Nolten says:
      August 31, 2018 at 2:23 pm

      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

    • Wolfgang says:
      September 19, 2018 at 9:42 am

      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

    • Mario Nolten says:
      September 25, 2018 at 10:14 am

      Hi Wolfi,
      we currently have no example that is using step/dir.
      Best regards,
      Mario

    • Iain says:
      September 26, 2018 at 11:44 am

      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

    • Mario Nolten says:
      September 26, 2018 at 12:30 pm

      Hi,
      thank you for sharing your Python code. I think this can be very helpful.
      Great Work!
      Best regards,
      Mario

    • Rhom says:
      October 14, 2018 at 1:47 am

      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

    • Roman Lindner says:
      October 22, 2018 at 1:08 pm

      Hello,
      why do you use wiringPi instead of bcm2835_gpio_write to set the gpios?
      BR
      Roman

    • Mario Nolten says:
      October 22, 2018 at 1:15 pm

      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

    • Mario Nolten says:
      October 25, 2018 at 3:42 pm

      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

    • Rhom says:
      October 28, 2018 at 7:01 pm

      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

    • Mario Nolten says:
      October 30, 2018 at 11:18 am

      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

    • Darren says:
      November 20, 2018 at 4:30 pm

      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?

    • Mario Nolten says:
      November 21, 2018 at 2:53 pm

      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

    • Irfaane says:
      January 7, 2019 at 4:25 pm

      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;
      }

    • Jason says:
      January 8, 2019 at 8:55 am

      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

    • Mario Nolten says:
      January 9, 2019 at 3:47 pm

      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

    • matang says:
      January 23, 2019 at 6:25 am

      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 ?

    • Mario Nolten says:
      January 23, 2019 at 9:00 am

      Hi Osprey,
      the error flags describe short between motor coils and VS/GND.
      Best regards,
      Mario

    • Arye Levin says:
      January 23, 2019 at 11:47 pm

      @ Irfaane,
      Your Arduino Code is incomplete, can you post it please?

      That will be very helpful.

    • Mikkel says:
      February 3, 2019 at 2:00 am

      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?

    • Lars Jaskulski says:
      February 6, 2019 at 10:11 am

      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

    • Mike Wyatt says:
      February 10, 2019 at 9:56 pm

      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

    • Mario Nolten says:
      February 11, 2019 at 2:27 pm

      Hi Mike,
      did you connect external power / motor power (24V) to the TMC5160-BOB?
      Best regards,
      Mario

    • Mike says:
      February 13, 2019 at 4:24 am

      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

    • Mario Nolten says:
      February 13, 2019 at 9:03 am

      Hi Mike,
      can you send / link a picture of wiring?
      Best regards,
      Mario

    • mihai says:
      April 4, 2019 at 8:48 pm

      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)?

    • Mario Nolten says:
      April 5, 2019 at 7:28 am

      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

    • Wolfgang says:
      April 8, 2019 at 11:43 am

      Hello! i have a compiler problem with stretch, Debug.c is not in TMC-API …
      yours
      wolfi

    • Mario Nolten says:
      April 8, 2019 at 12:18 pm

      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

    • Lasse says:
      May 5, 2019 at 6:25 pm

      is it not possible to use the TMC5160 in step/direction mode and still have the encoder functionality ?

    • Mario Nolten says:
      May 7, 2019 at 3:10 pm

      Hi,
      when using step/dir the motion controller is completely shut-off. This includes the encoder interface.
      Best regards,
      Mario

    Leave a Reply Cancel reply

    Your email address will not be published. Required fields are marked *

Recent Posts

  • Guest Blog: Designing My Own 3D Printer Mainboard
  • Field Bus Systems in Motion Control – Trinamic’s View
  • Writing Endless Lines of Code Is a Thing of the Past
  • Myths About Motor Control – Myth 3
  • Myths About Motor Control – Myth 2

Social

  • View trinamic.mc’s profile on Facebook
  • View Trinamic_MC’s profile on Twitter
  • View trinamic’s profile on GitHub
  • View UC4SHA5_GAw1Wbm2T2NWpWbA’s profile on YouTube

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Newsletter

 

Info

Waterloohain 5
22769 Hamburg
+49 40 514 806 40

Tags

3D printer 3d printing 10 myths arduino arduino stepper motor shield BLDC cDriver coolStep Driver ease of use electrical motors ethercat evaluation Hamburg heliostat How-To IC motion control motion controller motor control myth myths myths on motors open source hardware PMSM RAMPS reference design renewable energy silent silentstepstick solar stealthChop stepper stepper motor stepper motor driver stepper motor driver ic stepper motors stepRocker technology tmc5130 TMC5160 TMCL TRAMS TRINAMIC TRINAMIC Motion Control

Tag Cloud

    3D printer 3d printing 10 myths arduino arduino stepper motor shield BLDC cDriver coolStep Driver ease of use electrical motors ethercat evaluation Hamburg heliostat How-To IC motion control motion controller motor control myth myths myths on motors open source hardware PMSM RAMPS reference design renewable energy silent silentstepstick solar stealthChop stepper stepper motor stepper motor driver stepper motor driver ic stepper motors stepRocker technology tmc5130 TMC5160 TMCL TRAMS TRINAMIC TRINAMIC Motion Control

Pages

  • Blog Ethics
  • Legal/Impressum
  • Newsletter

Categories

  • Competition
  • Industry News
  • Jobs
  • Myths about Motors
  • Open Source Hardware
  • Products
  • Projects
    • DIY
  • Research
  • Social
  • Software
  • technology
  • Trade Shows
  • Tutorial
    • Code Snippet
  • Uncategorized

Copyright © 2015 TRINAMIC BlogTheme created by PWT. Powered by WordPress.org

loading Cancel
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.