Open-loop test with Arduino Mega 2560 and Trinamics TMC6200-BOB

Hi all,

I’m trying to pass the 3PWM open-loop test with the following setup:

  • MCU: Arduino Mega 2560
  • Driver: Trinamics TMC6200-BOB
  • Motor: iPower Motor GM3506

Unfortunately, I cannot manage to make it work. The Trinamics TMC6200-BOB has a fault detection feature that triggers as soon as I power my setup, disabling the power stage of the driver. I supply the motor with a lab power bench set on +12V, and no overcurrent is detected.

Is there something wrong with my setup? I’d be grateful for any help!


I have TMC6200 and TMC6300, they are 6PWM logic and i had no success running them on 3PWM,
it seem that whenever i tried to save some PWM I/O with 3PWM i had the DIAG led turned on.

What you can do is hook up BOB to Motor without logic, and try spin BLDC motor, the diag should lit white.

Also you need DRV_EN to be high, if its driven too low it will produce fault and will trigger DIAG led on,
Although with SimpleFOC the driver enable is optional and so is for some of the IC’s, the TMC’s on high power chips require EN to be driven hight and mandatory.

Did you hook it up to SPI to read the registers of driver? This IC is some badass one allow to make very reliable designs with the SPI interface read out, it monitors almost all input pins:

0 UL
1 UH
2 VL
3 VH
4 WL
5 WH
7 0
9 OT136°C
10 OT143°C

Hi Karl, thank you very much for your help!

I also tried the 6PWM with no better luck. This time, the FAULT pin stays low but the motor doesn’t move and stays very stiff, and my power bench voltage drops and current limit triggers… I checked that the PWM pins I used were from the same timer for the Arduino Mega 2560:

U: pins 11 (high side) and 12 (low side) → timer1
V: pins 9 (high side) and 10 (low side) → timer2
W: pins 7 (high side) and 8 (low side) → timer4

For the DRV_EN pin, I just tied it to +Vio as I saw on the TMC6200 datasheet. Isn’t it equivalent to using the enable function with SimpleFOC?

I’ll try to check the registers with the 3PWM, but as my attempt with the 6PWM was unsuccessful, it tells me that maybe something else is happening here.

Here is my code, if someone wants to have a look:

// Open loop motor control example
#include <SimpleFOC.h>

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(11);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver6PWM driver = BLDCDriver6PWM(11, 12, 9, 10, 7, 8);

// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&, cmd); }

int faultIn = 2; // FAULT output of driver connected to pin 2
int ledPin = 13;  // LED connected to digital pin 13
int faultState = 0; // variable to store the driver FAULT state

