Internet of [Moving] Things: TMC5130 + Raspberry Pi 3B+

Let’s say we’re working together in a shared office space where you can rent some desk for a certain time. For your convenience, the tables can be adjusted in height. What if the system already learned your preferred settings for standing and sitting and automatically adjusts as you wish as soon as you walk up to the table? Slight correction? Just grab your phone and make some finer adjustments.

This tutorial shall give a simple starter project for web-accessible motion applications. We’re working on a Raspberry Pi 3B+ with Raspian installed in combination with a TMC5130-BOB stepper driver breakout board. The basic principle will be the same for different drivers. The driver strength of this particular chip is probably too small for the shown application but it’s perfect for a first test on the desk.

The TMC5130 is a stepper motor driver with integrated motion controller, also called a cDriver™ . Therefore, it’s absolutely sufficient to command motions. The movement itself will not require any processing power from the Raspberry Pi, while the motor moves smoothly with outstanding performance.

Below you can find the 10 steps to take. It might be that some of them are already done in your case or you know a better way of doing it. Please feel free to share your wisdom 🙂

1. Set up Network & Interfacing

First we connect keyboard, mouse & display to Raspberry Pi and connect it to a network via wifi or cable. In the following steps we assume that the Raspi has access to the internet.

Now we should set static IP addresses for networks in order to access the Raspberry via networks & sub networks. In this tutorial, we use the following:

WIFI (wifi)

LAN (eth0)

Now we can make the Raspi accessible through your favorite machine. Therefore we open the configuration on the console:

With the Interfacing options we can enable SSH, SPI and GPIOs:

The SPI and the GPIOs will be required in order to access the driver chip.

Enabling SSH allows us to address the Raspi from our preferred device via network by its static IP in an SSH console like Putty. Even more convenient might be the access via remote desktop. The XRDP tool enables graphical access via tools like Windows Remote Desktop. Just install and connect to the IP:

For both you can log in with your standard Raspi credits.

2. Update

For the best user experience, we should make sure that all software is up to date. Run update/upgrade/dist-upgrade one after the other and reboot if packages were installed when running one of these commands. Start over until there are no updates left to install:

3. Install SPI Driver

The SPI driver can be found in the bcm2835 library. For this guide version “1.58” was used. In this case X.XX is replaced by “1.58”.
You can check the latest version by scrolling to the bottom of the following page:
Run one line after the other.

4. Download and install Apache Server, PHP and common Libraries

There are countless tutorials of that on the web. Here are the required lines for the most common setup for PHP7. Run one line after the other:

5. Download Project Files

We put the project files directly to the web server directory. The following lines will navigate there, unpack the files, remove the archive and replace the default ‘hello world’ landing page:

Of course you can download the package directly in order to have a look upfront:

6. Wire Everything Up

Here’s the pinout.

Now we can also connect the motor. Make sure that the motor is never disconnected when the driver is active. Therefore I highly recommend to always connect the motor first and then power the system. In this case you can choose something like 5…46V. At 24V, your power supply should supply 1A at least. For lower voltages a bit more.

7. Test TMC5130

Now we can compile the C source code that parametrizes the driver:

You can find everything in the src sub-directory. I suggest to access it with your favorite text editor that has built-in SSH (SFTP) support.

The code includes the access to the chip registers, simple functions for movements and a standard initialization. It utilizes the SPI interface in order to communicate with the chip. All in all it’s just around 120 lines plus defines in the header.

In the TMC5130_init function you can find the basic initialization. Please check whether the programmed current of around 0.7A RMS is suitable for your motor. There is also a second example for 0.25 A RMS.

With this line you can run the compiled program:

Make sure the system is powered for the test. Otherwise, nothing will happen. If everything is OK, the motor starts moving with constant velocity.

Our program is not clever enough to stop the motor yet – that’s the next step. If you want to stop it, just unpower it. This will also reset the driver chip.

8. Demo Program

Before starting, we have to comment the main function in the TMC5130.c, because now we want to run the main of the project.c file.

Now that is done we can compile the whole project:

Everything worked well? Now we can test the program with different parameters. Please try one line after the other:

