Quantcast
Channel: Open Source Hardware – Trinamic Blog
Viewing all articles
Browse latest Browse all 18

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

$
0
0

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


lt; -o $@ $(LDFLAGS)

# c source
$(BUILD_DIR)/%.c.o: %.c
$(MKDIR_P) $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -c


lt; -o $@ $(LDFLAGS)

# c++ source
$(BUILD_DIR)/%.cpp.o: %.cpp
$(MKDIR_P) $(dir $@)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c


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


Viewing all articles
Browse latest Browse all 18

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>