Quantcast
Channel: Open Source Hardware – Trinamic Blog

Now Available at Watterott: silentStepStick with TMC2100

$
0
0

Make your 3D-Printer silent with silentStepStick and stealthChop

SilentStepStick is a stepStick And Polulu compatible small stepper driver board with TMC2100, a great microstep resolution of 256 times and an interpolator so you can use it with standard step pulse engines.

It is designed and manufactured by Watterott electronic in Germany and shipped to the whole world.

 


A great Review of the silentStepStick Stepper Motor Driver Board

$
0
0

Hey Thank you Thomas for the great explanations to the silentStepStick boards and TMC2100!

We really appreciate your feedback.

 

 

First TRAMS prototype arrived today

$
0
0

Today the first protos of our new TRINAMIC RepRap Arduino Mega Shield (TRAMS) arrived – looking forward to having it operational in a few days.

TRAMS is a derivative of the popular RAMPS board and is build to work with an Arduino Mega Board. We developed a Marlin variant that uses the internal ramp controllers of TMC5130 and thus relieves the MCU from the task of generating the step pulses.

We will solve the “double step” problem all available open source printer solutions have. In addition TMC5130 comes with the absolutely silent stealthChop™ mode and will make the printer as silent as it can be.

Of course the board will be open source hardware and the firmware will be given back to the open source.

First print from TRAMS 3D-Printer Shield

$
0
0

For some weeks now we are working on our TRAMS 3D-printer shield – TRAMS is  a derivative of the popolar RAMPS shield for Arduino Mega Boards.

TRAMS is based on 4 TMC5130 cDriver –  a Stepper motor driver with integrated ramp controller, so it offloads the AVR and reduces interrupt load to 10% of the original load.

TMC5130 comes with the same stealthChop™ feature we introduced in out TMC2100 and TMC2130, that is already known from the silentStepStick and makes the fans and mechanics the loudes part at the printer.

The firmware is integrated in the popular Marlin software and controlled by repetier host and will of course be open source as the hardware design will be.

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 reboot -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 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

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

$
0
0

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.


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

$
0
0

This start-up guide explains how to connect your Raspberry Pi 3 to the TMC5160-BOB – the breakout board of the brand new TMC5160. We’ll be using the internal Motion Controller and +3V3 logic supply for the TMC5160. The wiring will be limited to the basic functionality to communicate via SPI. The usage of the TRINAMIC’s API – TMC-API – is minimizing the software effort.

Preparation

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

sudo apt update
 
sudo apt upgrade

Download and install the bcm2835 library. Note XXX is a placeholder for the latest version. For this guide version “1.52” was used. In this case, XXX is replaced by “1.52”. You can check the latest version by scrolling to the bottom of the following page: http://www.airspayce.com/mikem/bcm2835/

wget http://www.airspayce.com/mikem/bcm2835/bcm2835-XXX.tar.gz

tar zxvf bcm2835-XXX.tar

cd bcm2835-XXX

./configure

make

sudo make check

sudo make install

Create a project folder and download the latest TMC-API. Note X.XX is a placeholder for the latest version. For this guide version “3.02” was used. In this case, X.XX is replaced by “3.02”. You can check the latest version by scrolling to the bottom of the following page: https://www.trinamic.com/support/software/access-package/

mkdir ~/TMC_EXAMPLE

cd ~/TMC_EXAMPLE

wget https://www.trinamic.com/fileadmin/assets/Products/Eval_Software/TMC-API_Release_vX.XX.zip

unzip TMC-API_Release_vX.XX.zip

mv TMC-API_Release_vX.XX TMC-API

Wiring

The wiring is very simple. You will need 8 jumper wires. As a reference you can use the TMC5160-BOB_datasheet_Rev1.0.pdf. You will find the signals that are on each pin.

Signal Raspberry Pi 3 TMC5160-BOB
VCC_IO GPIO02 (3) VCC_IO (1)
GND GND (39) GND (2)
SPI Chip select (CS) SPI0 CE0 N (24) CSN (3)
SPI CLK SPI0 SCLK (23) SCK (4)
MOSI SPI0 MOSI (19) SDI (5)
MISO SPI0 MISO (21) SDO (6)
TMC5160 CLK GPIO04 (7) CLK (8)
TMC5160 DRV_ENN GPIO03 (5) DRV_ENN (9)

TMC5160-BOB

 