In the main loop of the project.c file, we are looking at the different ASCII commands (i,r,0,t,b,g,s,d) and the corresponding parameters and use the TMC5130 code to perform different movements.

By the way, the number of 51200 steps is exactly one revolution for the most common hybrid stepper motors. Typically these motors have 200 full steps. The driver runs with 256 microsteps per default. 200*256=51200.

The given velocity of 100000 is here around 77500pps. You can calculate it with the following formula:


As we are using the internal clock of the chip of around 13MHz, this gives:

v[pps] = 100000 * 13000000 / 2^24

As we know that one reveolution has 51200 micro steps, we are moving 77500/51200 or around 1.5 revolutions per second (rps). This is around 1.5*60 = 90 revolutions per minute (rpm).

Further information regarding real world units can be found in the datasheet.

9. Make Programs Accessible

Our two motor control programs work well now. But as they are using important hardware blocks of the Raspi you need certain rights. Therefore we need to allow the www-data user to access our programs as sudo. All we need to do is add following to the sudoers file. As the slightest mistake in this modification might mean that we lock ourselves out of the Raspi, we’re doing well in using the visudo helper, which performs a syntax check:

Here we can add the following lines to the bottom:

Now we can save the file and exit.

10. Check Out the Web Project

You can find all web relevant files in the web subfolder:

