Quantcast
Channel: ADI Trinamic Blog
Viewing all 66 articles
Browse latest View live

Job Posting: Content Marketing Manager

$
0
0
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:
    • Website
    • Editorial opportunities (vertical horizontal)
    • Blog
    • Press releases
    • Twitter/ google+
  • Manage video content development
  • Align PR with Advertising Campaigns

If this is you –  apply now!

 


How to drive a stepper motor with your Arduino Mega using a TMC5130-EVAL

$
0
0

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.

Extract from TMC5130-EVAL schematic
Illustration 1 – Extract from TMC5130-EVAL schematic

 

tmc5130-eval-logic-level-resistor
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.

Pinheader of TMC5130-EVAL
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.

Related Pages

How to drive a stepper motor with your Raspberry Pi 3/2 using a TMC5130-EVAL

$
0
0

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
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 3 wired up with TMC5130-EVAL
Raspberry 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:

wget http://blog.trinamic.com/wp-content/uploads/2017/04/spi-5130.c

#include <bcm2835.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  bcm2835_init();
  bcm2835_spi_begin();

  bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default
  bcm2835_spi_setDataMode(BCM2835_SPI_MODE3); // The default
  bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256); // The default
  bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // The default
  bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default

  // Send 5 byte to the slave and simultaneously read a byte back from the slave

  // Read GCONF to clear reset flag
  uint8_t gconf[40] = { 0x01, 0x00, 0x00, 0x00, 0x00 };

  bcm2835_spi_transfernb(gconf, gconf, 5);

  printf("Reply of TMC5130: %02x %02x %02x %02x %02x \n", gconf[0], gconf[1], gconf[2], gconf[3], gconf[4]);

  // Write chopper configs
  uint8_t chop_conf[40] = { 0xEC, 0x00, 0x01, 0x00, 0xC5 };
  bcm2835_spi_transfernb(chop_conf, chop_conf, 5);
  printf("Reply of TMC5130: %02x %02x %02x %02x %02x \n", chop_conf[0], chop_conf[1], chop_conf[2], chop_conf[3], chop_conf[4]);

  // Write IRUN=10 IHOLD=2
  uint8_t current[40] = { 0x90, 0x00, 0x06, 0x0A, 0x02 };

  bcm2835_spi_transfernb(current, current, 5);

  printf("Reply of TMC5130: %02x %02x %02x %02x %02x \n", current[0], current[1], current[2], current[3], current[4]);

  // Write - Set RAMPMODE to 1 (Velocity mode)
  uint8_t ramp_mode[40] = { 0xA0, 0x00, 0x00, 0x00, 0x01 };

  bcm2835_spi_transfernb(ramp_mode, ramp_mode, 5);

  printf("Reply of TMC5130: %02x %02x %02x %02x %02x \n", ramp_mode[0], ramp_mode[1], ramp_mode[2], ramp_mode[3], ramp_mode[4]);

  // Write - Set acceleration to AMAX = 50000
  uint8_t amax[40] = { 0xA6, 0x00, 0x00, 0xC3, 0x50 };

  bcm2835_spi_transfernb(amax, amax, 5);

  printf("Reply of TMC5130: %02x %02x %02x %02x %02x \n", amax[0], amax[1], amax[2], amax[3], amax[4]);

  // Write - Set velocity to VMAX = 200000
  uint8_t vmax[40] = { 0xA7, 0x00, 0x03, 0x0D, 0x40 };

  bcm2835_spi_transfernb(vmax, vmax, 5);

  printf("Reply of TMC5130: %02x %02x %02x %02x %02x \n", vmax[0], vmax[1], vmax[2], vmax[3], vmax[4]);


  // End SPI communication
  bcm2835_spi_end();


  bcm2835_close();
  return 0;
}

Compiling and running the code

Please use the following command to compile the code.

gcc –o spi-test spi-5130.c –lbcm2835

This compiles the file spi-5130.c

Now you are able to execute the example.

sudo ./spi-test

Related Pages

How to drive a stepper motor closed loop with your Arduino Uno using a TMC4361A-EVAL + TMC2130-EVAL

$
0
0

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-EVAL
Illustration 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.

Related Pages

How to drive a stepper motor via UART with your Arduino Mega using a TMC5072-EVAL

$
0
0

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

TMC5072_register.h

/* 
 * TMC5072-EVAL_UART.ino
 * 
 * Created on: 20.02.2017
 *     Author: MN
 */