Raspberry Pi 3 GPIO Header – Source: https://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-3-model-b-gpio-40-pin-block-pinout

Raspberry Pi Code

An example code to initialize the TMC5160 is shown below. These files need to be placed in the same project folder as the TMC-API, in this case into ~/TMC_EXAMPLE. First, +3.3V is supplied to VCC_IO, the driver stages are enabled by pulling down DRV_ENN and the internal clock is used by pulling down CLK16. Afterwards, the TMC5160 is initialized and a simple move to position cycle is executed. The sequence will rotate a 200 full stepper motor 10 revolutions clockwise and 10 revolutions counterclockwise – depending on the wiring of the stepper motor. Please refer to the TMC5160 datasheet or the TMCL-IDE as a reference for the different registers.

You can also download the source files directly with your Pi:

cd ~/TMC_EXAMPLE

wget http://blog.trinamic.com/wp-content/uploads/2018/01/TMC5160_TMCAPI_EXAMPLE.tar.gz

tar zxvf TMC5160_TMCAPI_EXAMPLE.tar.gz

 

#include <stdio.h>
#include <wiringPi.h>
#include <bcm2835.h>
#include "SPI_TMC.h"

// Include the IC(s) you want to use
#include "TMC-API/tmc/ic/TMC5160/TMC5160.h"

#define MOTOR0			0 // Motor 0

void resetMotorDrivers(uint8 motor);

int main(int argc, char **argv) {
	if (!bcm2835_init())
      return 1;

	wiringPiSetupGpio();
  	
	// Initiate SPI 
	bcm2835_spi_begin();
	bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // MSB first
  	bcm2835_spi_setDataMode(BCM2835_SPI_MODE3); // SPI Mode 3
  	bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256); // 1 MHz clock
  	bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // define CS pin
	bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // set CS polarity to low
	

	/***** TMC5160-BOB Example *****/
	pinMode(2, OUTPUT);
	digitalWrite(2, HIGH); // Apply VCC_IO voltage to Motor 0
	pinMode(3, OUTPUT);
	digitalWrite(3, LOW); // Use internal clock
	pinMode(4, OUTPUT);
	digitalWrite(4, LOW); // Enable driver stage

	resetMotorDrivers(MOTOR0);

	// MULTISTEP_FILT=1, EN_PWM_MODE=1 enables stealthChop™
	tmc5160_writeInt(MOTOR0, TMC5160_GCONF, 0x0000000C);

	// TOFF=3, HSTRT=4, HEND=1, TBL=2, CHM=0 (spreadCycle™)
	tmc5160_writeInt(MOTOR0, TMC5160_CHOPCONF, 0x000100C3);

	// IHOLD=10, IRUN=15 (max. current), IHOLDDELAY=6
	tmc5160_writeInt(MOTOR0, TMC5160_IHOLD_IRUN, 0x00080F0A);

	// TPOWERDOWN=10: Delay before power down in stand still
	tmc5160_writeInt(MOTOR0, TMC5160_TPOWERDOWN, 0x0000000A);

	// TPWMTHRS=500
	tmc5160_writeInt(MOTOR0, TMC5160_TPWMTHRS, 0x000001F4); 

	// Values for speed and acceleration
	tmc5160_writeInt(MOTOR0, TMC5160_VSTART, 1);
	tmc5160_writeInt(MOTOR0, TMC5160_A1, 5000);
	tmc5160_writeInt(MOTOR0, TMC5160_V1, 26843);
	tmc5160_writeInt(MOTOR0, TMC5160_AMAX, 5000);   
	tmc5160_writeInt(MOTOR0, TMC5160_VMAX, 100000);
	tmc5160_writeInt(MOTOR0, TMC5160_DMAX, 5000);
	tmc5160_writeInt(MOTOR0, TMC5160_D1, 5000);
	tmc5160_writeInt(MOTOR0, TMC5160_VSTOP, 10);
	tmc5160_writeInt(MOTOR0, TMC5160_RAMPMODE, TMC5160_MODE_POSITION);

	while(1)
	{
		// put your main code here, to run repeatedly:
		printf("Reply of TMC5160: 0x%08x\n", tmc5160_readInt(MOTOR0, TMC5160_XACTUAL));
		tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x0007D000);
		//XTARGET = 512000 -> 10 revolutions with micro step = 256
		
		delay(12000);
		
		printf("Reply of TMC5160: 0x%08x\n", tmc5160_readInt(MOTOR0, TMC5160_XACTUAL));
		tmc5160_writeInt(MOTOR0, TMC5160_XTARGET, 0x00000000); //XTARGET=0
		
		delay(12000);
	}

	// End SPI communication
  	bcm2835_spi_end();
   	bcm2835_close();

	return 0;
}

