TMC6200 BOB with arduino via spi

Hello,
I have connected TMC6200 BOB with arduino via SPI.
But it doesn’t work

This is the configuration
VCC - 3.3V from Arduino
GND - GND from Arduino
CSN - Pin 10 Arduino
MOSI - Pin 11 Arduino
MISO - Pin 12 Arduino
SCK - Pin 13 Arduino

From external PSU
24V to VM
GND from PSU to GND

and

Phase Pins

U - U
V - V
W - W

but it doesn’t work.

Any thoughts.

I am using the code without a library, only the SPI library.

#include <SPI.h>

// Define TMC6200 register addresses
#define GCONF      0x00
#define IHOLD_IRUN 0x10
#define TPOWERDOWN 0x11
#define CHOPCONF   0x6C
#define PWMCONF    0x70

// Define SPI pins
#define SS_PIN 10

void setup() {
  Serial.begin(9600);
  pinMode(SS_PIN, OUTPUT);

  // Initialize SPI
  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));

  // Configure TMC6200 settings
  configureTMC6200();
}

void loop() {
  // Run motor at full speed
  setMotorSpeed(1000);  // Adjust speed as needed
}

void configureTMC6200() {
  // Set GCONF register
  writeRegister(GCONF, 0x00000110);  // Example configuration, adjust as needed

  // Set IHOLD_IRUN register
  writeRegister(IHOLD_IRUN, 0x000000AA);  // Example configuration, adjust as needed

  // Set TPOWERDOWN register
  writeRegister(TPOWERDOWN, 0x00000000);

  // Set CHOPCONF register
  writeRegister(CHOPCONF, 0x000100D1);  // Example configuration, adjust as needed

  // Set PWMCONF register
  writeRegister(PWMCONF, 0x00050404);  // Example configuration, adjust as needed
}

void setMotorSpeed(int speed) {
  // Convert speed to PWM duty cycle
  int pwmValue = map(speed, 0, 1000, 0, 255);

  // Send PWM value to motor
  analogWrite(SS_PIN, pwmValue);
}

void writeRegister(byte address, uint32_t data) {
  // Send write command
  digitalWrite(SS_PIN, LOW);
  SPI.transfer(address | 0x80);  // Set write bit
  SPI.transfer((data >> 24) & 0xFF);
  SPI.transfer((data >> 16) & 0xFF);
  SPI.transfer((data >> 8) & 0xFF);
  SPI.transfer(data & 0xFF);
  digitalWrite(SS_PIN, HIGH);
}

Hey @Endrit, welcome to SimpleFOC!

have you tried our driver for the TMC6200? Its in our drivers library:

Perhaps it will work for you?

Compilation error: SimpleFOC.h: No such file or directory

Hello, for example i am getting this error when compile

c:\users\endrit\documents\arduino\libraries\simplefocdrivers\src\comms\registerreceiver.h:5:10: fatal error: common/base_classes/FOCMotor.h: No such file or directory

These errors seem like you don’t have both libraries included?

#include <Arduino.h>
#include <SPI.h>
#include "SimpleFOC.h"
#include "SimpleFOCDrivers.h" 
#include "drivers/tmc6200/TMC6200.hpp"


...

is that how you have it?

Yeah, i have installed all library

