Do you love tinkering with machines, motors, and anything that moves? Are you a semiconductor or electronics geek who also likes to write? If so, Trinamic may be the right place for you.
Trinamic is thirty-year old Hamburg, Germany-based “startup? that designs and builds the ICs and microsystems that connect the digital and physical worlds. And now we’re looking for a content marketing leader who can help us share our experience and deep expertise in embedded motor and motion control through an aggressive content marketing approach.
Motion control industry experts already know that the Trinamic brand is synonymous with precision, reliability, and efficiency. Now it’s time to spread the word even further. Are you the right person to lead our efforts?
We are looking for a TECHNICAL CONTENT MARKETING MANAGER.
DESIRED BACKGROUND
Do you have experience writing marketing copy for semiconductors and electronics?
Are you a tinkerer who is fascinated by electronics and the inner workings of physical devices?
Are you highly precise in your writing yet able to incorporate knowledge, personality, and humor when appropriate?
Can you engage an audience even when writing about highly technical areas?
Do enjoy all types of marketing-related writing?
Can you work independently and grow your responsibilities within a fast-paced and fast-growing company?
Are you fluent in English, German, or both?
RESPONSIBILITIES
Develop and maintain editorial schedule / topics
Manage internal and external editors, writer, and localization resources
Develop content plan in conjunction with development and sales teams
Work with customers to develop success stories and case studies.
Create and edit content for various outlets, including:
Only a few wires including an SPI port are required to control TMC5130-EVAL with your Arduino. Here are the few steps required to get started.
Preparation
If your Arduino is a 5V type you have to resolder one resistor on the TMC5130-EVAL from position R3 to R8. This sets the logic level of the TMC5130 to +5V. While by default the resistor is soldered to the “right-hand” position, you have to move it to the “left-hand” position for 5V operation.
Illustration 1 – Extract from TMC5130-EVAL schematic
Illustration 2 – Position of the logic level resistor on the TMC5130-EVAL board
Wiring
The wiring is very simple. You will need 8 jumper wires. To make the wiring more easy you can print out the TMC5130-EVAL_Pinning.pdf and cut out the template to mount it on the connector header of the TMC5130-EVAL (As seen on illustration 4). As a reference you can use the TMC5130-Eval_v15_01_Schematic.pdf. Here you’ll find the signals that are on each pin. The configuration is documented in the comment section of the Arduino code.
Illustration 3 – Pinheader of TMC5130-EVAL
Illustration 4 – TMC5130 wired up with Arduino Mega 2560
Cable colors of illustration 4
+5V –> red
GND –> blue
SDO –> yellow
SDI –> orange
SCK –> white
CSN –> grey
DRV_ENN –> black
CLK16 –> green
Arduino Code
The Arduino Code below does not need any additional libraries. The SPI library comes with the Arduino IDE. The program initializes the TMC5130 and executes a simple move to position cycle. It will rotate a 200 full step motor 10 revolutions to the one and 10 revolutions to the other direction depending on the wiring of the stepper motor. Please use either the TMC5130 datasheet or the TMCL IDE as a reference for the different registers.
#include <SPI.h>
#include "TMC5130_registers.h"
/* The trinamic TMC5130 motor controller and driver operates through an
* SPI interface. Each datagram is sent to the device as an address byte
* followed by 4 data bytes. This is 40 bits (8 bit address and 32 bit word).
* Each register is specified by a one byte (MSB) address: 0 for read, 1 for
* write. The MSB is transmitted first on the rising edge of SCK.
*
* Arduino Pins Eval Board Pins
* 51 MOSI 32 SPI1_SDI
* 50 MISO 33 SPI1_SDO
* 52 SCK 31 SPI1_SCK
* 25 CS 30 SPI1_CSN
* 17 DIO 8 DIO0 (DRV_ENN)
* 11 DIO 23 CLK16
* GND 2 GND
* +5V 5 +5V
*/
int chipCS = 25;
const byte CLOCKOUT = 11;
int enable = 17;
void setup() {
// put your setup code here, to run once:
pinMode(chipCS,OUTPUT);
pinMode(CLOCKOUT,OUTPUT);
pinMode(enable, OUTPUT);
digitalWrite(chipCS,HIGH);
digitalWrite(enable,LOW);
//set up Timer1
TCCR1A = bit (COM1A0); //toggle OC1A on Compare Match
TCCR1B = bit (WGM12) | bit (CS10); //CTC, no prescaling
OCR1A = 0; //output every cycle
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE3);
SPI.begin();
Serial.begin(9600);
sendData(0x80,0x00000000); //GCONF
sendData(0xEC,0x000101D5); //CHOPCONF: TOFF=5, HSTRT=5, HEND=3, TBL=2, CHM=0 (spreadcycle)
sendData(0x90,0x00070603); //IHOLD_IRUN: IHOLD=3, IRUN=10 (max.current), IHOLDDELAY=6
sendData(0x91,0x0000000A); //TPOWERDOWN=10
sendData(0xF0,0x00000000); // PWMCONF
//sendData(0xF0,0x000401C8); //PWM_CONF: AUTO=1, 2/1024 Fclk, Switch amp limit=200, grad=1
sendData(0xA4,0x000003E8); //A1=1000
sendData(0xA5,0x000186A0); //V1=100000
sendData(0xA6,0x0000C350); //AMAX=50000
sendData(0xA7,0x000186A0); //VMAX=100000
sendData(0xAA,0x00000578); //D1=1400
sendData(0xAB,0x0000000A); //VSTOP=10
sendData(0xA0,0x00000000); //RAMPMODE=0
sendData(0xA1,0x00000000); //XACTUAL=0
sendData(0xAD,0x00000000); //XTARGET=0
}
void loop()
{
// put your main code here, to run repeatedly:
sendData(0xAD,0x0007D000); //XTARGET=512000 | 10 revolutions with micro step = 256
delay(20000);
sendData(0x21,0x00000000);
sendData(0xAD,0x00000000); //XTARGET=0
delay(20000);
sendData(0x21,0x00000000);
}
void sendData(unsigned long address, unsigned long datagram)
{
//TMC5130 takes 40 bit data: 8 address and 32 data
delay(100);
uint8_t stat;
unsigned long i_datagram;
digitalWrite(chipCS,LOW);
delayMicroseconds(10);
stat = SPI.transfer(address);
i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
i_datagram <<= 8;
i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
i_datagram <<= 8;
i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
i_datagram <<= 8;
i_datagram |= SPI.transfer((datagram) & 0xff);
digitalWrite(chipCS,HIGH);
Serial.print("Received: ");
PrintHex40(stat, i_datagram);
Serial.print("\n");
Serial.print(" from register: ");
Serial.println(address,HEX);
}
void PrintHex40(uint8_t stat, uint32_t data) // prints 40-bit data in hex with leading zeroes
{
char tmp[16];
uint16_t LSB = data & 0xffff;
uint16_t MSB = data >> 16;
sprintf(tmp, "0x%.2X%.4X%.4X", stat, MSB, LSB);
Serial.print(tmp);
}
Download
The Arduino and TMC5130 zip file includes the pinning template, the TMC5130-EVAL schematic and the Arduino project.
In this start up guide you get explained how to connect your Raspberry Pi 3 or 2 for the basic operation of the TMC5130-EVAL board. It will use the internal Motion Controller and +3V3 logic supply for the TMC5130. The wiring will be limited to the basic functionallity to communicate via SPI. The internal CLK for the TMC5130 will be used respective the CLK16 pin (Shown on figure 1) has to be tied to GND. The SPI CLK frequency of the Raspberry Pi will be set up to be 1MHz.
Preparation
With a fresh installation of Raspbian (In this tutorial Raspbian Jessy Lite – Version March 2017 – Release date 2017-03-02) first update the libraries:
sudo apt-get update
sudo apt-get dist-upgrade
This may take a while since it will upgrade all packages that are installed to the newest version if available. Furthermore it will upgrade dependencies or remove them if they have been replaced with other dependencies.
Download and install the bcm2835 library. Note XXX is a place holder 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
gunzip bcm2835-XXX.tar.gz
tar xvf bcm2835-XXX.tar
cd bcm2835-XXX
./configure
make
sudo make check // This should show you a pass message
sudo make install
Afterwards restart your PI by typing.
sudo restart -h 0
Wiring
The wiring is very simple. You will need 8 jumper wires. As a reference you can use the TMC5130-Eval_v15_01_Schematic.pdf. You will find the signals that are on each pin.
Signal
Raspberry Pi 2
TMC5130-EVAL
+5V
+5V (2)
+5V (5)
GND
GND (39)
GND (2)
TMC5130 enable
GND (9)
DIO_0 (8)
TMC5130 CLK
GND (6)
CLK16 (23)
MOSI
SPI0 MOSI (19)
SPI1_SDI (32)
MISO
SPI0 MISO (21)
SPI1_SDO (33)
SPI CLK
SPI0 SCLK (23)
SPI1_SCK (31)
Chip select (CS)
SPI0 CS0 (24)
SPI1_CSN (30)
Pinheader of TMC5130-EVAL
Raspberry Pi 3 GPIO Header – Source: https://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-3-model-b-gpio-40-pin-block-pinoutRaspberry 3 wired up with TMC5130-EVAL
Please note that the TMC5130-EVAL has to be powered with the supply voltage e.g. 24V. To avoid damage only disconnect or connect a motor without supply voltage.
Raspberry Pi Code
An example code to initialize the TMC5130 is shown below. It will clear the reset flag in the GCONF register, sets example chopper configurations and sets the run and hold current for the motor. Furthermore it will set the ramping mode to velocity mode, an acceleration and a velocity. Be aware that the motor runs as soon as you execute the script.
You can download the code directly with your pi by typing:
Today we will wire up a TMC4361A-EVAL + TMC2130-EVAL combination to drive a stepper motor closed loop with an Arduino Uno. The encoder used for this test has a resolution of 10.000 cpr respective a resolution of 40.000.
Preparation
For this tutorial the Eselsbruecke got a soldered connection between +5V_USB (pin 5) to +5V_VM (pin 42) to get +5V for the encoder. You can use jumper wires as well but make sure the connection is properly.
Wiring
The wiring is very simple. You will need 9 jumper wires. To make the wiring more easy you can print out the TMC5130-EVAL_Pinning.pdf (used from a previous blog entry) and cut out the template to mount it on the connector header of the TMC4361-EVAL (As seen on illustration 4). As a reference you can use the TMC5130-Eval_v15_01_Schematic.pdf. Here you’ll find the signals that are on each pin. The configuration is documented in the comment section of the Arduino code.
Illustration 3 – Pinheader of TMC4361-EVALIllustration 4 – TMC4361A+TMC2130 wired up with Arduino Uno
Cable colors of illustration 4
+5V –> red
GND –> blue
SDO –> yellow
SDI –> orange
SCK –> white
CSN –> grey
DIO0 (DRV_ENN) –> black (Is passed thru to TMC2130-EVAL DRV_ENN pin)
DIO16 (NFREEZE) –> brown
CLK16 –> green
Arduino Code
The Arduino Code below does not need any additional libraries. The SPI library comes with the Arduino IDE. The program initializes the TMC2130 thru the TMC4361A-EVAL (cover datagram) and the TMC4361 itself. It will rotate a 200 full step motor 2 revolutions to the one and 2 revolutions to the other direction depending on the wiring of the stepper motor. Please use either the TMC4361 and TMC2130 datasheets as a reference for the different registers (Download links below).
#include <SPI.h>
#include "TMC4361A_Register.h"
/* The trinamic TMC4361 motor controller operates through an
* SPI interface. Each datagram is sent to the device as an address byte
* followed by 4 data bytes. This is 40 bits (8 bit address and 32 bit word).
* Each register is specified by a one byte (MSB) address: 0 for read, 1 for
* write. The MSB is transmitted first on the rising edge of SCK.
*
* Arduino Uno Pins Eval Board Pins
* 11 MOSI 32 SPI1_SDI
* 12 MISO 33 SPI1_SDO
* 13 SCK 31 SPI1_SCK
* 8 CS 30 SPI1_CSN
* 7 DIO 8 DIO0 (DRV_ENN)
* 9 DIO 23 CLK16
* 2 DIO 38 NFREEZE
* GND 2 GND
* +5V 5 +5V
*/
int chipCS = 8;
const byte CLOCKOUT = 9;
int enable = 7;
int nFreeze = 2;
void setup()
{
// put your setup code here, to run once:
pinMode(chipCS,OUTPUT);
pinMode(CLOCKOUT,OUTPUT);
pinMode(enable, OUTPUT);
pinMode(nFreeze, OUTPUT);
digitalWrite(chipCS,HIGH);
digitalWrite(enable,LOW);
digitalWrite(nFreeze,HIGH);
//set up Timer1
TCCR1A = bit (COM1A0); //toggle OC1A on Compare Match
TCCR1B = bit (WGM12) | bit (CS10); //CTC, no prescaling
OCR1A = 0; //output every cycle
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE3);
SPI.begin();
Serial.begin(9600);
// General setup of TMC4361 Motion Controller with TMC2130 stepper driver
sendData(0xCF,0x52535400); // reset squirrel
sendData(0x83,0x00540022); // input filter: START and encoder pins
sendData(0x84,0x8440000d);
sendData(0x80,0x00007026); // direct-a, direct-bow
sendData(0x90,0x00060004); // Steplength
sendData(0xED,0x00000080); // Using cover datagram to write to GCONF of TMC2130:
sendData(0xEC,0x00012200); // diag1=index, pushpull, direct_mode = on --> SPI mode
sendData(0xED,0x00000090); // Using cover datagram to write to IHOLD_IRUN of TMC2130:
sendData(0xEC,0x00051905); // IHOLD = 29, IHOLDDELAY = 5, IRUN = 25
sendData(0xED,0x00000091); // Using cover datagram to write to TPOWERDOWN of TMC2130:
sendData(0xEC,0x0000000A); // TZEROWAIT = 10
sendData(0xED,0x00000094); // Using cover datagram to write to TCOOLTHRS of TMC2130:
sendData(0xEC,0x000000C8); // = 200
sendData(0xED,0x00000095); // Using cover datagram to write to TCOOLTHRS of TMC2130:
sendData(0xEC,0x00000032); // = 50
sendData(0xED,0x000000EE); // Using cover datagram to write to DCCTRL of TMC2130:
sendData(0xEC,0x00070025); //
sendData(0xED,0x000000F0); // Using cover datagram to write to PWMCONF of TMC2130:
sendData(0xEC,0x000404FF); // DCCTRLSG = 5, DC_TIME = 37
sendData(0xED,0x000000EC); // Using cover datagram to write to CHOPCONF of TMC2130:
sendData(0xEC,0x00010223); //
sendData(0xED,0x000000ED); // Using cover datagram to write to COOLCONF of TMC2130:
sendData(0xEC,0x0100a220); // OFF
sendData(0xA4,0x00000000); // v = 0
sendData(0xA1,0x00000000); // xactual = 0
sendData(0xB7,0x00000000); // xtarget = 0
// Closed Loop calibration of TMC4361 Motion Controller
sendData(0xD4,0x00009C40); // Encoder resolution = 40k/rev
sendData(0x9C,0x00FF00FF); // CL_BETA = CL_GAMMA = 255
sendData(0xA0,0x00000004); // hold + position mode
sendData(0xA4,0x00100000); // slow velocity
sendData(0xDC,0x00010000); // cl_p = 1.0
sendData(0x87,0x00400000); // turn on closed loop
sendData(0xB7,0x00000080); // move to full step position
sendData(0x87,0x01400000); // turn on closed loop calibration
sendData(0x87,0x00400000); // turn off closed loop calibration
sendData(0xA4,0x00000000); // v = 0
// Setup Closed Loop Operation
sendData(0xA0,0x00000006); // S-Ramp + POS Mode
sendData(0xA4,0x079A8000); // VMAX = 400.000 pps
sendData(0xA8,0x00000200); // AMAX
sendData(0xA9,0x00000200); // DMAX
sendData(0xAD,0x00000100); // bow1
sendData(0xAE,0x00000100); // bow2
sendData(0xAF,0x00000100); // bow3
sendData(0xB0,0x00000100); // bow4
sendData(0xE0,0x00250000); // emf_vmin =
sendData(0xE1,0x00450000); // emf_vadd = -> emf_vmax =
sendData(0xE2,0x00FFFFFF); // emf_vel0_timer
sendData(0xE3,0x02000864); // enc vel filter settings
sendData(0xDF,0x00000014); // cl_tolerance = 20
sendData(0xDC,0x00010000); // cl_p = 1.0
sendData(0xDA,0x000000C8); // cl_vlimit_p = 200
sendData(0xDB,0x00000032); // cl_vlimit_i = 50
sendData(0xDD,0x000003E8); // cl_vlimit_diclip = 1000
sendData(0xDE,0x00100000); // cl_vlimit = 100.000 pps
sendData(0x86,0x0032f064); // cl scaling values
sendData(0x98,0x00001000); // cl_upscale
sendData(0x99,0x00100000); // cl_dnscale
sendData(0x87,0x0A400000); // cl with gamma correction and vlimit
sendData(0x85,0x00000080); // cl scaling on
}
void loop()
{
// put your main code here, to run repeatedly:
sendData(0xB7,0x00019000); // XTARGET = 100.000
delay(3000);
sendData(0xB7,0x00000000); // XTARGET = 0
delay(3000);
}
void sendData(unsigned long address, unsigned long datagram)
{
//TMC4361 takes 40 bit data: 8 address and 32 data
delay(100);
unsigned long i_datagram;
digitalWrite(chipCS,LOW);
delayMicroseconds(10);
SPI.transfer(address);
i_datagram |= SPI.transfer((datagram >> 24) & 0xff);
i_datagram <<= 8;
i_datagram |= SPI.transfer((datagram >> 16) & 0xff);
i_datagram <<= 8;
i_datagram |= SPI.transfer((datagram >> 8) & 0xff);
i_datagram <<= 8;
i_datagram |= SPI.transfer((datagram) & 0xff);
digitalWrite(chipCS,HIGH);
Serial.print("Received: ");
Serial.println(i_datagram,HEX);
Serial.print(" from register: ");
Serial.println(address,HEX);
}
Download
The Arduino_TMC4361_TMC2130 zip file includes the pinning template, the TMC4361-EVAL schematic and the Arduino project.
TMC4361-EVAL (Please note: This EVAL version has the previous TMC4361-LA on board. This version is compatible as well. The TMC4361A-EVAL will be available shortly.)
Today we show how to connect TRINAMIC’s TMC5072-EVAL via Single Wire UART to an Arduino Mega for basic operation. The wiring is limited to the basic functionality to communicate via Single Wire UART.
Preperation
To use the 5V version of the Arduino MEGA you have to resolder Resistor from position R3 to R8. This enables 5V logic level for the TMC5072. The sense resistor by default is soldered to the right position. Please desolder and resolder to the left position.
Figure 1: Extract from TMC5072-EVAL schematic
Figure 2: TMC5072-EVAL with pins marked for logic supply voltage
Wiring
The wiring is very simple. You will need X jumper wires. To make the wiring easier you can connect the wire directly to the Eselsbrücke. As a reference you can use the TMC5072Eval_v10_01_Schematic.pdf. Here you 1nd the signals that are on each pin. The con1guration is documented in the comment section of the Arduino code.
Figure 3: Pinheader of TMC5072-EVAL
Arduino Code
The Arduino Code below is based on the TMC-API package. The program initializes the TMC5072 and executes a simple move to position cycle. The sequence will rotate two 200 full stepper motors 10 revolutions to the one and 10 revolutions to the other direction depending on the wiring of the stepper motor. Please refer to the TMC5072 datasheet or the TMCL-IDE as a reference for the different registers.
TMC5072-EVAL_UART.ino
/*
* TMC5072-EVAL_UART.ino
*
* Created on: 20.02.2017
* Author: MN
*
* The Trinamic TMC5072 motor controller and driver operates through Single
* Wire UART. This is 64 bits datagram (8 sync bytes, 8 bit slave address,
* 8 bit register address and 32 bit word).
* Each register is specified by a one byte register address: with MSB = 0
* for read, MSB = 1 for write.
*
* Arduino Pins Eval Board Pins
* 18 TX1 40 SWIOP
* 19 RX1 41 SWION
* 2 DIO 38 DIO16 (SWSEL)
* 4 DIO 33 SDO/RING
* 3 DIO 8 DIO0 (DRV_ENN)
* 10 DIO 23 CLK16
* GND 2 GND
* +5V 5 +5V
*/
#include "TMC5072_register.h"
#include "CRC.h"
#define CRC8_GEN 0x07
int SWSEL = 2;
int DRV_ENN = 3;
int SDO_RING = 4;
const int CLOCKOUT = 10;
void setup() {
pinMode(SWSEL, OUTPUT);
pinMode(CLOCKOUT,OUTPUT);
pinMode(DRV_ENN, OUTPUT);
pinMode(SDO_RING, OUTPUT);
digitalWrite(DRV_ENN, LOW);
//HIGH = power stage disabled, LOW = power stage enabled
digitalWrite(SWSEL, HIGH);
//HIGH = UART mode, LOW = SPI mode
digitalWrite(SDO_RING, HIGH);
//HIGH = ring mode, LOW = normal mode
//setup timer2
TCCR2A = ((1 << WGM21) | (1 << COM2A0));
TCCR2B = (1 << CS20);
TIMSK2 = 0;
OCR2A = 0;
Serial.begin(115200);
Serial1.begin(115200);
delay(500);
uartWriteDatagram(0x00, TMC5072_SLAVECONF, 0x00000001); //SLAVEADDR to 1
delay(500);
tmc5072_initMotorDrivers();
}
void loop() {
// put your main code here, to run repeatedly:
uartRead(0x01, TMC5072_XACTUAL_1); //read out XACTUAL of motor 1
uartRead(0x01, TMC5072_XACTUAL_2); //read out XACTUAL of motor 2
uartWriteDatagram(0x01, TMC5072_XTARGET_1, 0x0007D000);
//XTARGET=512000 | 10 revolutions with micro step = 256
uartWriteDatagram(0x01, TMC5072_XTARGET_2, 0xFFF83000);
//XTARGET=-512000 | 10 revolutions with micro step = 256
delay(15000);
uartRead(0x01, TMC5072_XACTUAL_1); //read out XACTUAL of motor 1
uartRead(0x01, TMC5072_XACTUAL_2); //read out XACTUAL of motor 2
uartWriteDatagram(0x01, TMC5072_XTARGET_1, 0x00000000); //XTARGET=0
uartWriteDatagram(0x01, TMC5072_XTARGET_2, 0x00000000); //XTARGET=0
delay(15000);
}
void uartWriteDatagram(uint8_t SLAVEADDR, uint8_t registerAddress,
unsigned long datagram) {
//TMC5072 takes 64 bit data: 8 sync + reserved, 8 chip address,
//8 register address, 32 data, 8 CRC
uint8_t CRC = 0;
int temp;
unsigned char buf[8];
CRC = NextCRC(CRC, 0x05, CRC8_GEN);
CRC = NextCRC(CRC, SLAVEADDR, CRC8_GEN);
CRC = NextCRC(CRC, registerAddress|0x80, CRC8_GEN);
CRC = NextCRC(CRC, (datagram >> 24) & 0xff, CRC8_GEN);
CRC = NextCRC(CRC, (datagram >> 16) & 0xff, CRC8_GEN);
CRC = NextCRC(CRC, (datagram >> 8) & 0xff, CRC8_GEN);
CRC = NextCRC(CRC, datagram & 0xff, CRC8_GEN);
buf[0] = 0x05;
buf[1] = SLAVEADDR;
buf[2] = registerAddress|0x80;
buf[3] = (datagram >> 24) & 0xff;
buf[4] = (datagram >> 16) & 0xff;
buf[5] = (datagram >> 8) & 0xff;
buf[6] = datagram & 0xff;
buf[7] = CRC;
temp = Serial1.write(buf, 8); //write datagram
Serial1.flush(); //wait until all datas are written
Serial1.readBytes(buf, 8); //clear input buffer
}
unsigned long uartRead(uint8_t SALVEADDR, uint8_t registerAddress) {
uint8_t CRC = 0, temp;
unsigned char buf[8];
unsigned long dataBytes;
CRC = NextCRC(CRC, 0x05, CRC8_GEN);
CRC = NextCRC(CRC, SALVEADDR, CRC8_GEN);
CRC = NextCRC(CRC, registerAddress, CRC8_GEN);
buf[0] = 0x05;
buf[1] = SALVEADDR;
buf[2] = registerAddress;
buf[3] = CRC;
Serial1.write(buf, 4); //write datagram
Serial1.flush(); //wait until all datas are written
Serial1.readBytes(buf, 4); //clear input buffer
Serial1.readBytes(buf, 8);
temp = buf[2];
dataBytes = buf[3]; //bit 32...24
dataBytes <<= 8;
dataBytes |= buf[4]; //bit 23...16
dataBytes <<= 8;
dataBytes |= buf[5]; //bit 15...8
dataBytes <<= 8;
dataBytes |= buf[6]; //bit 7...0
CRC = 0;
for(int i=0;i<7;i++)
{
CRC = NextCRC(CRC, buf[i], CRC8_GEN);
}
//show received bytes
Serial.print("Received: 0x");
for(int i=0;i<8;i++)
{
char tmp[16];
sprintf(tmp, "%.2X", buf[i]);
Serial.print(tmp);
}
Serial.print("\n");
Serial.print("CRC: "); Serial.print(CRC,HEX);Serial.print(" <-> BUFFER: ");
Serial.println(buf[7],HEX);
return dataBytes;
}
void tmc5072_initMotorDrivers()
{
//2-phase configuration Motor 1
uartWriteDatagram(0x01, TMC5072_CHOPCONF_1, 0x00010135);
uartWriteDatagram(0x01, TMC5072_IHOLD_IRUN_1, 0x00071400);
//2-phase configuration Motor 2
uartWriteDatagram(0x01, TMC5072_CHOPCONF_2, 0x00010135);
uartWriteDatagram(0x01, TMC5072_IHOLD_IRUN_2, 0x00071400);
//Reset positions
uartWriteDatagram(0x01, TMC5072_RAMPMODE_1, TMC5072_MODE_POSITION);
uartWriteDatagram(0x01, TMC5072_XTARGET_1, 0);
uartWriteDatagram(0x01, TMC5072_XACTUAL_1, 0);
uartWriteDatagram(0x01, TMC5072_RAMPMODE_2, TMC5072_MODE_POSITION);
uartWriteDatagram(0x01, TMC5072_XTARGET_2, 0);
uartWriteDatagram(0x01, TMC5072_XACTUAL_2, 0);
//Standard values for speed and acceleration
uartWriteDatagram(0x01, TMC5072_VSTART_1, 1);
uartWriteDatagram(0x01, TMC5072_A1_1, 5000);
uartWriteDatagram(0x01, TMC5072_V1_1, 26843);
uartWriteDatagram(0x01, TMC5072_AMAX_1, 5000);
uartWriteDatagram(0x01, TMC5072_VMAX_1, 100000);
uartWriteDatagram(0x01, TMC5072_DMAX_1, 5000);
uartWriteDatagram(0x01, TMC5072_D1_1, 5000);
uartWriteDatagram(0x01, TMC5072_VSTOP_1, 10);
uartWriteDatagram(0x01, TMC5072_VSTART_2, 1);
uartWriteDatagram(0x01, TMC5072_A1_2, 5000);
uartWriteDatagram(0x01, TMC5072_V1_2, 26843);
uartWriteDatagram(0x01, TMC5072_AMAX_2, 5000);
uartWriteDatagram(0x01, TMC5072_VMAX_2, 100000);
uartWriteDatagram(0x01, TMC5072_DMAX_2, 5000);
uartWriteDatagram(0x01, TMC5072_D1_2, 5000);
uartWriteDatagram(0x01, TMC5072_VSTOP_2, 10);
}
/****************************************************
Projekt: TMC5130 and TMC5072 CRC calculation
Modul: CRC.h
CRC-Calculation for UART interfacing
Hinweise: Start with CRC-Register=0,
then call NextCRC for each byte to be sent
or each by received. Send CRC byte last or
check received CRC
Datum: 14.6.2011 OK
*****************************************************/
#ifndef CRC_H
#define CRC_H
#include "TypeDefs.h"
uint8 NextCRCSingle(uint8 Crc, uint8 Data, uint8 Gen, uint8 Bit);
uint8 NextCRC(uint8 Crc, uint8 Data, uint8 Gen);
#endif
CRC.cpp
/****************************************************
Projekt: TMC5130 and TMC5072 CRC calculation
Modul: CRC.cpp
CRC-Calculation for UART interfacing
Hinweise: Start with CRC-Register=0,
then call NextCRC for each byte to be sent
or each by received. Send CRC byte last or
check received CRC
Datum: 14.6.2011 OK
Geändert: crc counting direction, 17.06.2011, LL, SK
*****************************************************/
#include "CRC.h"
uint8 NextCRCSingle(uint8 Crc, uint8 Data, uint8 Gen, uint8 Bit)
{
uint8 Compare;
Compare=Data<<(7-Bit);
Compare&=0x80;
if((Crc & 0x80) ^ (Compare))
return (Crc << 1) ^ Gen;
else
return (Crc << 1);
}
uint8 NextCRC(uint8 Crc, uint8 Data, uint8 Gen)
{
uint8 Temp;
int i;
Temp=Crc;
for(i=0; i<=7; i++)
{
Temp=NextCRCSingle(Temp, Data, Gen, i);
}
return Temp;
}
TypeDefs.h
/*
* Types.h
*
* Created on: 29.09.2016
* Author: ed
*/
#ifndef API_TYPEDEFS_H
#define API_TYPEDEFS_H
// unsigned types
typedef unsigned char u8;
typedef unsigned short u16;
// typedef unsigned int u32;
typedef unsigned long long u64;
typedef unsigned char uint8;
typedef unsigned short int uint16;
typedef unsigned long int uint32;
typedef unsigned long long uint64;
#define u8_MAX (u8)255
#define u10_MAX (u16)1023
#define u12_MAX (u16)4095
#define u15_MAX (u16)32767
#define u16_MAX (u16)65535
#define u20_MAX (u32)1048575uL
#define u24_MAX (u32)16777215uL
#define u32_MAX (u32)4294967295uL
// signed types
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef signed char int8;
typedef signed short int int16;
typedef signed long int int32;
typedef signed long long int64;
#define s16_MAX (s16)32767
#define s16_MIN (s16)-32768
#define s24_MAX (s32)8388607
#define s24_MIN (s32)-8388608
#define s32_MAX (s32)2147483647
#define s32_MIN (s32)-2147483648
#define FALSE 0
#define TRUE 1
// parameter access
#define READ 0
#define WRITE 1
// "macros"
#define MIN(a,b) (a<b) ? (a) : (b)
#define MAX(a,b) (a>b) ? (a) : (b)
#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif
#ifndef NULL
#define NULL 0x00u
#endif
#endif /* API_TYPEDEFS_H */
RISC-V is a new instruction set architecture (ISA) designed to be scalable for a wide variety of applications. Open-sources and easy to implement, it has been named the ISA for and by the people, free of those pesky licensing fees that can weigh heavy upon BOMs.
Every embedded motor control solution contains hardware and software. And as motor control solutions are closely connected to mechanics and typically have a long product lifetime, they require much more reliable microcontroller platforms than for example user interfaces. ARM has been a reliable, stable and powerful platform over the past years. But the tendency towards consolidation of manufacturers offering M-Series ARM-controllers and the licensing model call for a new, open instruction set controller type to assure long-term availability and development.
ARM and x86 are the two leading architectures dominating the industry, followed by ARC, MIPS, Power, and Tensilica. All other ISAs are obsolete by now – either taken over by bigger ones, or simply didn’t make the cut. As a result, valuable time and money invested in the other ISAs and products using those ISAs are written off.
This doesn’t mean that the survivors of the consolidation phase are safe. If anything, Broadcom’s 130 billion USD bid to take over Qualcomm has shown that publicly traded companies can easily be subject to takeovers. So, who’s to say when the next ISA owned by a public company disappears? Sure, this won’t happen overnight, but the risk is always there.
Que RISC-V. Easy to implement, the reduced instruction set computer (RISC) set to become a standard open architecture – governed by the RISC-V foundation – for industry implementations, mitigating the risk of depending on a few manufacturers.
As with everything open source, everyone can join in to help evolve processor IP cores – which is why RISC-V has the potential to become the industry standard. It can be implemented in almost any FPGA and Microsemi states that RISC-V beats other soft-core processors such as the ARM Cortex M1, NIOS II/EF and MicroBlaze. Regardless of its performance (2.01 CoreMark/MHz), the biggest benefit is that RISC-V is open source – poised to develop faster than licensed ISAs and protected against takeovers that might make it obsolete.
Using Microsemi’s FPGAs with RISC-V cores, we’ve joined the cause – developing motor and motion control solutions that will stay available.
Keeping your videos safe is easy, right? All you need is enough storage space and those Gigabytes of childhood memories will stay right where you left them. But what if those memories were shot the old-fashioned way on 8 mm?
By design, Normal 8, Super 8 and similar videos won’t last. The cellulose acetate decomposition, a self-catalyzing degradation of the film backing that’s also called the Vinegar Syndrome, is known to ruin those precious childhood memories. It even resulted in companies and products designed to digitize them. For the avid hobbyist Wolfgang Kurz, however, buying a product was simply not an option. Instead, he designed his own cinema digitizer.
Starting out his career as land-surveyor, Wolfgang Kurz followed his passion for technology and became an IT engineer when he was 29. Now pensioned, he still follows his passion at 76 by designing applications from his home in Stuttgart.
Keeping it affordable
Ten years ago, Wolfgang designed a Java-based program called CineToVid. This was followed by CineToVidPro, based on Microsoft C# with .NET. With CineToVidPro, users can digitize their 8 mm, 9.5 mm (Pathé) and 16 mm cine films using Windows 7 or a more recent version of Windows in combination with a good flatbed scanner. Although not the ideal solution, using a flatbed scanner was the obvious choice to keep the costs low as digital microscopes were fairly expensive, making it perhaps too expensive for most people.
This all changed dramatically over the last years according to Wolfgang. “Now you can get a digital microscope for less than 40 Euro with a resolution of 720P HD (960 x 720 pixels or better with a 1.3 Megapixel chip – 4:3 aspect ratio). And that is more than sufficient for Super 8 digitization.” The result is the CineFrameCatcher.
Step by step, frame by frame
Before, the process required the scanning of filmstrips, allowing for strips of 4 to 36 frames (depending on the transparency unit width of the scanner) to be scanned and digitized. The frames would then be extracted from the strips and put into a sequence to generate the digital video. However, the manufacturing tolerances of consumer flatbed printers make this extremely difficult. These tiny differences might not be a problem when working with still images, but can lead to irksome transitions between the frames – requiring severe adjustment calculations in the software.
This is no longer necessary thanks to the new Cinema Digitizer – capturing one frame at the time in the exact same position with a digital microscope. To ensure each frame being placed exactly the same, the DIY solution uses a transport wheel with teeth that grip in the little holes of the strip, using a rotation angle identical to the distance from one hole to the next. By ensuring that one tooth of the transport wheel always transports one single frame, the angle will always be the same. “And here normal stepper motors have a problem because the accuracy is only about 5% – and that is too much,” according to Wolfgang.
The easy to use TMCM-1110 StepRocker solves the problem. Splitting up a full step into 256 microsteps, it allows for the accuracy demanded in the CineFrameCatcher. Depending on the transport wheel used (10, 20 or 25 teeth), you can set the number of steps accordingly so that one tooth translates into one frame. Furthermore, the module also provides power to the stepper motor, keeping the BOM of this do it yourself-project short and simple. The software developed by Wolfgang, together with a (free to use) video editor will take care of stabilizing the individual frames and putting them in a sequence, so that you can relive your childhood memories once more.
3D printing is great for rapid prototyping. But what do you do if the 3D printer is too small? Well… just get a bigger one of course! And while you’re at it, why not get one big enough to 3D print a Christmas tree?
This is exactly what was going on at TRINAMIC Motion Control’s headquarter from 11 December till 15 December. Thomas Sanladerer, one of the most prominent YouTubers in the 3D printing community, flew over to Hamburg together with Torbjørn Ludvigsen, creator of the Hangprinter. That’s right, a hanging 3D printer. This Norwegian born Swede was thinking outside the box when swapping the well-known rigid frame of a RepRap for fishing line. As such, you can turn any space into a 3D printer, printing objects nearly as big as the space itself.
While building the 3rd version of the Hangprinter in the lounge of Trinamic’s HQ, Thomas Sanladerer and Torbjørn Ludvigsen discussed all aspects of it while at the same time documenting their work and trying not to get caught in the wires. Behind the scenes, our engineers were answering the questions that popped up in the live stream, opening up to a community that was eager to learn more about Trinamic’s products and technologies.
All in all, it was a great project that resulted in a short series of interesting videos: Building the Hangprinter. Be sure to check out this site as well for some more information.
If you’re all excited about building your own Hangprinter, you can get yourself some SilentStepSticks and find out what else you need in the BOM below.
That’s right, you can win a BQ Witbox Go! – the latest 3D printer by Spanish company BQ using our TMC5130. There are several ways you can participate, starting by signing up to the competition. Once you’ve signed up, you can find other ways to increase your chances of winning this 3D printer!
Now that 3D printing has made its way into manufacturing, producers are looking to conquer the consumer market as well. However, with a new market comes new challenges, and a 3D printer that’s clean and has precise motion control is no longer sufficient. Consumers want silent 3D printers that are easy to use.
The first 3D printer using Android
This is where BQ’s Witbox Go! comes into play. The Spanish company designed a new printer, featuring a quad-core Qualcomm Snapdragon 410 processor and an internal memory of 8GB, which can easily be operated using any computer or Android device (Mac/iOS app coming soon). Operating a 3D printer with NFC and WiFi connectivity via a smartphone is nothing new, but operating a 3D printer from an Android device can lead to technical difficulties when the printer itself uses another OS. BQ applied their Know-How from manufacturing Android phones and tablets when designing the Go! by giving it Android Marshmallow. As a result, the Witbox Go! promises an interesting cross-device interaction. It packs the potential to remotely operate and monitor a 3D printer from your Android phone or tablet with the ease of a normal printer.
In order to save time and to focus on the 3D printer software, BQ turned to TRINAMIC Motion Control for an easy to program cDriver. They opted for the TMC5130 stepper motion control IC, which has an integrated motor drive delivering a performance of 46 V, 2 A. Just like the Witbox Go!, the TMC5130 was designed by Trinamic to be not only cost-efficient but also easy to use for designers. This allowed BQ to focus their efforts on creating the minimalist 3D printer which can easily be controlled from your Android phone or tablet.
Blending in with StealthChop
Another advantage of designing Trinamic’s TMC5130 cDriver into the Witbox Go!, is that the TMC5130 features StealthChop. This patented voltage chopper-based principle eliminates the “humming” of motors operating at a low speed. As a result, the soundless integrated motor driver and motion controller solution for 3D printing and other automated equipment applications proved to be the perfect fit for BQ’s Witbox Go! Together with the sleek, light-weight design and user-friendly interface, the silent motion control means that the printer blends in with any home or office.
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/
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 SCLK (23)
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=8, 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;
}
TRINAMIC Motion Control teams up with AISLER for rapid, powerful prototyping.
The trend towards automation, including the recent surge in IoT applications, has shown that small motors are everywhere – and so is motion control. Finding the right solution for your specific requirements, however, can be challenging. Designing your prototype, testing it, making adjustments and testing it again takes time. Valuable time.
AISLER reduces this to a minimum. They’re a one-stop-shop with everything you need to get your electronics project built and shipped right to your doorstep within 7 business days worldwide. Whether it’s PCBs, parts, or stencils. And if you design your prototype with one of Trinamic’s motion control ICs, you will get the IC for free!*
Building the next infamous and reliable product often means a great deal of complexity and meticulous parts research. Each IC developed by Trinamic comes with all the necessary information including proven reference designs, CAD symbols and sample code that you are free to use as the foundation for your own design. Depending on which chip you’re using, CoolStep, StealthChop, and other great features such as microstepping and ramping profiles can easily be activated using Trinamic’s own TMCL-IDE – an intuitive API that’s designed with ease-of-use in mind.
By partnering up, AISLER’s quick delivery cycles and Trinamic’s plug-and-play solutions shorten your time-to-market, allowing you to stay one step ahead of the rest.
*TRINAMIC Motion Control will only sponsor the following chips when designed in your prototype via AISLER: TMC2100-LA, TMC2130-LA, TMC5130-TA, TMC5041-LA, TMC389-LA, TMC2100-TA, TMC4361A-LA, TMC4330A-LA, TMC4331A-LA, TMC2224-LA, TMC2208-LA, TMC2041-LA, TMC5072-LA, TMC2130-TA.
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:
Basic configuration of TMC4361A for controlling the TMC5160 family in step/dir mode
Basic configuration of TMC5160 for step/dir mode via cover datagrams
Setting up a one stage shadow register set, see chapter 9.2.1 of TMC4361A Datasheet
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:
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/
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.
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 SCLK (23)
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:
cd ~/TMC_EXAMPLE
wget http://blog.trinamic.com/wp-content/uploads/2018/02/TMC4361A_and_TMC5160_TMCAPI_EXAMPLE.tar.gz
tar zxvf TMC5160_TMCAPI_EXAMPLE.tar.gz
#include <stdio.h>
#include <wiringPi.h>
#include <bcm2835.h>
#include <signal.h>
#include "SPI_TMC.h"
// Include the IC(s) you want to use
#include "TMC-API/tmc/ic/TMC5160/TMC5160.h"
#include "TMC-API/tmc/ic/TMC4361A/TMC4361A.h"
#define MOTOR0 0 // Motor 0
void resetMotorDrivers(uint8 motor);
void signal_callback_handler(int signum);
int main(int argc, char **argv)
{
// Register signal and signal handler
signal(SIGINT, signal_callback_handler);
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
/***** IO control of TMC4361A-BOB & TMC5160-BOB *****/
pinMode(2, OUTPUT);
digitalWrite(2, HIGH); // TMC5160: Apply VCC_IO voltage
pinMode(3, OUTPUT);
digitalWrite(3, LOW); // TMC5160: Use internal clock
pinMode(14, OUTPUT);
digitalWrite(14, LOW); // TMC5160: Enable driver stage
pinMode (4, GPIO_CLOCK);
gpioClockSet (4, 9600000); // TMC4361A: Set clock to 9.6MHz
pinMode(15, OUTPUT);
digitalWrite(15, HIGH); // TMC4361A: Low active reset
// Reset the TMC4361A & TMC5160
resetMotorDrivers(MOTOR0);
/***** Configuring TMC4361A & TMC5160 *****/
// CLK_FREQ=9.6MHz
tmc4361A_writeInt(TMC4361A_CLK_FREQ, 0x00927C00);
// SR_ENC_IN=2, FILT_L_ENC_IN=2, SR_REF=0, FILT_L_REF=0, SR_S=4, FILT_L_S=5, SR_ENC_OUT=0, FILT_L_ENC_OUT=0
tmc4361A_writeInt(TMC4361A_INPUT_FILT_CONF, 0x00540022);
// SPI_OUTPUT_FORMAT=12, DISABLE_POLLING=1, COVER_DATA_LENGTH=0, SPI_OUT_LOW_TIME=4, SPI_OUT_HIGH_TIME=4, SPI_OUT_BLOCK_TIME=8
tmc4361A_writeInt(TMC4361A_SPIOUT_CONF, 0x8440004C);
// DIRECT_ACC_VAL_EN=1, DIRECT_BOW_VAL_EN=1, STDBY_CLK_PIN_ASSIGNMENT=3
tmc4361A_writeInt(TMC4361A_GENERAL_CONF, 0x00006006);
// STP_LENGTH=4, DIR_SETUP_TIME=6
tmc4361A_writeInt(TMC4361A_STP_LENGTH_ADD, 0x00060004);
/***** TMC5160 Settings *****/
// EN_PWM_MODE=1 enables stealthChop, MULTISTEP_FILT=1, DIRECT_MODE=0 (off)
tmc4361A_writeInt(TMC4361A_COVER_HIGH_WR, TMC5160_GCONF | 0x80);
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, 0x0000000C);
delay(1); // COVER_DONE flag: ~90µs -> 1 ms more than enough
// TOFF=3, HSTRT=4, HEND=1, TBL=2, CHM=0 (spreadCycle)
tmc4361A_writeInt(TMC4361A_COVER_HIGH_WR, TMC5160_CHOPCONF | 0x80);
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, 0x000100C3);
delay(1); // COVER_DONE flag: ~90µs -> 1 ms more than enough
// IHOLD=8, IRUN=15 (max. current), IHOLDDELAY=6
tmc4361A_writeInt(TMC4361A_COVER_HIGH_WR, TMC5160_IHOLD_IRUN | 0x80);
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, 0x00080F0A);
delay(1); // COVER_DONE flag: ~90µs -> 1 ms more than enough
// TPOWERDOWN=10: Delay before power down in stand still
tmc4361A_writeInt(TMC4361A_COVER_HIGH_WR, TMC5160_TPOWERDOWN | 0x80);
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, 0x0000000A);
delay(1); // COVER_DONE flag: ~90µs -> 1 ms more than enough
// TPWMTHRS=5000
tmc4361A_writeInt(TMC4361A_COVER_HIGH_WR, TMC5160_TPWMTHRS| 0x80);
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, 0x00001388);
delay(1); // COVER_DONE flag: ~90µs -> 1 ms more than enough
/***** END of TMC5160 Settings *****/
//MOTION_PROFILE = 2 (s-shaped ramp), OPERATION_MODE = 0 (velocity mode)
tmc4361A_writeInt(TMC4361A_RAMPMODE, TMC4361A_RAMP_SSHAPE);
// Values for speed and acceleration of 1st profile
tmc4361A_writeInt(TMC4361A_AMAX, 0x00001000); // AMAX = 4096 pps²
tmc4361A_writeInt(TMC4361A_DMAX, 0x00001000); // DMAX = 4096 pps²
tmc4361A_writeInt(TMC4361A_BOW1, 0x00000200); // BOW1 = 512 pps³
tmc4361A_writeInt(TMC4361A_BOW2, 0x00000200); // BOW2 = 512 pps³
tmc4361A_writeInt(TMC4361A_BOW3, 0x00000200); // BOW3 = 512 pps³
tmc4361A_writeInt(TMC4361A_BOW4, 0x00000200); // BOW4 = 512 pps³
tmc4361A_writeInt(TMC4361A_VMAX, 0x01F40000); // VMAX = 128k pps = 2.5 RPS (1.8° motor)
// Values for speed and acceleration of 2nd profile
tmc4361A_writeInt(TMC4361A_SH_REG1, 0x00001000); // AMAX = 4096 pps²
tmc4361A_writeInt(TMC4361A_SH_REG2, 0x00001000); // DMAX = 4096 pps²
tmc4361A_writeInt(TMC4361A_SH_REG8, 0x00000200); // BOW1 = 512 pps³
tmc4361A_writeInt(TMC4361A_SH_REG9, 0x00000200); // BOW2 = 512 pps³
tmc4361A_writeInt(TMC4361A_SH_REG10, 0x00000200); // BOW3 = 512 pps³
tmc4361A_writeInt(TMC4361A_SH_REG11, 0x00000200); // BOW4 = 512 pps³
tmc4361A_writeInt(TMC4361A_SH_REG0, 0x03E80000); // VMAX = 256k pps = 5 RPS (1.8° motor)
/***** Setting up the TMC4361A for circular motion *****/
// START_EN = 8, TRIGGER_EVENTS = 8, PIPELINE_EN = 2, CYCLIC_SHADOW_REGS = 1, XPIPE_REWRITE_REG = 1
tmc4361A_writeInt(TMC4361A_START_CONF, 0x01042110);
// XRANGE = 256k (10 rotations)
tmc4361A_writeInt(TMC4361A_X_RANGE_WR, 0x0003E800);
// CIRCULAR_MOVEMENT_EN = 1
tmc4361A_writeInt(TMC4361A_REFERENCE_CONF, 0x00400000);
// POS_COMP = -256k (5 rotations)
tmc4361A_writeInt(TMC4361A_POS_COMP, 0xFFFC1800);
// 1st pipeline stage of POS_COMP = 0
tmc4361A_writeInt(TMC4361A_X_PIPE0, 0x00000000);
printf("Press \"CTRL + C\" to stop the motor(s) and to close the program\n");
delay(1);
while(1){}
// End SPI communication
bcm2835_spi_end();
bcm2835_close();
return 0;
}
void resetMotorDrivers(uint8 motor)
{
if(!tmc4361A_readInt(TMC4361A_VACTUAL))
{
digitalWrite(2, LOW); // TMC5160: Reset
delay(10);
digitalWrite(2, HIGH);
delay(10);
digitalWrite(15, LOW); // TMC4361A Reset
delay(10);
digitalWrite(15, HIGH);
delay(10);
tmc4361A_writeInt(TMC4361A_RESET_REG, 0x52535400);
}
}
void signal_callback_handler(int signum)
{
tmc4361A_writeInt(TMC4361A_VMAX, 0x00000000); // VMAX = 0 pps
digitalWrite(14, HIGH); // TMC5160: Disable driver stage
// Exit program
exit(signum);
}
#include <bcm2835.h>
#include "SPI_TMC.h"
#include "TMC-API/tmc/ic/TMC4361A/TMC4361A_Register.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);
}
// TMC4361 SPI wrapper
void tmc4361A_writeDatagram(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(0, address, value);
}
void tmc4361A_writeInt(uint8 address, int value)
{
tmc40bit_writeInt(0, address, value);
}
int tmc4361A_readInt(uint8 address)
{
tmc40bit_readInt(0, address);
return tmc40bit_readInt(0, address);
}
unsigned char tmc4361A_cover(unsigned char data, unsigned char lastTransfer)
{
static uint64 coverIn = 0; // read from squirrel
static uint64 coverOut = 0; // write to squirrel
static uint8 coverLength = 0; // data to be written
uint8 out = 0; // return value of this function
// buffer outgoing data
coverOut <<= 8; // shift left by one byte to make room for the next byte
coverOut |= data; // add new byte to be written
coverLength++; // count outgoing bytes
// return read and buffered byte to be returned
out = coverIn >> 56; // output last received byte
coverIn <<= 8; // shift by one byte to read this next time
if(lastTransfer)
{
/* Write data to cover register(s). The lower 4 bytes go into the cover low register,
* the higher 4 bytes, if present, go into the cover high register.
* The datagram needs to be sent twice, otherwise the read buffer will be delayed by
* one read/write datagram.
*/
// Send the buffered datagram & wait a bit before continuing so the 4361 can complete the datagram to the driver
// measured delay between COVER_LOW transmission and COVER_DONE flag: ~90�s -> 1 ms more than enough
// todo CHECK 3: Delay measurement only done on TMC4361, not 4361A - make sure the required delay didnt change (LH) #1
if(coverLength > 4)
tmc4361A_writeInt(TMC4361A_COVER_HIGH_WR, coverOut >> 32);
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, coverOut & 0xFFFFFFFF);
delay(1);
// Trigger a re-send by writing the low register again
tmc4361A_writeInt(TMC4361A_COVER_LOW_WR, coverOut & 0xFFFFFFFF);
// Read the reply
coverIn = 0;
if(coverLength > 4)
coverIn |= (uint64) tmc4361A_readInt(TMC4361A_COVER_DRV_HIGH_RD) << 32;
coverIn |= tmc4361A_readInt(TMC4361A_COVER_DRV_LOW_RD);
coverIn <<= (8-coverLength) * 8; // Shift the highest byte of the reply to the highest byte of the buffer uint64
// Clear write buffer
coverOut = 0;
coverLength=0;
}
return out; // return buffered read byte
}
// 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;
}
The TMC2208 stepper motor driver is an ultra-silent motor driver IC for 2-phase stepper motors. Its features and benefits make it a popular replacement for pin-compatible legacy drivers, such as the Allegro A4988. Whether you simply want to benchmark different stepper driver ICs or if you’re looking to replace an A4988 with the TMC2208 by TRINAMIC Motion Control, this application note explains in detail how you can drop-in the TMC2208 for any application that uses Allegro’s A4988.
Trinamic’s sophisticated StealthChop2 chopper is supported by the TMC2208, ensuring absolute silence except for ball bearing noise, maximum efficiency, and motor torque. Its fast current regulation and optional combination with SpreadCycle allows for highly dynamic motion, making it a popular motor driver IC for compatible design upgrades, 3D printers, office and home automation, textile, CCTV, ATMs, HVAC systems and many more applications.
When one compares the Allegro A4988 and other motor drivers with the TMC2208, Trinamic’s chip offers additional features such as:
– Power down: An automatic current reduction reduces power dissipation and cooling requirements. The standstill current is per default enabled by pulling PDN UART input to GND.
– UART: The UART single wire interface allows control of the TMC2208 with any microcontroller UART. This gives the possibility to program the TMC2208 and add additional features such as full 256 Microsteps control (not only interpolation). UART is not available in legacy mode.
– Diagnostics: An active DIAG output shows that the driver cannot work normally.
– Index: The INDEX output signals the microstep counter zero position, which occurs once per electrical revolution/four full steps. In combination with a mechanical home switch, a more precise homing is enabled.
– Microstepping: The TMC2208 is able to control the motor with 256 microsteps per full step. In legacy mode, the TMC2208 will interpolate received step signals to 256 microsteps.
For optimized performance in legacy mode, it is recommended to consider the hints shown in the application note.
Available through our distributors, it’s easy to use TRINAMIC Motion Control’s TMC2208 as a drop-in replacement for the Allegro A4988. One way of doing so is by following this application example:
A schematic of a SilentStepStick is depicted below as an application example. The TMC2208 is inserted and used in legacy mode, as shown in the second figure below. Recommended changed parts are marked blue. The Pins PDN/UART, INDEX, DIAG, MS2, MS1 feature additional or slightly changed functions as discussed in the app note.
The sense resistor should be chosen according to the motor current of the application. Table 1 (below) shows the relation between sense resistor and current for VREF = 2.5A after equation 1. For the application example, RSENSE is set to 0.18Ω which allows to control motor currents up to 1.2A.
The image above shows the pinout of the A4988. The image below shows the pinout of the TMC2208 used in legacy mode with recommended changed parts marked blue.
Following this application example to replace the Polulu A4988 with the Trinamic TMC2208, the sense resistor should be chosen according to the motor current of the application. Please have a look at the application note which explains this in further detail.
There was a time where one new product per month was a big achievement for TRINAMIC Motion Control. In 2015, there were 20 new products and in 2016 a total of 33 new products were released over the entire year. Following this trend, 60 new products were scheduled in 2018.
It became clear, however, that we will introduce more than 60 new products this year. In the second quarter of 2018 alone, we released 37 new products – that’s more products in 3 months than in the entire year of 2016!
To keep up with this pace, we’re looking for new team members who are ready for a challenge! There are several job openings in the Sales Team so take your pick and apply – are you the supportive person everyone can rely on, the one who keeps their head cool while looking for new opportunities at existing and new partners, or the adventurous Engineer always on the lookout for new customers and markets?
Expect a creative environment with all the latest tools and technologies to not only show your expertise but also grow your potential. As can be expected from the global leader in motor and motion control, you will be in touch with companies all over the world so an interest in new countries and cultures is a plus!
In the video below, our Field Application Engineer Thomas Ernst explains how you can use graphs for your own evaluations. Trinamics TMCL-IDE is an integrated development environment that allows for easy and in-depth exploration of all Trinamic products supporting the TMCL protocol.
You can try for yourself using a PD1270 PANdrive, a potentiometer, and the following script:
SAP 5, 0, 500000 //set Maximum acceleration [pps/s]
SAP 254,0,2 //GPIO mode
SAP 6, 0, 10 //set Maximum current
SAP 187, 0, 4 //set PWM gradient
SAP 186, 0, 200000 //set PWM threshold speed [pps]
ROR 0,0
Loop:
GIO 1,1
CALC SUB,4095
CALC MUL,-100
AAP 2,0
JA Loop
While the current buffer holds the data for the past 30 seconds with a possibly high time resolution, you can also monitor values over longer timespans using TMCL-IDE’s logging feature. This not only allows you to evaluate the product, it also allows for close monitoring of your application’s behavior. All values that you can display in the graphs, can also be requested through the communication interfaces. This means you’ll have full access to all parameters which are ready to be used within your own control software.
Growing success is great, but also brings about growing constraints. Expectations get higher and higher with every new goal achieved, steering life into narrow lanes. But there’s a way to escape the pressure every now and then, to overcome these limitations and revitalize, to get a new perspective on things. For some, this escape is as a sport or a hobby. For others, it’s riding motorbikes.
The Distinguished Gentleman’s Ride (DGR) allows us to combine riding motorbikes with charity: raising money for prostate cancer research and men’s mental health programs.
On September 30, the Distinguished Gentleman’s Ride 2018 will take place and all around the world dapper men and stylish women will take over the streets on their trusted two-wheelers – ranging from classic motorbikes and scooters to choppers, scramblers, café racers, and sidecars. Everyone is welcome as long as they fit the DGR style-guide – making it an event that mesmerizes the public and press every year since its start in 2012.
But it’s not all about the show. Prostate cancer and men’s mental health issues are as serious now as they were in 2012. That’s why Trinamic joins in with a team of their own and call on everyone they know to make a donation for the cause. As they say, every little bit helps.
NOTE: This blog post deals with freewheeling diodes, not with actual TL-Smoothers. For more info on TL-Smoothers, please visit our other blog post here.
There is a debate going on in the 3D printing community whether or not to use TL-Smoothers. These little modules can be added to stepper motors of 3D printers, offering recovery diodes to protect the electronic system from motor current that flows back into the system. This article discusses the use of such diodes, also known as catch diodes, flyback diodes or freewheeling diodes, and whether or not TL-Smoothers should be used in 3D printers with modern stepper drivers.
Historic use:
The idea to add recovery diodes to chopper-controlled drivers came up decades ago, when there were early (stepper motor) drivers in bipolar technology. The reason is, that bipolar devices do not automatically have internal recovery diodes: Each chopper operated motor driver (half bridge) needs so-called break-before-make operation, in order to prevent a short time short circuit between high-side and low-side device. During the so-called break-before-make (BBM) time or dead-time, both high-side and low-side devices are off. However, the inductivity of the motor coil will keep current flowing and thus it needs to flow somewhere. This is where the recovery diodes are needed – either within the driver IC, or externally. With these bipolar drivers, the external diode often has been required to protect the driver IC. It will catch motor current not only during break-before-make time, but also during times of so-called fast decay, where the motor coil feeds back energy to the power supply. Modern drivers use synchronous rectification in order to relieve the diodes and to reduce power consumption in diodes.
These bipolar drivers have been popular in the eighties and some of them are still on the market.
The first MOSFET based stepper drivers had a high MOSFET resistance due to their costly technology. They profit from the external recovery diodes, because they catch current not only during break-before-make time but also during conduction of the MOSFETs in fast-decay mode. This eliminates part of the power dissipation, and even more important a part of the power dissipation inside the IC. Reducing power dissipation allows reaching higher overall current due to reduced heating up of the driver chip itself.
Image 1: Switching diagram showing how diodes take over current with break before make time (BBM)
Effect in modern drivers:
Due to the required break-before-make (BBM) operation of each motor driver half-bridge, the intrinsic MOSFET bulk diodes become active for a short time with each switching event. Once the BBM time ends, the diodes have to recover, i.e. they go from a conducting to a non-conducting state. This recovery needs a few 10ns to roughly 150ns and some energy. As the recovery ends quite abruptly, it will cause high current spikes and inductive ringing in the interconnections with each switching event.
The external recovery diodes typically are Schottky diodes, which offer a fast and soft recovery and low forward voltage. Their recovery behavior is much better than that of the MOSFET bulk diodes. Due to the low flow voltage of the Schottky diodes, they will prevent conduction of the MOSFET bulk diodes within the driver ICs completely, and thus eliminate the recovery energy and ringing.
However, modern MOSFET drivers use improved technology which gives better recovery and also shorter, more precise BBM-times than previous older designs from the early 2000s.
There also is one additional effect which is not during actual operation: Upon hot unplugging a motor, the diodes will take over inductive currents and might save the driver from destruction.
Image 2: Diode recovery ringing, explaining ringing during reverse recovery
Actual benefits of Schottky recovery diodes
The argument to reduce power dissipation still is true with actual drivers when they are operated near their limits. However, the effect is smaller and you might not even notice the few percent difference a TL-Smoother makes in 3D printers.
The argument to improve diode recovery should be of less importance: The reason is, that MOSFET bulk diode recovery has improved a lot with modern ICs.
With a poorly designed driver IC, or poor layout, however, the current spikes caused by MOSFET driver recovery diodes could negatively influence the control part of the chip and reduce quality of the current regulation. In this case, the external diodes could also improve microstepping quality and thus printing quality. This probably is what some users see as improved printing quality with the TL-Smoothers.
For Trinamic drivers, the diodes offered on TL-Smoothers are not required and will only slightly reduce power dissipation when operating at motor currents near to the driver IC limit. In fact, when using Trinamic drivers in SpreadCycle mode, it is advised not to use recovery diodes as they negatively influence the SpreadCycle current regulation.
SpreadCycle measures both positive and negative current running through the sense resistor and uses this measurement to optimize chopper operation. Recovery diodes or TL-Smoothers allow part of the current to bypass the point of measurement, meaning SpreadCycle can’t measure the correct values. Due to this, the additional external Schottky diode from motor output to GND would negatively impact SpreadCycle operation. With StealthChop, however, there’s no negative effect of using additional recovery diodes as it measures different values.
Summed up, TL-Smoothers will only have a minor effect on the print when using state-of-the-art stepper driver ICs, so there’s no need to use them in 3D printers with Trinamic’s chips.
So, after our first blog post, which you can read here, Watterott kindly pointed out to us that our post didn’t make sense, so we looked at TL-Smoothers for 3D printers again. Turns out, our explanation of TL-Smoothers doesn’t apply to TL-Smoothers, since these small boards don’t use freewheeling diodes. Instead – and to our surprise – TL-Smoothers simply put diodes in series with the motors.
Now, what’s important to understand is that this increases power dissipation significantly because the full motor coil current drops in these diodes. With a 0.8A motor, and a voltage drop of roughly 1V (maybe less or more, depending on the number of diodes) you get 0.8W additional power dissipation per coil, i.e. 1.6W per motor.
What will the series diodes cause?
By dropping voltage they generally eliminate energy. Eliminating energy causes heat and reduces efficiency, but it also may cause dampening and thus reduce resonance. To understand in more detail, we need to look at the different chopper phases and what the diodes will cause in each phase:
On-Phase: Less voltage applied to the motor coil, so basically we lose dynamics, like with a lower supply voltage.
Fast-Decay phase: Fast decay may become a bit faster, like with a higher supply voltage. Assuming that the fast decay phase was optimum before, now it will be too long.
Slow-Decay phase: The slow decay phase is the phase with lowest power dissipation, as the motor coil current just re-circulates. In this phase, we get probably the most sensible effect: While eliminating desired motor current, at the same time the diodes will also eliminate current fed back from the motor’s back EMF due to resonances, thus offering a kind of electrical dampening. However, this is paid with a lot of energy wasted.
What does fast decay mean? Normally, stepper motor drivers not only put current actively into the coil, but they also feed back coil energy into the supply in order to reduce coil current during the falling slope. This is necessary to allow the motor current to follow the desired sine waveform. Most drivers do not control this so-called fast-decay phase, but they use a pre-determined time for fast decay. This time might be too long, which basically will just waste some energy by causing higher current ripple, but it can also be too low, which will cause a non-optimum sine wave. This might be exactly the point, where the diode array also helps. The control of this time is not easy, because the required fast decay period depends on many factors, like supply voltage, motor type, velocity and mechanical load.
So, to get back to the question if you should use TL-Smoothers on your 3D printer, you shouldn’t. At least not when using Trinamic motor drivers. Our drivers actively measure motor current, also during the fast decay time when operated in SpreadCycle, so it automatically becomes optimized.
By embedding RISC-V processor cores into our products, we’re pushing motor driver ICs to the next level. It’s a huge step forward, allowing you to create superior products faster than ever before with the new ROCINANTE family.
During electronica, Trinamic unveils its new family of motor drives with an embedded RISC-V core, dubbed ‘Rocinante’. Components in the new family combine Trinamic’s decades of experience in embedded motor and motion control together with the flexibility of an open RISC-V ISA microcontroller. The family is suitable to drive Stepper or BLDC motors, brushed DC-motors, and even voice-coil motors found in rapidly growing markets like service robots, home and office automation, light electric vehicles, and power tools.
“Embedding powerful processors into motor controllers gives us a new degree of freedom and enables features that will be indispensable in the future, e.g. condition monitoring and predictive maintenance,” explains TRINAMIC CEO and founder Michael Randt.
The debut members of the new component family will be a dedicated BLDC/PMSM driver with 6 integrated gate-drivers and a dedicated stepper motor and stepper servo driver with 8 integrated gate drivers. Both components share a rich set of integrated diagnostics and interfacing features. The whole family is equipped with a 32-bit RISC-V core, hardware-based field oriented control, serial interfaces, USB, CAN-FD and gate drivers for 2-phase or 3-phase motors. Integrated switching regulators allow for one-chip drive solutions. 128k EEPROM based non-volatile memory and 32k SRAM make it powerful enough to handle everything from standalone applications to high-level industrial protocols like CANopen or CANopen-FD.
Want to know more about our products? Visit us at electronica in Munich, hall B5, booth 449.
From evaluation kits to open-source breakout boards and easy to use building blocks, we always try to help our customers where we can. This also means making documents accessible. Not only datasheets and application notes, but also reference design schematics to give engineers fast design starts.
Miniaturization is one of the megatrends influencing application design, which in turn democratizes technology. Applications that used to be privileged to industries can now be found on people’s desks, either in their office or at home. Wearables people couldn’t even imagine a couple of years ago now fit snug on the body, ranging from medical devices to those for your entertainment.
An important aspect driving the miniaturization are EDA tools, such as Altium, OrCAD, Eagle, Mentor PADS Logic, and Mentor DxDesigner. But what’s maybe even more important are 3D models verified by the manufacturer, ensuring design engineers have the exact dimensions to work with. That’s why Trinamic geared up with the Ultra Librarian Reference Design Cloud to start rolling out such files. Thanks to EMA Design Automation and TRINAMIC Motion Control, engineers will no longer have to design 3D models of Trinamic components. Instead, engineers developing products can easily specify the Trinamic ICs in the design, with access to schematic symbols, PCB footprints, 3D models, and reference design schematics from the cloud. And, if needed, they can even make changes and download a modified schematic in OrCAD.