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);
tmc9660::BootloaderConfig cfg{};
cfg.uart.baud_rate = tmc9660::bootcfg::BaudRate::BR115200;
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;
}
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 ➡️ |