C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:46: error: ‘UH’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:46: note: suggested alternative: ‘ZH’
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
ZH
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:50: error: ‘UL’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:50: note: suggested alternative: ‘YL’
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
YL
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:54: error: ‘VH’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:54: note: suggested alternative: ‘ZH’
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
ZH
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:58: error: ‘VL’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:58: note: suggested alternative: ‘YL’
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
YL
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:62: error: ‘WH’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:62: note: suggested alternative: ‘ZH’
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
ZH
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:66: error: ‘WL’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:66: note: suggested alternative: ‘YL’
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~
YL
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:70: error: ‘nCS’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:10:75: error: ‘DRV_EN’ was not declared in this scope
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);
^~~~~~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino: In function ‘void setup()’:
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:18:13: error: ‘UL’ was not declared in this scope
pinMode(UL, OUTPUT);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:18:13: note: suggested alternative: ‘YL’
pinMode(UL, OUTPUT);
^~
YL
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:19:13: error: ‘VL’ was not declared in this scope
pinMode(VL, OUTPUT);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:19:13: note: suggested alternative: ‘YL’
pinMode(VL, OUTPUT);
^~
YL
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:20:13: error: ‘WL’ was not declared in this scope
pinMode(WL, OUTPUT);
^~
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:20:13: note: suggested alternative: ‘YL’
pinMode(WL, OUTPUT);
^~
YL
In file included from C:\Users\Endrit\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Arduino.h:258:0,
from C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:1:
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:46:43: error: ‘FAULT’ was not declared in this scope
attachInterrupt(digitalPinToInterrupt(FAULT), handleFault, RISING);
^
C:\Users\Endrit\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\standard/pins_arduino.h:79:37: note: in definition of macro ‘digitalPinToInterrupt’
#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT))
^
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:46:43: note: suggested alternative: ‘DEFAULT’
attachInterrupt(digitalPinToInterrupt(FAULT), handleFault, RISING);
^
C:\Users\Endrit\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\standard/pins_arduino.h:79:37: note: in definition of macro ‘digitalPinToInterrupt’
#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT))
^
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino: In function ‘void handleFault()’:
C:\Users\Endrit\Documents\Arduino\sketch_jan25a\sketch_jan25a.ino:63:18: error: ‘DRV_EN’ was not declared in this scope
digitalWrite(DRV_EN, LOW);
^~~~~~

exit status 1

Compilation error: ‘UH’ was not declared in this scope

these are errors.

And here is my code

#include "Arduino.h"
#include <SimpleFOC.h>
#include "SimpleFOCDrivers.h"
#include "drivers/tmc6200/TMC6200.hpp"

// Motor instance
BLDCMotor motor = BLDCMotor(15);

// TMC6200 driver instance
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);

void setup() {
    // Initialize motor
    motor.linkDriver(&driver);
    motor.controller = MotionControlType::velocity_openloop;

    // Set up pins for 6-PWM control
    pinMode(UL, OUTPUT);
    pinMode(VL, OUTPUT);
    pinMode(WL, OUTPUT);
    digitalWrite(WL, HIGH);
    digitalWrite(UL, HIGH);
    digitalWrite(VL, HIGH);

    // Initialize SimpleFOC
    motor.init();

    // Set velocity setpoint
    motor.target = 2.0; // RPM

    // Align sensor and start FOC
    motor.initFOC();

    // Set driver options
    driver.setCurrentSenseGain(TMC6200_AmplificationGain::_5);
    driver.setCurrentSenseAmplifierState(true); // Ensure current sensing is on
    driver.setDriverStrength(TMC6200_DRVStrength::Strong);

    // Validate SPI connection
    if(driver.getInputs().VERSION != TMC6200_VERSION) {
        // Something is wrong with the SPI connection
        Serial.println("SPI connection issue");
    }

    // Attach fault interrupt
    attachInterrupt(digitalPinToInterrupt(FAULT), handleFault, RISING);
}

void loop() {
    // Execute control loop
    motor.loopFOC();
}

void handleFault() {
    // Handle faults here
    TMC6200GStatus status = driver.getStatus();
    // Print fault status
    Serial.println("Fault detected:");
    Serial.print("U shorted: "); Serial.println(status.hasUShorted());
    Serial.print("V shorted: "); Serial.println(status.hasVShorted());
    Serial.print("W shorted: "); Serial.println(status.hasWShorted());
    // Clear fault by cycling DRV_EN
    digitalWrite(DRV_EN, LOW);
    delayMicroseconds(100);
    digitalWrite(DRV_EN, HIGH);
}

Well, you do have to define all these constants like UH, VH, DRV_EN etc… to match the pin numbers you are using on your setup…


thanks for your time

in which mode should the tmc6200 be in spi or standalone.

UH
VH
WH
UL
VL
WL
should they all be pwm?
How should I connect them?
in VM and GND I have power from an external psu.

While in U V W in TMC6200BOB there are bldc phases, I have set them.

but i am not getting result

the code now is compile.

#include "Arduino.h"
#include <SimpleFOC.h>
#include "SimpleFOCDrivers.h"
#include "drivers/tmc6200/TMC6200.hpp"

// Pin Definitions
#define UH 2
#define UL 3
#define VH 4
#define VL 5
#define WH 6
#define WL 7
#define nCS 8
#define DRV_EN 9
#define FAULT 10