void resetMotorDrivers(uint8 motor)
{
	if(!tmc5160_readInt(MOTOR0, TMC5160_VACTUAL)) 
	{
		digitalWrite(2, LOW); // Apply VCC_IO voltage to Motor 0
		delay(10);
		digitalWrite(2, HIGH); // Apply VCC_IO voltage to Motor 0
		delay(10);
	}
}

 

/*
 * SPI_TMC.h
 *
 *  Created on: 12.01.2018
 *      Author: MN
 */
#ifndef SPI_TMC_H
#define SPI_TMC_H

#include "TMC-API/tmc/helpers/API_Header.h"

void initSPI(void);

// TMC5160 SPI wrapper
void tmc5160_writeDatagram(uint8 motor, uint8 address, uint8 x1, uint8 x2, uint8 x3, uint8 x4);
void tmc5160_writeInt(uint8 motor, uint8 address, int value);
int tmc5160_readInt(u8 motor, uint8 address);

// General SPI functions
void tmc40bit_writeInt(u8 motor, uint8 address, int value);
int tmc40bit_readInt(u8 motor, uint8 address);

#endif /* SPI_TMC_H */

 

#include <bcm2835.h>
#include "SPI_TMC.h"


// TMC5160 SPI wrapper
void tmc5160_writeDatagram(uint8 motor, uint8 address, uint8 x1, uint8 x2, uint8 x3, uint8 x4)
{
    int value = x1;
	value <<= 8;
	value |= x2;
	value <<= 8;
	value |= x3;
	value <<= 8;
	value |= x4;

    tmc40bit_writeInt(motor, address, value);
}

void tmc5160_writeInt(uint8 motor, uint8 address, int value)
{
    tmc40bit_writeInt(motor, address, value);
}

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

// General SPI decription
void tmc40bit_writeInt(u8 motor, uint8 address, int value)
{
    char tbuf[5];
    tbuf[0] = address | 0x80;
    tbuf[1] = 0xFF & (value>>24);
    tbuf[2] = 0xFF & (value>>16);
    tbuf[3] = 0xFF & (value>>8);
    tbuf[4] = 0xFF & value;

    bcm2835_spi_writenb (tbuf, 5);
}

int tmc40bit_readInt(u8 motor, uint8 address)
{
    char tbuf[5], rbuf[5];
    int value;
	// clear write bit
	tbuf[0] = address & 0x7F;
    
    bcm2835_spi_transfernb (tbuf, rbuf, 5);

	value =rbuf[1];
	value <<= 8;
	value |= rbuf[2];
	value <<= 8;
	value |= rbuf[3];
	value <<= 8;
	value |= rbuf[4];

	return value;
}

 

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

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

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

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

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

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


lt; -o $@ $(LDFLAGS)

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


lt; -o $@ $(LDFLAGS)

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


lt; -o $@ $(LDFLAGS)

.PHONY: clean

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

-include $(DEPS)

MKDIR_P ?= mkdir -p

Compiling and running the code

Use the following command to compile the code.

cd ~/TMC_EXAMPLE

make

Now you are able to execute this example.

sudo ~/TMC_EXAMPLE/bin/TMCAPI_EXAMPLE

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

Related Pages

TMCL-IDE

TMC5160

TMC5160-BOB

TRINAMIC Technology Access Package -TMC-API

www.trinamic.com

Reference Design for Battery-Powered IoT Devices

$
0
0

The TMC2300-IOT-REF is a completely open-source reference design for easy evaluation of the TMC2300-LA stepper motor driver IC. Whether it’s a POS device, toys, office and home automation, or mobile medical devices, Engineers can quickly prototype IoT applications running on 3.5 – 6 V batteries.

Besides the low-voltage stepper motor driver, the board features a Li-Ion cell charger via USB-C, an ESP32-PICO-D4 processor with integrated WiFi and BLE capabilities, as well as UART and USB-C for serial communication and programming. Other features including StealthChop2™, StallGuard4™ and CoolStep™ bring industrial-grade solutions to convenient, handheld devices.



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