#ifndef TMC5072_REGISTER_H
#define TMC5072_REGISTER_H

	// ===== TMC5072 register set =====

	#define TMC5072_GCONF        0x00
	#define TMC5072_GSTAT        0x01
	#define TMC5072_IFCNT        0x02
	#define TMC5072_SLAVECONF    0x03
	#define TMC5072_INP_OUT      0x04
	#define TMC5072_X_COMPARE    0x05

	#define TMC5072_PWMCONF_1	  0x10
	#define TMC5072_PWM_STATUS_1 0x11

	#define TMC5072_PWMCONF_2	  0x18
	#define TMC5072_PWM_STATUS_2 0x19

	#define TMC5072_RAMPMODE_1   0x20
	#define TMC5072_XACTUAL_1    0x21
	#define TMC5072_VACTUAL_1    0x22
	#define TMC5072_VSTART_1     0x23
	#define TMC5072_A1_1         0x24
	#define TMC5072_V1_1         0x25
	#define TMC5072_AMAX_1       0x26
	#define TMC5072_VMAX_1       0x27
	#define TMC5072_DMAX_1       0x28
	#define TMC5072_D1_1         0x2A
	#define TMC5072_VSTOP_1      0x2B
	#define TMC5072_TZEROWAIT_1  0x2C
	#define TMC5072_XTARGET_1    0x2D
	#define TMC5072_IHOLD_IRUN_1 0x30
	#define TMC5072_VCOOLTHRS_1  0x31
	#define TMC5072_VHIGH_1      0x32
	#define TMC5072_VDCMIN_1     0x33
	#define TMC5072_SWMODE_1     0x34
	#define TMC5072_RAMPSTAT_1   0x35
	#define TMC5072_XLATCH_1     0x36
	#define TMC5072_ENCMODE_1    0x38
	#define TMC5072_XENC_1       0x39
	#define TMC5072_ENC_CONST_1  0x3A
	#define TMC5072_ENC_STATUS_1 0x3B
	#define TMC5072_ENC_LATCH_1  0x3C

	#define TMC5072_RAMPMODE_2   0x40
	#define TMC5072_XACTUAL_2    0x41
	#define TMC5072_VACTUAL_2    0x42
	#define TMC5072_VSTART_2     0x43
	#define TMC5072_A1_2         0x44
	#define TMC5072_V1_2         0x45
	#define TMC5072_AMAX_2       0x46
	#define TMC5072_VMAX_2       0x47
	#define TMC5072_DMAX_2       0x48
	#define TMC5072_D1_2         0x4A
	#define TMC5072_VSTOP_2      0x4B
	#define TMC5072_TZEROWAIT_2  0x4C
	#define TMC5072_XTARGET_2    0x4D
	#define TMC5072_IHOLD_IRUN_2 0x50
	#define TMC5072_VCOOLTHRS_2  0x51
	#define TMC5072_VHIGH_2      0x52
	#define TMC5072_VDCMIN_2     0x53
	#define TMC5072_SWMODE_2     0x54
	#define TMC5072_RAMPSTAT_2   0x55
	#define TMC5072_XLATCH_2     0x56
	#define TMC5072_ENCMODE_2    0x58
	#define TMC5072_XENC_2       0x59
	#define TMC5072_ENC_CONST_2  0x5A
	#define TMC5072_ENC_STATUS_2 0x5B
	#define TMC5072_ENC_LATCH_2  0x5C

	#define TMC5072_MSLUT0       0x60
	#define TMC5072_MSLUT1       0x61
	#define TMC5072_MSLUT2       0x62
	#define TMC5072_MSLUT3       0x63
	#define TMC5072_MSLUT4       0x64
	#define TMC5072_MSLUT5       0x65
	#define TMC5072_MSLUT6       0x66
	#define TMC5072_MSLUT7       0x67
	#define TMC5072_MSLUTSEL     0x68
	#define TMC5072_MSLUTSTART   0x69

	#define TMC5072_MSCNT_1      0x6A
	#define TMC5072_MSCURACT_1   0x6B
	#define TMC5072_CHOPCONF_1   0x6C
	#define TMC5072_COOLCONF_1   0x6D
	#define TMC5072_DCCTRL_1     0x6E
	#define TMC5072_DRVSTATUS_1  0x6F

	#define TMC5072_MSCNT_2      0x7A
	#define TMC5072_MSCURACT_2   0x7B
	#define TMC5072_CHOPCONF_2   0x7C
	#define TMC5072_COOLCONF_2   0x7D
	#define TMC5072_DCCTRL_2     0x7E
	#define TMC5072_DRVSTATUS_2  0x7F

	#define TMC5072_PWMCONF_1	  0x10
	#define TMC5072_PWM_STATUS	  0x11

	#define TMC5072_RAMPMODE     0x00
	#define TMC5072_XACTUAL      0x01
	#define TMC5072_VACTUAL      0x02
	#define TMC5072_VSTART       0x03
	#define TMC5072_A1           0x04
	#define TMC5072_V1           0x05
	#define TMC5072_AMAX         0x06
	#define TMC5072_VMAX         0x07
	#define TMC5072_DMAX         0x08
	#define TMC5072_D1           0x0A
	#define TMC5072_VSTOP        0x0B
	#define TMC5072_TZEROWAIT    0x0C
	#define TMC5072_XTARGET      0x0D
	#define TMC5072_IHOLD_IRUN   0x10
	#define TMC5072_VCOOLTHRS    0x11
	#define TMC5072_VHIGH        0x12
	#define TMC5072_VDCMIN       0x13
	#define TMC5072_SWMODE       0x14
	#define TMC5072_RAMPSTAT     0x15
	#define TMC5072_XLATCH       0x16
	#define TMC5072_ENCMODE      0x18
	#define TMC5072_XENC         0x19
	#define TMC5072_ENC_CONST    0x1A
	#define TMC5072_ENC_STATUS   0x1B
	#define TMC5072_ENC_LATCH    0x1C
	#define TMC5072_CHOPCONF     0x6C
	#define TMC5072_COOLCONF     0x6D
	#define TMC5072_DRVSTATUS    0x6F

	//Motorbits und Write-Bit
	#define TMC5072_MOTOR0       0x20
	#define TMC5072_MOTOR1       0x40
	#define TMC5072_WRITE        0x80

	//Rampenmodi (Register TMC5072_RAMPMODE)
	#define TMC5072_MODE_POSITION   0
	#define TMC5072_MODE_VELPOS     1
	#define TMC5072_MODE_VELNEG     2
	#define TMC5072_MODE_HOLD       3

	//Endschaltermodusbits (Register TMC5072_SWMODE)
	#define TMC5072_SW_STOPL_ENABLE   0x0001
	#define TMC5072_SW_STOPR_ENABLE   0x0002
	#define TMC5072_SW_STOPL_POLARITY 0x0004
	#define TMC5072_SW_STOPR_POLARITY 0x0008
	#define TMC5072_SW_SWAP_LR        0x0010
	#define TMC5072_SW_LATCH_L_ACT    0x0020
	#define TMC5072_SW_LATCH_L_INACT  0x0040
	#define TMC5072_SW_LATCH_R_ACT    0x0080
	#define TMC5072_SW_LATCH_R_INACT  0x0100
	#define TMC5072_SW_LATCH_ENC      0x0200
	#define TMC5072_SW_SG_STOP        0x0400
	#define TMC5072_SW_SOFTSTOP       0x0800

	//Statusbitss (Register TMC5072_RAMPSTAT)
	#define TMC5072_RS_STOPL          0x0001
	#define TMC5072_RS_STOPR          0x0002
	#define TMC5072_RS_LATCHL         0x0004
	#define TMC5072_RS_LATCHR         0x0008
	#define TMC5072_RS_EV_STOPL       0x0010
	#define TMC5072_RS_EV_STOPR       0x0020
	#define TMC5072_RS_EV_STOP_SG     0x0040
	#define TMC5072_RS_EV_POSREACHED  0x0080
	#define TMC5072_RS_VELREACHED     0x0100
	#define TMC5072_RS_POSREACHED     0x0200
	#define TMC5072_RS_VZERO          0x0400
	#define TMC5072_RS_ZEROWAIT       0x0800
	#define TMC5072_RS_SECONDMOVE     0x1000
	#define TMC5072_RS_SG             0x2000

	#define MOTOR_ADDR(m) (0x20 << m )
	#define MOTOR_ADDR_DRV(m)  (m << 4)