// Motor instance
BLDCMotor motor = BLDCMotor(15);

// TMC6200 driver instance
TMC6200Driver6PWM driver = TMC6200Driver6PWM(UH, UL, VH, VL, WH, WL, nCS, DRV_EN);

void setup() {
    // Initialize serial communication
    Serial.begin(115200);
    
    // Initialize motor
    motor.linkDriver(&driver);
    motor.controller = MotionControlType::velocity_openloop;

    // Set up pins for 6-PWM control
    pinMode(UL, OUTPUT);
    pinMode(VL, OUTPUT);
    pinMode(WL, OUTPUT);
    digitalWrite(WL, HIGH);
    digitalWrite(UL, HIGH);
    digitalWrite(VL, HIGH);

    // Initialize SimpleFOC
    motor.init();

    // Set velocity setpoint
    motor.target = 2.0; // RPM

    // Align sensor and start FOC
    motor.initFOC();

    // Set driver options
    driver.setCurrentSenseGain(TMC6200_AmplificationGain::_5);
    driver.setCurrentSenseAmplifierState(true); // Ensure current sensing is on
    driver.setDriverStrength(TMC6200_DRVStrength::Strong);

    // Validate SPI connection
    if(driver.getInputs().VERSION != TMC6200_VERSION) {
        // Something is wrong with the SPI connection
        Serial.println("SPI connection issue");
    }

    // Attach fault interrupt
    attachInterrupt(digitalPinToInterrupt(FAULT), handleFault, RISING);
}

void loop() {
    // Execute control loop
    motor.loopFOC();
}

void handleFault() {
    // Handle faults here
    TMC6200GStatus status = driver.getStatus();
    // Print fault status
    Serial.println("Fault detected:");
    Serial.print("U shorted: "); Serial.println(status.hasUShorted());
    Serial.print("V shorted: "); Serial.println(status.hasVShorted());
    Serial.print("W shorted: "); Serial.println(status.hasWShorted());
    // Clear fault by cycling DRV_EN
    digitalWrite(DRV_EN, LOW);
    delayMicroseconds(100);
    digitalWrite(DRV_EN, HIGH);
}

Hello,
Anyone any idea what could be the problem?

Hey @Endrit ,

Well for sure one problem is you’re only calling motor.loopFOC() and not motor.move() in the main loop. You need both.

I’d encourage you to read over our documentation at docs.simplefoc.com… the “Writing the Code” section explains it all in detail, and has many examples.

In addition, your question regarding 3PWM vs. 6PWM, this depends on your hardware, and how it is set up. On some setups you may be able to use either one, and choose. But on other setups, you might have only 3-PWM or only 6-PWM. Please check the documentation for your hardware.

Which MCU are you using? Depending on the MCU type, you need to use different pins. I can’t say if the pins you are using are correct or not at the moment.

Hello, thank you for your response and your time.

I understand that I have replied multiple times, but I lack proficiency in programming, and I urgently need this project to function.

I am using an Arduino Uno, but it still isn’t working.

According to the TMC6200 datasheet, it states that in dual-line mode, LS (Low-Side) and HS (High-Side) are used, or in single-line mode, only HS (High-Side) is enabled with LS polarity.

I am unsure where the problem lies.

Currently, in the breakout board (BOB), I have it set to SPI mode with R203.

Hello, any thoughts about my reply?

So it seems you can choose between 3-PWM and 6-PWM, using the same set of pins. You have to set the correct PWM input mode via SPI, which the driver does for you depending on whether you choose the TMC6200Driver6PWM or the TMC6200Driver3PWM.

The UNO can only use certain pins for PWM, that is 3,5,6,9,10,11 - it can’t use other pins for PWM. So you can’t use pin 2, pin 4 or pin 7 for PWM. And for 6-PWM the pins have to be used pair-wise like this: 3/11, 5/6 and 9/10.

Hello, thanks for your reply here is my code and config. UL VL WL i pulled up and UH VH WH from arduino to TMC and SPI pins from Arduino to TMC6200 BOB. But still doesnt work

#include "Arduino.h"
#include <SimpleFOC.h>
#include "SimpleFOCDrivers.h"
#include "drivers/tmc6200/TMC6200.hpp"

