Setup Example

Real-time Motor and Motion Control with a Raspberry Pi without a real-time OS

Single-board computer (SBC) gained more and more popularity during the last years due its opensource software and the simple hardware. With these SBC it is possible to develop quickly and easily prototype systems or even full products. The standard Linux distributions have no real-time capabilities. For many projects like a digital weather station, this is not crucial. For motion control, on the other hand, it is mandatory to have real-time access for making clean acceleration ramps, position control and closed-loop operation. All of this is possible with motion control ICs from TRINAMIC without needing any real-time operating system on the SBC.

The project below shows how to do precise autonomous cyclic movements with the TMC4361A without any MCU power. The Raspberry Pi 3 is used to set up the needed registers and from there the TMC4361A takes care of the movement. The used system consists besides the Raspberry Pi 3 of a TMC4361A-BOB and a TMC5160-BOB, which is used a plain pre-driver stage, so the internal motion controller is deactivated. The usage of the TRINAMIC’s API – TMC-API – is minimizing the software effort.

The motor will do alternating exactly 5 rotations at 2.5 RPS and 5 rotations at 5 RPS. The switching points are handled by the TMC4361A in hardware. So there is no need for real-time software capabilities. The following steps need to be done to setup the TMC4361A:

  1. Basic configuration of TMC4361A for controlling the TMC5160 family in step/dir mode
  2. Basic configuration of TMC5160 for step/dir mode via cover datagrams
  3. Activation of circular motion, see chapter 8.5.2. of TMC4361A Datasheet
  4. Setting up a one stage shadow register set, see chapter 9.2.1 of TMC4361A Datasheet
  5. Configuring a cyclic pipeline structure, see chapter 9.3.4. and 9.3.5. of TMC4361A Datasheet

Software Preparation

In this tutorial we are using a fresh Raspbian Stretch System (Version November 2017 – Release date 2017-11-29) with the latest updates:

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/

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/

Enable step/dir Mode on TMC5160-BOB

The TMC5160-BOB allows the TMC5160 to use in 2 different modes: With integrated motion controller and in step/dir mode. For controlling the TMC5160 by the TMC4361A the TMC5160 has to be in step/dir. On the TMC5160-BOB this can easily be done by desoldering the R2 and soldering it to R1.

TMC5160-BOB: R1 and R2 are red marked 

Wiring

The wiring is very simple. You will need 18 jumper wires. As a reference, you can use the TMC4361A-BOB_datasheet_Rev1.0.pdf and TMC5160-BOB_datasheet_Rev1.0.pdf.

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

Rasbperry Pi to TMC4361A-BOB

Signal Raspberry Pi 3 TMC4361-BOB
VCC_IO 3.3v (1) VCC_IO (1)
GND GND (39) GND (2)
TMC4361A CLK GPIO04 (7) CLK (3)
TMC4361A NRST GPIO15 (10) NRST (4)
SPI Chip select (CS) SPI0 CE0 N (24) CSN (5)
SPI CLK SPI0 SCLK (23) SCK (6)
MOSI SPI0 MOSI (19) SDI (7)
MISO SPI0 MISO (21) SDO (8)
TMC4361A-BOB

Rasbperry Pi to TMC5160-BOB

Signal Raspberry Pi 3 TMC5160-BOB
VCC_IO GPIO02 (3) VCC_IO (1)
TMC5160 CLK GPIO14 (8) CLK (8)
TMC5160 DRV_ENN GPIO03 (5) DRV_ENN(9)

TMC4361A-BOB to TMC5160-BOB

Signal TMC4361A TMC5160-BOB
GND GND (2) GND (2)
SPI Chip select (CS) CSN_DRV (18) CSN (3)
SPI CLK SCK_DRV (19) SCK (4)
MOSI SDI_DRV (21) SDI (5)
MISO SDO_DRV (20) SDO (6)
STEP STPOUT (22) REFL (10)
DIR STPDIR (23) REFR (11)
TMC5160-BOB

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:

 

 

 

 

Compiling and running the code

Use the following command to compile the code.

Now you are able to execute this example.

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

Related Pages

TMCL-IDE

TMC4361A

TMC4361A-BOB

TMC5160

TMC5160-BOB

TRINAMIC Technology Access Package -TMC-API

www.trinamic.com