#endif

CRC.h

/****************************************************
  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 */

Download

The TMC5072-EVAL_UART zip file contains the Arduino project.

Related Pages

TMC5072-EVAL

TMC5072-LA

TRINAMIC Technology Access Package

www.trinamic.com

Joining the RISC-V foundation

$
0
0

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.

DIY Cinema Digitizer

$
0
0

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

Fig. 2 The CineToVidPro

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.

Bill Of Materials for the DIY Cinema DigitizerThe 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.

Be sure to visit Wolfgang’s website, and his tips to build your own CineFrameCatcher.

 

Do you also have an interesting project using our solutions that you want to share? Leave a comment and Corné will get in touch with you.

Building the Hangprinter

$
0
0

TRINAMIC Motion Control - Hangprinter 3D print3D 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.

Part Function Qty needed
12V 7.5A (or 10A) power supply Power supply 1
15-lead (or more) ribbon wire Connection electronics – effector 5m
Arduino Mega 2560 clone Mainboard 1
E3D Titan Aero 1.75mm Extruder 1
E3D Volcano 1.75mm / 12V Hotend 1
E3D Volcano copper nozzle 1.2mm Hotend 1 (optional)
PTFE tube 4x2mm 10cm
RAMPS Mainboard 1
TMC2130 SilentStepStick Stepper motor drivers 5
13mm (1/2″) square wood profile Effector frame 3x40cm, 1x20cm
4×10 ~ 4×20 wood screws Fastener >20
608 bearings Spool bearings 8
623VV bearings Line bearing 12
Fused fishing line (30lb or more) Effector suspension 60m
M3 nuts Fastener 25
M3 washers Fastener 35
M3x10 screws, length 10 mm Fastener 2
M3x25 screws, length 25 mm Fastener 13
M3x5 screws, length 5 mm Fastener 16
M8 nuts Fastener 4
M8 washers Fastener 4
M8x50 (or longer) countersink screws Fastener 4
MDF or plywood sheet Assembly base 47x47cm