// Pin Definitions
#define UH 3
#define VH 5
#define WH 6
#define nCS 10
#define DRV_EN 9
#define FAULT 2

// Motor instance
BLDCMotor motor = BLDCMotor(15);

// TMC6200 driver instance for 3-PWM operation
TMC6200Driver3PWM driver = TMC6200Driver3PWM(UH, VH, WH, nCS, DRV_EN);

void setup() {
    // Initialize serial communication
    Serial.begin(115200);
    
    // Initialize motor
    motor.linkDriver(&driver);
    motor.controller = MotionControlType::velocity_openloop;

    // Set up pins for 3-PWM control
    pinMode(UH, OUTPUT);
    pinMode(VH, OUTPUT);
    pinMode(WH, OUTPUT);

    // Initialize SimpleFOC
    motor.init();

    // Set velocity setpoint
    motor.target = 20.0; // RPM

    // Align sensor and start FOC
    motor.initFOC();

    // Set driver options
    driver.setCurrentSenseGain(TMC6200_AmplificationGain::_5);
    driver.setCurrentSenseAmplifierState(true); // Ensure current sensing is on
    driver.setDriverStrength(TMC6200_DRVStrength::Strong);

    // Validate SPI connection
    if(driver.getInputs().VERSION != TMC6200_VERSION) {
        // Something is wrong with the SPI connection
        Serial.println("SPI connection issue");
    }

    // Attach fault interrupt
    attachInterrupt(digitalPinToInterrupt(FAULT), handleFault, RISING);
}

void loop() {
    // Execute control loop
    motor.loopFOC();

    motor.move();
}

void handleFault() {
    // Handle faults here
    TMC6200GStatus status = driver.getStatus();
    // Print fault status
    Serial.println("Fault detected:");
    Serial.print("U shorted: "); Serial.println(status.hasUShorted());
    Serial.print("V shorted: "); Serial.println(status.hasVShorted());
    Serial.print("W shorted: "); Serial.println(status.hasWShorted());
    // Clear fault by cycling DRV_EN
    digitalWrite(DRV_EN, LOW);
    delayMicroseconds(100);
    digitalWrite(DRV_EN, HIGH);
}

SPI connection issue

serial print report

That’s not quite enough… you also need to set these pins to high:

    pinMode(UL, OUTPUT);
    pinMode(VL, OUTPUT);
    pinMode(WL, OUTPUT);
    digitalWrite(UL, HIGH);
    digitalWrite(VL, HIGH);
    digitalWrite(WL, HIGH);

Regarding the SPI issue, I think you need to call SPI.begin(), and you are also not calling driver.init()… please take a look at some of our example code.

void setup() {
    // Initialize serial communication
    Serial.begin(115200);
    SimpleFOCDebug::enable(Serial);

    // Initialize driver
    driver.voltage_power_supply = 12.0f; // 12V power supply
    driver.voltage_limit = 10.0f;  // 10V limit
    SPI.begin();
    driver.init();

    // Set driver options
    driver.setCurrentSenseGain(TMC6200_AmplificationGain::_5);
    driver.setCurrentSenseAmplifierState(true); // Ensure current sensing is on
    driver.setDriverStrength(TMC6200_DRVStrength::Strong);

    // Validate SPI connection
    if(driver.getInputs().VERSION != TMC6200_VERSION) {
        // Something is wrong with the SPI connection
        Serial.println("SPI connection issue");
    }

    // Initialize motor
    motor.linkDriver(&driver);
    motor.controller = MotionControlType::velocity_openloop;
    motor.voltage_limit = driver.voltage_limit / 2.0f;  // motor limit set to driver limit / 2
    motor.init();

    // enable the phases
    pinMode(UL, OUTPUT);
    pinMode(VL, OUTPUT);
    pinMode(WL, OUTPUT);
    digitalWrite(UL, HIGH);
    digitalWrite(VL, HIGH);
    digitalWrite(WL, HIGH);

    // Align sensor and start FOC
    // motor.initFOC();   // call initFOC() only in closed loop mode, it needs a sensor

    // Set velocity setpoint
    motor.target = 2.0f; // radians per second
}

void loop() {
   motor.move();
   motor.loopFOC();
}

See how it goes with the init method as shown above… that looks more correct to me.