We linked the index.html before. This means we can now open our browser and access the web project on the Raspi via its IP address (whichever you use or directly from our browser. (If you call it from the Raspi directly it’s of course http://localhost/)

All the forms are defined in the index.html file. Submitting a form by clicking a button will call the run.php with all given parameters. The run.php is called in an iframe, which is shown in the feedback field. Therefore all responses will be shown there.

The run.php translates the commands from the web interface into calls of our little project program, which will move the motor. Most commands are triggering or stopping a motion and inform that the end of the program is reached.

There is one additional command d (|<>|), which will start the demo, where the motor is moved back and forth. In mode the program stays active. In a state machine the actual status of the motor is monitored. As soon as the motor arrives at a target position the motor goes back where it came from. Even though the program is active, everything still needs only around 1% of processing power.


Of course you can build way way fancier programs, utilize java script and sweet graphics. But I hope this project gives you a brief idea of how to get started.

This project is meant as a starter for different projects around automation. You can shut your window blinds, open your cat flap or rock your baby to sleep. Very similar implementations allow stronger drivers like the TMC5160 or TMC5161, but also smaller two-axis systems that are e.g. based on the TMC5041.

As the actual driving of the motors doesn’t consume processing power of the Raspberry Pi You can combine different motors for several tasks and still have easily enough processing capabilities for powerful application layers.

For the driver itself, we’re working with standard C code. Therefore you can also use it on any microcontroller or platform in order to make it work in different environments.

Please feel free to add a comment if this post was helpful, about what you made out of it or if there is anything I can improve.



  • Tamas

    Dear Trinamic!

    I am trying to use a TMC5130 but no success. I use a custom board with STM32L4 MCU. The SPI communication with the TMC5130 does not work.
    As in the datasheet, I send 5 bytes (First byte is the address with the R/W flag)
    For any of the registers I always receive zero values. But the first byte (received immediately after the address byte) apparently contains a valid status. The state of the REFL and REFR pins are reflected properly in the status byte. Also, the IC is live , and the connections should be good!

    But what is the problem? I receive always zeroes for all of the registers.
    When trying to write any registers, it reads back always zero.

    If I remove the module from the socket, I receive full 0xff, because there is a weak pull-up resistor on the MISO line.

  • Thomas Ernst

    Dear Tamas,

    Here’s my best guess: Might it be that the chip select goes high between the bytes you send?
    This might explain that the status byte is transferred properly, but all the others not.

    Please make sure to keep the chip select line low for all five bytes. I hope this solves it.

    Best regards,


  • Mike

    Hello Thomas,

    Been working with various Trinamic stepper motor controllers to develop a macro photography focus stacking system, and later a more involved multi-axis stack and stitch system, and developed custom circuit boards and code for the Raspberry Pi 3B for the BOB TMC5130, 5160, 5161, 5072 and dual chip versions with 5130 & 5072 for triple axis and two 5072 for quad axis control. The code is in Python and even runs on the RPI ZERO W! Also developed a custom “Hall Effect” Motor current sensor for oscilloscope or DVM use to optimize motor/rail performance, it doesn’t rely on the usual series resistor or the traditional current probe “clamp” and displays both Sine and Cosine current waveforms with excellent accuracy.

    Various Precision Rails for focus stacking work beautifully with the Trinamic controllers once optimized, and are very quite and vibration free!!

    I have links for the details for those that are interested.



  • Stepper John

    Hello Trinamic,

    i’m trying to get feedback value from an as5601 encoder behind a stepper motor, connected to TMC5130 board. I’m using a Raspberry Compute Module (V3), the last Rasbian release, golang with go-rpio library for SPI communication (

    I can drive the motor, reinit him, ask and receive xactual etc. but I don’t succeed to read the value of register 0x39, is it possible for you to tell me if my config values are set right? (I’m using position mode).

    gconfW := []byte{0x80, 0x00, 0x00, 0x00, 0x00} //GCONF
    chopConfW := []byte{0xEC, 0x00, 0x01, 0x01, 0xD5} //CHOPCONF TOFF=5, HSTRT = 5, HEND =3, TBL = 2, CHM = 0 (spreadcycle)
    iholdIrunW := []byte{0x90, 0x00, 0x07, 0x17, 0x03} //IHOLD_RUN: IHOLD=3, IRUN= 10, (max.current) IHOLDDEALY=6 // equivalent old current
    tpowerdownW := []byte{0x91, 0x00, 0x00, 0x00, 0x0A} // TPOWERDOWN = 10
    pwminitW := []byte{0xF0, 0x00, 0x00, 0x00, 0x00} // PVMINIT
    pwmconfW := []byte{0xF0, 0x00, 0x04, 0x01, 0xC8} // PVMCONF : AUTO=1, 2/1024 fclk, Switch amp limit=200, grad =1
    a1W := []byte{0xA4, 0x00, 0x00, 0x03, 0xE8} //A1 = 1000
    v1W := []byte{0xA5, 0x00, 0x01, 0x86, 0xA0} //V1 = 100000
    amaxW := []byte{0x06, 0x00, 0x00, 0xC3, 0x50} // AMAX = 50000
    vmaxW := []byte{0xA7, 0x00, 0x03, 0x20, 0x00} // VMAX=204800 soit 120 tr/min
    d1W := []byte{0xAA, 0x00, 0x00, 0x05, 0x78} //D1=1400
    vstopW := []byte{0xAB, 0x00, 0x00, 0x00, 0x0A} // VSTOP= 10
    rampmodeW := []byte{0xA0, 0x00, 0x00, 0x00, 0x00} //POSITIONING = 0 VELOCITY = 1
    xactualW := []byte{0xA1, 0x00, 0x00, 0x00, 0x00} //XACTUAL = 0
    xtargetW := []byte{0xAD, 0x00, 0x00, 0x00, 0x00}
    encMode := []byte{0x38, 0x00, 0x00, 0x04, 0x00} // TO CHECK encMode is set on 11 bit (0 to 10) Need to verify if this value is good
    encConst := []byte{0x3A, 0x00, 0x00, 0x00, 0x01}
    encStatus := []byte{0x3B, 0x00, 0x00, 0x00,0x01} // TO CHECK encStatus is set on 1 bit Need to verify if this value is good

    Tell me if you wanna see the all code. My question is, if i have the right configuration, do you have any exemple, or pseudo code to show me how the 0x39 register is supposed to be request?

    Thanks for all you’re doing, your products are just awesome, and sorry for my english. Available for any question.


  • ANNA

    how can we get the header files of TMC

  • Thomas Ernst

    Hi John,

    My first impression is that the encoder constant is not correct (ENC_CONST register).
    I need to free up to check and will come back to you hopefully soon.
    Meanwhile please feel free to have a look at the datasheet. There is a section for the encoder interface with some calculation examples.

    Best regards,


Leave a Reply

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