void setup() {

  pinMode(faultIn, INPUT);
  pinMode(ledPin, OUTPUT);

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  driver.pwm_frequency = 20000;
  driver.dead_zone = 0.05;
  // link the motor and the driver

  // limiting motor movements
  motor.phase_resistance = 12.5; // [Ohm]
  motor.current_limit = 2;   // [Amps] - if phase resistance defined
  motor.velocity_limit = 5; // [rad/s] cca 50rpm
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware

  // add target command T
  command.add('T', doTarget, "target velocity");

  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");

void loop() {

  faultState = digitalRead(faultIn);

  if (faultState == HIGH)
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin, LOW);

  // open loop velocity movement
  // using motor.voltage_limit and motor.velocity_limit

  // user communication;

The disable() function depends on a hardware enable/disable function in the driver, and the enable pin being connected to the MCU and passed to the driver, for it to actually be able to physically disable the driver… otherwise, the disable() function just sets the PWM to zero, which normally will close all the high side FETs, open all the low side FETs, but leave everything else “on”, so to speak.

Thanks, I see!
I tied pin 5 of the Arduino Mega to the DRV_EN pin of the TMC6200-BOB and declared it as the “enabled pin” in the BLDCDriver6PWM declaration, but nothing happened… Then I removed the jumper from pin 5 to DRV_EN and left it unconnected, and the motor started to move randomly (jitter), and the PSU voltage dropped from 12V to around 9V…

It’s quite complicated to troubleshoot as I do not have an oscilloscope.

I have the following configurations on the TMC6200-BOB:

  • Standalone mode
  • Driver Strength: 0.5A (following the recommendations in the introduction of the TMC6200-BOB’s datasheet)
  • Individual gate control (for 6PWM operation)

Also, I tried to visualize the PWM signals out of the Arduino using a logic analyzer, with the code provided in my previous answer. I do not see any PWM modulation with this code on the specified pins.

However, I do see PWM modulation on the driver with the blcd_driver_3pwm_standalone example!

Hey, while I don’t use the atmega 2560 myself, I looked in our code for its PWM support, and it does support 6-PWM…

But the only pins you can use are these:

9,10 on one phase
11,12 on one phase
4,13 on one phase

it doesn’t actually matter which is high and which is low, as long as you use these pairs of pins…

So looking at your code you need to be using pins 4 and 13 instead of pins 7 and 8.

1 Like


Thank you for your help! Now I see the PWM modulation.

I’m unable to test it with a motor at the moment but I’ll get back to you once I will!

1 Like


I finally managed to test it with the motor. Unfortunately, I faced the same problem as before and the FAULT pin of the TMC6200 keeps going high.

This time, I configured the TMC6200 in SPI mode as Karl suggested. This way, I was able to get the state of the GSTAT register of the TMC6200 (the fault detection register).

Turns out the following bits of the GSTAT register are high:

  • uv_cp
  • s2gu
  • s2vsu
  • s2gv
  • s2vsv

Which indicates a short circuit between GND and VM on phase U and V. Sometimes, it triggers the others registers bits for short on W as well, it seems quite random.

I did a bit more investigations with my logic analyzer on the PWM outputs of the Arduino and I saw that VH and VL (last two channels on the plot) were driven HIGH at the same time:

This explains why the TMC6200 raises a fault. I use the following pins following Runger answer:

U: pins 9 (high side) and 10 (low side)
V: pins 11 (high side) and 12 (low side)
W: pins 4 (high side) and 13 (low side)

Is there something I am missing using the library?

Hey @Navymud,

This is very strange, as the chennales VH an dVL aren’t neither in syn nor inverted. Could you test the standalone driver example in the library examples and set show us all the signals using your logic analyser?

It is possible that there is a bug in the low lever mega2560 library code. :smiley:


Yes sure, here are two screenshots showing the high and low sides PWMs (I only have 4 channels on my logic analyzer), with the standalone example code. I only modified the pins to match Runger’s answer.

Here are phase U and V:

And here are phase U and W:

Phase U and W seems fine though, as we can clearly see the phase inversion and the dead time. The problem really seems to come from V. It almost seems like the high side is somehow synced with U: it goes low as UL goes low and then goes high as UH goes high after the dead- time.

Hey @Navymud,

This is very strange as these pins cannot belong to the same timer. So I’ve updated the code in the dev branch to allow for more timer high-low pair combinations. It would be really cool if you could try it out.

Now allowed pairs will be:

Timer PWM pin pairs
TIM0 4, 13
TIM1 11, 12
TIM2 10, 9
TIM3 5, 2
TIM4 6, 7
TIM5 45, 46

It would be awesome if you could let us know if some other pin combination will work for you.

If you are not sure how to use the dev branch, you can also only copy paste the changes that I’ve made. Ony thing that you need to do is go to your SimpleFOC library code and navigate to src\drivers\hardware_specific\atmega2560_mcu.cpp and replace the function _configureComplementaryPair with this code

// function configuring pair of high-low side pwm channels, 32khz frequency and center aligned pwm
// supports Arudino/ATmega2560
int _configureComplementaryPair(int pinH, int pinL) {
  if( (pinH == 4 && pinL == 13 ) || (pinH == 13 && pinL == 4 ) ){
    // configure the pwm phase-corrected mode
    TCCR0A = ((TCCR0A & 0b11111100) | 0x01);
    // configure complementary pwm on low side
    if(pinH == 13 ) TCCR0A = 0b10110000 | (TCCR0A & 0b00001111) ;
    else TCCR0A = 0b11100000 | (TCCR0A & 0b00001111) ;
    // set prescaler to 1 - 32kHz freq
    TCCR0B = ((TCCR0B & 0b11110000) | 0x01);
  }else if( (pinH == 11 && pinL == 12 ) || (pinH == 12 && pinL == 11 ) ){
    // set prescaler to 1 - 32kHz freq
    TCCR1B = ((TCCR1B & 0b11111000) | 0x01);
    // configure complementary pwm on low side
    if(pinH == 11 ) TCCR1A = 0b10110000 | (TCCR1A & 0b00001111) ;
    else TCCR1A = 0b11100000 | (TCCR1A & 0b00001111) ;
  }else if((pinH == 10 && pinL == 9 ) || (pinH == 9 && pinL == 10 ) ){
    // set prescaler to 1 - 32kHz freq
    TCCR2B = ((TCCR2B & 0b11111000) | 0x01);
    // configure complementary pwm on low side
    if(pinH == 10 ) TCCR2A = 0b10110000 | (TCCR2A & 0b00001111) ;
    else TCCR2A = 0b11100000 | (TCCR2A & 0b00001111) ;
  }else if((pinH == 5 && pinL == 2 ) || (pinH == 2 && pinL == 5 ) ){
    // set prescaler to 1 - 32kHz freq
    TCCR3B = ((TCCR3B & 0b11111000) | 0x01);
    // configure complementary pwm on low side
    if(pinH == 5 ) TCCR3A = 0b10110000 | (TCCR3A & 0b00001111) ;
    else TCCR3A = 0b11100000 | (TCCR3A & 0b00001111) ;
  }else if((pinH == 6 && pinL == 7 ) || (pinH == 7 && pinL == 6 ) ){
    // set prescaler to 1 - 32kHz freq
    TCCR4B = ((TCCR4B & 0b11111000) | 0x01);
    // configure complementary pwm on low side
    if(pinH == 6 ) TCCR4A = 0b10110000 | (TCCR4A & 0b00001111) ;
    else TCCR4A = 0b11100000 | (TCCR4A & 0b00001111) ;
  }else if((pinH == 46 && pinL == 45 ) || (pinH == 45 && pinL == 46 ) ){
    // set prescaler to 1 - 32kHz freq
    TCCR5B = ((TCCR5B & 0b11111000) | 0x01);
    // configure complementary pwm on low side
    if(pinH == 46 ) TCCR5A = 0b10110000 | (TCCR5A & 0b00001111) ;
    else TCCR5A = 0b11100000 | (TCCR5A & 0b00001111) ;
    return -1;
  return 0;

Hi Antun,

Thank you for your help! The standalone example works fine with the pins (5,2) instead of (11,12). I didn’t had the time to test the other combinations yet. I’m not sure what is up with (11,12) but every time I use those pins in the configuration I ended up with the weird signal I showed in my previous post.

I also tried the open-loop example that I sent earlier in the discussion with no luck: the FAULT pin of the TMC6200 still goes high and the register still blames short circuits on phases. This time I don’t really understand why since the PWM signals looks fine with the new pins.

I was tempted to blame the TMC6200-BOB board but after a simplistic trial with a handwritten driver code, the motor spins fine, so it seems like there is still something going on with the usage of the library with the Mega and the TMC6200.

I’ll try the other pins configurations with the standalone code and let you know if I come across the problem that I had with pins (11,12)!

Hey @Navymud,

Thank you for the feedback!
This is so strange. It really does not make sense, because this iPower motor almost cannot create over-current of the driver. It has to be some short circuit somewhere.

Unfortunately I don’t have a mega2560 to help you out with testing, let me know if there is any way I can help.