Win a BQ Witbox Go!

$
0
0

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!

click here to enter

 

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.

 

Visit BQ’s website

 

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

 

TARGET_EXEC ?= TMCAPI_EXAMPLE
BUILD_DIR ?= ./bin
CC = gcc
CXX = g++

# C Fags
CFLAGS			+= -Wall 
CFLAGS			+= -g
LDFLAGS			+= -lbcm2835 
LDFLAGS			+= -lwiringPi

# define the C source files
SRCS				+= main.c
SRCS				+= SPI_TMC.c
# used functions from TMC_API
SRCS				+= TMC-API/tmc/helpers/Debug.c
#SRCS 			+= TMC-API/tmc/ic/TMC2130/TMC2130.c
#SRCS 			+= TMC-API/tmc/ic/TMC2208/TMC2208.c
#SRCS 			+= TMC-API/tmc/ic/TMC2224/TMC2224.c
#SRCS 			+= TMC-API/tmc/ic/TMC2660/TMC2660.c
#SRCS 			+= TMC-API/tmc/ic/TMC5130/TMC5130.c
SRCS 			+= TMC-API/tmc/ic/TMC5160/TMC5160.c
#SRCS				+= TMC-API/tmc/ic/TMC4330/TMC4330.c
#SRCS				+= TMC-API/tmc/ic/TMC4331/TMC4331.c
#SRCS				+= TMC-API/tmc/ic/TMC4361/TMC4361.c
#SRCS				+= TMC-API/tmc/ic/TMC4361A/TMC4361A.c
#SRCS				+= TMC-API/tmc/ic/TMC4670/TMC4670.c
#SRCS				+= TMC-API/tmc/ic/TMC4671/TMC4671.c
#SRCS				+= TMC-API/tmc/ic/TMC4672/TMC4672.c
#SRCS				+= TMC-API/tmc/ic/TMCC160/TMCC160.c
#SRCS				+= TMC-API/tmc/ic/TMC5041/TMC5041.c
#SRCS				+= TMC-API/tmc/ic/TMC5062/TMC5062.c
#SRCS				+= TMC-API/tmc/ic/TMC5072/TMC5072.c

OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:.o=.d)

$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
	$(CC) $(OBJS) -o $@ $(LDFLAGS)

# assembly
$(BUILD_DIR)/%.s.o: %.s
	$(MKDIR_P) $(dir $@)
	$(AS) $(ASFLAGS) -c $< -o $@ $(LDFLAGS)

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

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


.PHONY: clean