8 Comments

  • Radek Reply

    Hello Mario,
    Nice article. I have to think about writing code on BBB to handle a closed loop or use TMC4361 instead.
    One more question, I like the terminal adapter board you use. Where can I buy this?
    Regards
    Radek

    • Mario Nolten Reply

      Thanks Radek.
      The adapter board is called “Schraubstock”. It will be soon available at our distribution channels.
      Best regards,
      Mario

  • J Reply

    Hey Mario,

    i tried the Program on my Raspberry Pi, but an error acquired:

    mkdir -p bin/TMC-API/tmc/ic/TMC5160/
    gcc -Wall -g -c TMC-API/tmc/ic/TMC5160/TMC5160.c -o bin/TMC-API/tmc/ic/TMC5160/TMC5160.c.o -lbcm2835 -lwiringPi
    TMC-API/tmc/ic/TMC5160/TMC5160.c: In function ‘tmc5160_initConfig’:
    TMC-API/tmc/ic/TMC5160/TMC5160.c:74:2: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode
    for(int i = 0; i < REGISTER_COUNT; i++)
    ^
    TMC-API/tmc/ic/TMC5160/TMC5160.c:74:2: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code
    Makefile:48: recipe for target 'bin/TMC-API/tmc/ic/TMC5160/TMC5160.c.o' failed
    make: *** [bin/TMC-API/tmc/ic/TMC5160/TMC5160.c.o] Error 1

    can you help me at this ?

    Best regards

    J

    • Mario Nolten Reply

      Hi J,
      please add an additional LDFLAG to the Makefile:
      LDFLAGS += -std=gnu99

      Best regards,
      Mario

      • J Reply

        Hi Mario Nolten,

        Thanks for your answer. It help a lot!

        I wanted to use the code with the tmc4361 and with tmc2130. I changed a bit in the code the name tmc5130 for tmc2130 and change the register values but i get one problem :

        mkdir -p bin/TMC-API/tmc/ic/TMC2130/
        gcc -Wall -g -c TMC-API/tmc/ic/TMC2130/TMC2130.c -o bin/TMC-API/tmc/ic/TMC2130/TMC2130.c.o -lbcm2835 -lwiringPi -std=gnu99
        gcc ./bin/main.c.o ./bin/SPI_TMC.c.o ./bin/TMC-API/tmc/helpers/Debug.c.o ./bin/TMC-API/tmc/ic/TMC2130/TMC2130.c.o ./bin/TMC-API/tmc/ic/TMC4361A/TMC4361A.c.o -o bin/TMCAPI_EXAMPLE -lbcm2835 -lwiringPi -std=gnu99
        ./bin/TMC-API/tmc/ic/TMC2130/TMC2130.c.o: In function tmc2130_writeConfiguration':
        /home/pi/TMC_EXAMPLE/TMC-API/tmc/ic/TMC2130/TMC2130.c:86: undefined reference to
        tmc2130_writeInt’
        collect2: error: ld returned 1 exit status
        Makefile:40: recipe for target ‘bin/TMCAPI_EXAMPLE’ failed
        make: *** [bin/TMCAPI_EXAMPLE] Error 1

        It would be very helpful.

        Best regards

        J

        • Mario Nolten Reply

          Hi J,
          first you need add the following line to the Makefile / remove the “#” at the beginning:
          SRCS += TMC-API/tmc/ic/TMC2130/TMC2130.c

          Then you need to write the SPI Wrapper functions for the TMC2130 in SPI.c. For this you can just copy the code for the TMC5160 and rename it to TMC2130.

          SPI.h:

          // TMC2130 SPI wrapper
          void tmc2130_writeDatagram(uint8 motor, uint8 address, uint8 x1, uint8 x2, uint8 x3, uint8 x4);
          void tmc2130_writeInt(uint8 motor, uint8 address, int value);
          int tmc2130_readInt(u8 motor, uint8 address);

          SPI.c:

          // TMC2130 SPI wrapper
          void tmc2130_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 tmc2130_writeInt(uint8 motor, uint8 address, int value)
          {
          tmc40bit_writeInt(motor, address, value);
          }

          int tmc2130_readInt(u8 motor, uint8 address)
          {
          tmc40bit_readInt(motor, address);
          return tmc40bit_readInt(motor, address);
          }

          Best regards,
          Mario

          • J

            Hey Mario Nolten,

            Thank you very much! It works!

            But it works only in one direction, shouldn’t it change the direction ?
            (I only change the value for the speed and acceleration in the skript, then the motor start to move)
            Hope you can help me at that.

            Best regards,
            J

          • Mario Nolten

            Hi J,

            it should be working in both direction. Can you double-check if the dir signal is connected properly?

            Best regards,
            Mario

Leave a Reply

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