HF-TMC9660 Driver
Hardware Agnostic C++ Driver for the TMC9660
Loading...
Searching...
No Matches
Extensive TMC9660 Examples

This document collects hardware agnostic walkthroughs showing how to configure the TMC9660 from bootloader setup to running a variety of motors. All code examples use a very small "DummyBus" that merely echoes SPI transfers. When porting the library to real hardware you must implement your own class derived from TMC9660CommInterface and replace the dummy bus with that implementation.


Bootloader Configuration

The bootloader registers are configured via TMC9660Bootloader. The snippet below writes a minimal configuration enabling SPI and UART communication. The DummyBus seen in all snippets simply echoes data and serves as a placeholder for your real SPI or UART implementation.

#include "TMC9660.hpp"
#include <iostream>
class DummyBus : public SPITMC9660CommInterface {
public:
bool spiTransfer(std::array<uint8_t,8>& tx,
std::array<uint8_t,8>& rx) noexcept override {
rx = tx; // echo back for demonstration
return true;
}
};
int main() {
DummyBus bus;
TMC9660 driver(bus);
cfg.spiComm.boot_spi_iface = tmc9660::bootcfg::SPIInterface::IFACE0;
cfg.clock.use_external = tmc9660::bootcfg::ClockSource::Internal;
auto result = driver.bootloaderInit(&cfg);
if (result == TMC9660::BootloaderInitResult::Success)
std::cout << "Bootloader configured" << std::endl;
else
std::cout << "Bootloader configuration failed" << std::endl;
}
SPI implementation of TMC9660CommInterface.
Definition TMC9660CommInterface.hpp:248
virtual bool spiTransfer(std::array< uint8_t, 8 > &tx, std::array< uint8_t, 8 > &rx) noexcept=0
Low-level SPI transfer of 8 bytes.
Definition tmc9660_adc.hpp:12
Aggregated bootloader configuration written by ::TMC9660Bootloader.
Definition TMC9660Bootloader.hpp:191
UARTConfig uart
Definition TMC9660Bootloader.hpp:194
bootcfg::BaudRate baud_rate
Definition TMC9660Bootloader.hpp:134

Compile with:

g++ -std=c++20 -Iinc src/TMC9660.cpp src/TMC9660Bootloader.cpp \
docs/bootloader_example.cpp -o bootloader_demo

BLDC with ABN Encoder

This example configures a BLDC motor using an incremental ABN encoder for closed loop FOC control. Again the DummyBus merely mimics the real transport layer.

#include "TMC9660.hpp"
#include <iostream>
class DummyBus : public SPITMC9660CommInterface {
public:
bool spiTransfer(std::array<uint8_t,8>& tx,
std::array<uint8_t,8>& rx) noexcept override {
rx = tx;
return true;
}
};
int main() {
DummyBus bus;
TMC9660 driver(bus);
driver.motor.setType(tmc9660::tmcl::MotorType::BLDC_MOTOR, 7);
driver.motor.configureABNEncoder(2048);
driver.motor.setCommutationMode(
tmc9660::tmcl::CommutationMode::FOC_ENCODER);
driver.motor.setMaxTorqueCurrent(2000);
driver.rampGenerator.setTargetVelocity(1500);
std::cout << "Motor running with ABN feedback" << std::endl;
}

Stepper Closed‑Loop Control

The library can control a stepper motor using field‑oriented control. The following snippet sets up a stepper with an ABN encoder and commands a position move. As before, DummyBus is just a stand‑in for a real bus driver.

#include "TMC9660.hpp"
#include <iostream>
class DummyBus : public SPITMC9660CommInterface {
public:
bool spiTransfer(std::array<uint8_t,8>& tx,
std::array<uint8_t,8>& rx) noexcept override {
rx = tx;
return true;
}
};
int main() {
DummyBus bus;
TMC9660 driver(bus);
driver.motor.setType(tmc9660::tmcl::MotorType::STEPPER_MOTOR);
driver.motor.configureABNEncoder(4000);
driver.motor.setCommutationMode(
tmc9660::tmcl::CommutationMode::FOC_ENCODER);
driver.position.moveTo(1000);
std::cout << "Stepper moving to position 1000" << std::endl;
}

Step/Dir Interface

External controllers can drive the STEP/DIR pins while the TMC9660 extrapolates between pulses. Here a stepper motor is configured for 1/8 micro‑steps and the interface is enabled. DummyBus once again represents the application‑specific communication layer.

#include "TMC9660.hpp"
#include <iostream>
class DummyBus : public SPITMC9660CommInterface {
public:
bool spiTransfer(std::array<uint8_t,8>& tx,
std::array<uint8_t,8>& rx) noexcept override {
rx = tx;
return true;
}
};
int main() {
DummyBus bus;
TMC9660 driver(bus);
driver.motor.setType(tmc9660::tmcl::MotorType::STEPPER_MOTOR);
driver.stepDir.setMicrostepResolution(
tmc9660::tmcl::StepDirStepDividerShift::DIV8);
driver.stepDir.enableInterface(true);
driver.stepDir.enableExtrapolation(true);
std::cout << "STEP/DIR interface enabled" << std::endl;
}

DC Motor Current Control

A brushed DC motor can be driven using open‑loop current mode. The following example sets a current limit and commands a constant current. Replace DummyBus with your hardware specific implementation when integrating.

#include "TMC9660.hpp"
#include <iostream>
class DummyBus : public SPITMC9660CommInterface {
public:
bool spiTransfer(std::array<uint8_t,8>& tx,
std::array<uint8_t,8>& rx) noexcept override {
rx = tx;
return true;
}
};
int main() {
DummyBus bus;
TMC9660 driver(bus);
driver.motor.setType(tmc9660::tmcl::MotorType::DC_MOTOR);
driver.motor.setCommutationMode(
tmc9660::tmcl::CommutationMode::FOC_OPENLOOP_CURRENT);
driver.motor.setMaxTorqueCurrent(1000);
driver.rampGenerator.setTargetCurrent(500);
std::cout << "DC motor running in current mode" << std::endl;
}

These snippets are minimal but cover the main features of the library. Refer to inc/TMC9660.hpp for all available parameters and helper methods.


⬅️ Prev | ⬆️ Back to Index | Next ➡️