clean:
	$(RM) -r $(BUILD_DIR)

-include $(DEPS)

MKDIR_P ?= mkdir -p

Compiling and running the code

Use the following command to compile the code.

cd ~/TMC_EXAMPLE

make

Now you are able to execute this example.

sudo ~/TMCAPI_test/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

Your Project in Motion with Powerful Prototypes

$
0
0

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.

Visit www.aisler.net/trinamic for more information.

 

*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.

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

$
0
0

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:

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

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

 

/*
 * 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);

// TMC4361A SPI wrapper
void tmc4361A_writeDatagram(uint8 address, uint8 x1, uint8 x2, uint8 x3, uint8 x4);
void tmc4361A_writeInt(uint8 address, int value);
int tmc4361A_readInt(uint8 address);
unsigned char tmc4361A_cover(unsigned char data, unsigned char lastTransfer);

// 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"
#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;
}

 

TARGET_EXEC ?= TMCAPI_EXAMPLE
BUILD_DIR ?= ./bin
CC = gcc
CXX = g++

# C Fags
CFLAGS			+= -Wall 
CFLAGS			+= -g
LDFLAGS			+= -lbcm2835 
LDFLAGS			+= -lwiringPi

# define the C source files
SRCS				+= main.c
SRCS				+= SPI_TMC.c
# used functions from TMC_API
SRCS				+= TMC-API/tmc/helpers/Debug.c
#SRCS 			+= TMC-API/tmc/ic/TMC2130/TMC2130.c
#SRCS 			+= TMC-API/tmc/ic/TMC2208/TMC2208.c
#SRCS 			+= TMC-API/tmc/ic/TMC2224/TMC2224.c
#SRCS 			+= TMC-API/tmc/ic/TMC2660/TMC2660.c
#SRCS 			+= TMC-API/tmc/ic/TMC5130/TMC5130.c
SRCS 			+= TMC-API/tmc/ic/TMC5160/TMC5160.c
#SRCS				+= TMC-API/tmc/ic/TMC4330/TMC4330.c
#SRCS				+= TMC-API/tmc/ic/TMC4331/TMC4331.c
#SRCS				+= TMC-API/tmc/ic/TMC4361/TMC4361.c
SRCS				+= TMC-API/tmc/ic/TMC4361A/TMC4361A.c
#SRCS				+= TMC-API/tmc/ic/TMC4670/TMC4670.c
#SRCS				+= TMC-API/tmc/ic/TMC4671/TMC4671.c
#SRCS				+= TMC-API/tmc/ic/TMC4672/TMC4672.c
#SRCS				+= TMC-API/tmc/ic/TMCC160/TMCC160.c
#SRCS				+= TMC-API/tmc/ic/TMC5041/TMC5041.c
#SRCS				+= TMC-API/tmc/ic/TMC5062/TMC5062.c
#SRCS				+= TMC-API/tmc/ic/TMC5072/TMC5072.c

OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:.o=.d)

$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
	$(CC) $(OBJS) -o $@ $(LDFLAGS)

# assembly
$(BUILD_DIR)/%.s.o: %.s
	$(MKDIR_P) $(dir $@)
	$(AS) $(ASFLAGS) -c $< -o $@ $(LDFLAGS)

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

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


.PHONY: clean

clean:
	$(RM) -r $(BUILD_DIR)

-include $(DEPS)

MKDIR_P ?= mkdir -p

Compiling and running the code

Use the following command to compile the code.

cd ~/TMC_EXAMPLE

make

Now you are able to execute this example.

sudo ~/TMCAPI_test/bin/TMCAPI_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

How to replace an Allegro A4988 with the TMC2208

$
0
0

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.

Trinamic is looking for you!

$
0
0

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!

Click here for all job openings

 

How to use graphs within TMCL-IDE and log data

$
0
0

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.

You can find more information on the TMCL-IDE over here, including a download.


The Distinguished Gentleman’s Ride 2018

$
0
0

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.

Donate now by sponsoring Trinamic MC

 

TL-Smoothers, do 3D printers really need them?

$
0
0

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.

Break Before Make Time (BBM) explained

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.

TL-Smoothers, do they make sense?

$
0
0

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.

 

Taking motion control to the next level with RISC-V

$
0
0

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.

Online Reference Design Cloud with Trinamic Components

$
0
0

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.

Read the entire press release here

Viewing all 66 articles
Browse latest View live


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