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

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


Viewing all articles
Browse latest Browse all 66

Trending Articles



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