TMCStepper
TMCStepper copied to clipboard
Using TMCStepper in firmware with custom pins
Hi,
I'm attempting to use TMCStepper in the GRBL_ESP32 firmware with custom pins. Custom pins could be I2SO, I2C, etc... In the past, we would change the behavior of digitalRead, setMode and digitalWrite to change the behavior, and handle the lookup through a table. However, this is quite inefficient and quite nasty, so I was looking for some other way to do this.
First off, putting my pin info in a global variable is not a good solution. It's likely that multiple steppers are installed in a board, and they could even be different stepper types.
What I tried instead is to implement my own version of TMC2130Stepper::switchCSpin and have that write to the CS pin. While that has access to the members of the class (such as the CS pin), there does not seem to be a way to add a custom or user defined field. So, in an attempt to solve this, I created a few derived classes (for each stepper type) class MyTMC2130Stepper : TMC2130Stepper that adds the field. If switchCSpin was virtual, that would have been the end of it - but unfortunately it's only weakly linked, so the issue now is that there's no way for me to figure out which derived class I'm dealing with (and no way to store it). Note that dynamic_cast requires RTTI, which is disabled, so I cannot even use multiple inheritance to solve this issue.
At this point, I can get it done by hacking the required info into the CS pin (u16) value, which is the workaround I'm planning... However, to make it a pretty solution one of these is needed:
- Add a single 'user defined field' with state information to the TMC2130Stepper class. Basically this is just a
void* customprotected field, with some way of setting it. That's it. - Make the switchCSpin
virtual, so we can override it.
Is one of these possible?
I'd like to avoid using runtime polymorphism in the library if at all possible. The v1 branch adds more flexibility in how the the driver classes are structured. Perhaps it would be possible to use CRTP to create an interface class for pins that would allow for the user added functionality you're looking for. This is a bit of a niche request but definitely interesting. I'll first need to focus on getting the v1 release out but I'll see what kind of a solution I can come up with after that.
#include <TMCStepper.h> // Master branch
struct MyTMC2130 : public TMC2130Stepper {
using TMC2130Stepper::TMC2130Stepper;
void Custom_CS_Pin_Handler(const bool state) {
cs_pin_state = state;
}
bool cs_pin_state = false;
};
MyTMC2130 driver(42, 0.11);
void setup() {
Serial.begin(9600);
SPI.begin();
driver.begin();
Serial.print("Driver firmware version = ");
Serial.println(driver.version());
}
void loop() {}
void TMC2130Stepper::switchCSpin(bool state) {
static_cast<MyTMC2130*>(this)->Custom_CS_Pin_Handler(state);
}
I only tried compiling for ESP32 Dev Module so no guarantees about functionality.