Open jangrewe opened 5 years ago
ESP32 is not listed as a SW Serial capable platform, mostly due to lack of testing, so there's not constructor to match that.
Try this branch where I added ESP32. Not sure how it works though. https://github.com/teemuatlut/TMCStepper/tree/esp32 (EDIT: Changes merged into master)
Hello, I have tested this code for TMC2208 with ESP32.
#include <TMCStepper.h>
#define SW_RX 16 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX 17 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define EN_PIN 32 // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN 12 // Step on rising edge
#define SERIAL_PORT Serial2 // TMC2208/TMC2224 HardwareSerial port
#define R_SENSE 0.11 // SilentStepStick series use 0.11 Watterott TMC5160 uses 0.075
TMC2208Stepper driver = TMC2208Stepper(&SERIAL_PORT, R_SENSE); // Hardware Serial0
//***********************************************************************
void setup() {
Serial.begin(115200);
Serial2.begin(115200); // SW UART drivers
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver in hardware
driver.begin(); // SPI: Init CS pins and possible SW SPI pins
driver.rms_current(800); // Set motor RMS current
read_ms();
driver.microsteps(16);
read_ms();
driver.toff(5); // Enables driver in software
// driver.en_pwm_mode(true); // Enable stealthChop
driver.pwm_autoscale(true); // Needed for stealthChop
}
//***********************************************************************
void read_ms() {
uint16_t msread=driver.microsteps();
Serial.print(" read:ms="); Serial.println(msread);
}
//***********************************************************************
void turn() {
for(int i=0;i<=6400 ;i++) {
digitalWrite(STEP_PIN, !digitalRead(STEP_PIN));
delayMicroseconds(200); }
}
//***********************************************************************
void loop() {
delay(1000);
driver.shaft(0);
driver.microsteps(2);
read_ms();
turn();
delay(1000);
driver.shaft(1);
driver.microsteps(32);
read_ms();
turn();
}
//***********************************************************************
Connection works with hardware serial2 but microstep function doesn't works :
Did I made a mistake about microstep setting in this code ? Thanks.
It seems I need to update the examples to add a few things for TMC2208.
Try adding this to setup:
driver.pdn_disable(true); // Use PDN/UART pin for communication
driver.I_scale_analog(false); // Use internal voltage reference
You can also checkout the examples from the older TMC2208Stepper library https://github.com/teemuatlut/TMC2208Stepper/tree/master/examples
I add these lines to setup and there is no change. So I test this new code and I had a look to the connection with a oscilloscope . Here is the code:
#include <TMCStepper.h>
#define SW_RX 16 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX 17 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define EN_PIN 32 // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN 12 // Step on rising edge
#define SERIAL_PORT Serial2 // TMC2208/TMC2224 HardwareSerial port
#define R_SENSE 0.11 // SilentStepStick series use 0.11 Watterott TMC5160 uses 0.075
TMC2208Stepper driver = TMC2208Stepper(&SERIAL_PORT, R_SENSE); // Hardware Serial0
//***********************************************************************
void setup() {
Serial.begin(115200);
Serial2.begin(115200); // SW UART drivers
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver in hardware
driver.begin(); // SPI: Init CS pins and possible SW SPI pins
driver.pdn_disable(true); // Use PDN/UART pin for communication
driver.I_scale_analog(false); // Use internal voltage reference
driver.rms_current(800); // Set motor RMS current
driver.microsteps(16);
driver.toff(5); // Enables driver in software
// driver.en_pwm_mode(true); // Enable stealthChop
driver.pwm_autoscale(true); // Needed for stealthChop
}
//***********************************************************************
void loop() {
driver.microsteps(32);
uint16_t msread=driver.microsteps();
Serial.print(" read:ms=");
Serial.println(msread);
delay(5000);
}
//***********************************************************************
Here is the screen capture of the signal with decoding :
Hope this can help ? Thanks for your help .
I finally found the solution . It was necessary to call the mstep_reg_select function with parameter=1 to set GCONF register of TMC2208 as indicated in TMC220x_TMC222x_datasheet_Rev1.07.pdf (chapter 5.1: General Registers , page 24) Here is a code with works for esp32.
#include <TMCStepper.h>
#define SW_RX 16 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX 17 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define EN_PIN 32 // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN 12 // Step on rising edge
#define SERIAL_PORT Serial2 // TMC2208/TMC2224 HardwareSerial port
#define R_SENSE 0.11 // SilentStepStick series use 0.11 Watterott TMC5160 uses 0.075
TMC2208Stepper driver = TMC2208Stepper(&SERIAL_PORT, R_SENSE); // Hardware Serial0
//***********************************************************************
void setup() {
Serial.begin(115200);
Serial2.begin(115200); // SW UART drivers
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver in hardware
driver.begin(); // SPI: Init CS pins and possible SW SPI pins
driver.pdn_disable(true); // Use PDN/UART pin for communication
driver.I_scale_analog(false); // Use internal voltage reference
driver.rms_current(800); // Set motor RMS current
driver.mstep_reg_select(1); // necessary for TMC2208 to set microstep register with UART
driver.microsteps(16);
driver.toff(5); // Enables driver in software
// driver.en_pwm_mode(true); // Enable stealthChop
driver.pwm_autoscale(true); // Needed for stealthChop
}
//***********************************************************************
void read_ms() {
Serial.print(" read:ms="); Serial.println(driver.microsteps());
}
//***********************************************************************
void turn() {
for(int i=0;i<=6400 ;i++) {
digitalWrite(STEP_PIN, !digitalRead(STEP_PIN));
delayMicroseconds(400); }
}
//***********************************************************************
void loop() {
delay(1000); driver.shaft(0); driver.microsteps( 2); read_ms(); turn();
delay(1000); driver.shaft(1); driver.microsteps( 4); read_ms(); turn();
delay(1000); driver.shaft(0); driver.microsteps( 8); read_ms(); turn();
delay(1000); driver.shaft(1); driver.microsteps(16); read_ms(); turn();
delay(1000); driver.shaft(0); driver.microsteps(32); read_ms(); turn();
delay(1000); driver.shaft(1); driver.microsteps(64); read_ms(); turn();
}
//***********************************************************************
Good catch. I should've taken a look at the init section in Marlin that would've pointed this out. Have you tried SW UART? I'd like to add STM32 as a SW Serial capable platform in the next release.
I have tried to compile this code with software serial :
TMC2208Stepper driver = TMC2208Stepper(SW_RX, SW_TX, R_SENSE); // Software serial
//
void setup() {
Serial.begin(115200);
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver in hardware
driver.begin(); // SPI: Init CS pins and possible SW SPI pins
driver.pdn_disable(true); // Use PDN/UART pin for communication
driver.I_scale_analog(false); // Use internal voltage reference
driver.rms_current(600); // Set motor RMS current
driver.mstep_reg_select(1);
driver.microsteps(16);
driver.toff(5); // Enables driver in software
driver.pwm_autoscale(true); // Needed for stealthChop
}
//
void loop() {}
But compilation is not ok . Here is the error message from Arduino IDE : TMC2208_esp32_test04_swser:8:61: error: invalid conversion from 'int' to 'Stream*' [-fpermissive] TMC2208Stepper driver = TMC2208Stepper(SW_RX, SW_TX, R_SENSE); // Software serial
Must I open a software serial object in my code ?
@teemuatlut Do you have plans (roadmap) to implement support to the MKR platform? What's the difference between this library and the TMC2208Stepper?
Thanks!
@roberto1963 Try the esp32 branch of the library. The SW Serial constructor is limited to approved platforms that have the required library implemented.
@thalesfsp I've never had any of the MKR boards but fundamentally the library could/should be compatible as long as there are the requires prerequisites, like an SPI library. This library supercedes the older TMC2208 and TMC2130. The change was made to accommodate the increasing number of TMC drivers as I didn't want to have separate libraries for each that I'd have to maintain. Much of the interface remains the same, except the yet-not-implemented helper methods, but the underlying architecture and structure is completely rewritten.
I tried this code with the esp32 branch. The compilation is ok, but it does not work . The stepper makes just a turn. Then it doesn't turn any more . The esp32 chip continues to work, so the TMC2208 chip was probably blocked by communication?
#include <TMCStepper.h>
#define SW_RX 16 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX 17 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define EN_PIN 32 // LOW: Driver enabled. HIGH: Driver disabled
#define STEP_PIN 12 // Step on rising edge
#define R_SENSE 0.11 // SilentStepStick series use 0.11 Watterott TMC5160 uses 0.075
TMC2208Stepper driver = TMC2208Stepper(SW_RX, SW_TX, R_SENSE); // Software serial
//***********************************************************************
void setup() {
Serial.begin(115200);
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver in hardware
driver.begin(); // SPI: Init CS pins and possible SW SPI pins
driver.pdn_disable(true); // Use PDN/UART pin for communication
driver.I_scale_analog(false); // Use internal voltage reference
driver.rms_current(600); // Set motor RMS current
driver.mstep_reg_select(1);
driver.microsteps(16);
driver.toff(5); // Enables driver in software
driver.pwm_autoscale(true); // Needed for stealthChop
}
//***********************************************************************
void read_ms() {Serial.print(" read:ms="); Serial.println(driver.microsteps());}
//***********************************************************************
void turn() {
for(int i=0;i<=6400 ;i++) {
digitalWrite(STEP_PIN, !digitalRead(STEP_PIN));
delayMicroseconds(400); }
}
//***********************************************************************
void loop() {
delay(1000); driver.shaft(0); driver.microsteps( 2); read_ms(); turn();
delay(1000); driver.shaft(1); driver.microsteps( 4); read_ms(); turn();
delay(1000); driver.shaft(0); driver.microsteps( 8); read_ms(); turn();
delay(1000); driver.shaft(1); driver.microsteps(16); read_ms(); turn();
delay(1000); driver.shaft(0); driver.microsteps(32); read_ms(); turn();
}
//***********************************************************************
I have trouble with SoftwareSerial.h and ESP32 as well. I don't think that is included in the Arduino core for ESP32. I was able to get rid of the error by commenting out the ESP32 on this line in TMCStepper.h
#define SW_CAPABLE_PLATFORM defined(__AVR__) || defined(TARGET_LPC1768) // || defined(ARDUINO_ARCH_ESP32)
The ESP32 has 3 UARTS and 3 SPIs. I don't think soft version of these are needed in most applications.
@teemuatlut Happy to create a separate issue, but figured I'd try here first :)
Having looked over the code at current master, it looks like the ESP32 would still end up using the SW_SPI.cpp
stuff; is that correct? If so, any interest in making that somewhat configurable? I might just jank it out locally and replace with one of the ESP32's hardware SPIs (which can then be mapped to most GPIO pins in hardware by specifying in the constructor). It'l be a little ugly, so it'd be great to know if I can potentially replace my kludge with a one-liner in the future :)
If the code calls for the SW SPI constructor then the library sure will use the internal bit banging implementation. I'm not familiar with the ESP32 codebase but if you want you can make a pull request as a proof of concept and I can then refine it from there. A PoC does not need to be pretty =) I don't expect there to be a one-liner solution.
ESP32 is not listed as a SW Serial capable platform, mostly due to lack of testing, so there's not constructor to match that.
Try this branch where I added ESP32. Not sure how it works though. https://github.com/teemuatlut/TMCStepper/tree/esp32 (EDIT: Changes merged into master)
I don't see in 0.7.1 master, is it still there?
@johnsmakar See #59
I have more than one sketch written before this thread started that uses SW serial. Maybe it's not relevant to this library, but the ESP32 can use it. If it's relevant, I'll have to dig back into the files to see what I changed to make it work. Andreas Spiess clued me into the process in one of his early ESP32 videos.
Hello, I am coming here from this electronics.stackexchange post because I would like to drive a stepper motor with TMC2209 and ESP32.
I read though this thread and also looked at #59, but my understanding of the topic is not deep enough. Is there some possibility to use TMCStepper library on ESP32 or not ? Would be glad for an simple explanation, thanks.
I believe the HW serial at least should work. I haven't done much (at all) testing with the ESP platform and the TMC drivers. But as long as the MCU sends out the correct UART signals, it should work. If you want a more tested setup, go with the 5160 as that has been proven by https://github.com/bdring/Grbl_Esp32
Thanks for the answer. I actually found some more examples regarding ESP32 in other issues, event this repo 👍 I am unsure though, how is the wiring done with the HW serial - do I still connect the drivers Tx/Rx to the Tx/Rx pins on the ESP32 ?
Sorry for asking such noob questions - I am just a guy trying to get some silent motor drive for a swing oh his newborn baby girl :-) and so far I wasn't even able to get the motor running even using the simplest wiring.
Watterott has gathered quite a lot of information about the TMC drivers they sell, including how to wire the serial based drivers. https://learn.watterott.com/silentstepstick/configurator/ Be sure to read their FAQ as well. In short, you connect the ESP RX to the driver UART pin and then the TX pin with a 1kOhm resistor.
When you think you've got the wiring done, the first thing you should test is if the communication works. 90% of the problems I see are issues with the communication. While I won't claim there can be no bugs in the code and I hope that people will report them if they find any, I try to keep in mind that the library is used by quite a few users in their 3D printers.
You can read back the driver firmware version with Serial.println(driver.version());
And congrats on a new family member =)
@teemuatlut Many thanks, dealing with the pinout of TMC2209 brought me to my problem - I the wiring for the EN pin was wrong. I used the ESP32 example from this repository, connected the Tx and Rx to Pins 16 and 0 and initialized the hardware serial connection as:
#define RX2 16
#define TX2 0
...
SERIAL_PORT.begin(115200, SERIAL_8N1, RX2, TX2);
The motor spins now 😄 , I wonder if it is due to the working Hardware Serial connection or if the motor would spin even if the serial connection would not work
The 2208/9 have defaults in OTP memory and the driver is functional even without working comms. This all makes it a bit more confusing when the motor happily spins but you cannot change the configuration at all.
Do any of you finally get it to work?
I ended up finding ... for get example go to https://forum.arduino.cc/t/using-a-tmc2209-silent-stepper-motor-driver-with-an-arduino/666992/10
You copy and past laste code
#include <HardwareSerial.h>
#include <TMCStepper.h>
#define RX2 16
#define TX2 0
#define DIAG_PIN 15 // STALL motor 2
#define EN_PIN 14 // Enable
#define DIR_PIN 4 // Direction
#define STEP_PIN 2 // Step
#define SERIAL_PORT Serial2 // TMC2208/TMC2224 HardwareSerial port
#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE 0.11f // E_SENSE for current calc.
#define STALL_VALUE 2 // [0..255]
hw_timer_t * timer1 = NULL;
TMC2209Stepper driver(&SERIAL_PORT, R_SENSE , DRIVER_ADDRESS );
void IRAM_ATTR onTimer() {
digitalWrite(STEP_PIN, !digitalRead(STEP_PIN));
}
void setup() {
Serial.begin(250000); // Init serial port and set baudrate
while(!Serial); // Wait for serial port to connect
Serial.println("\nStart...");
SERIAL_PORT.begin(115200, SERIAL_8N1, RX2, TX2);
pinMode(DIAG_PIN ,INPUT);
pinMode(EN_PIN ,OUTPUT);
pinMode(STEP_PIN ,OUTPUT);
pinMode(DIR_PIN ,OUTPUT);
digitalWrite(EN_PIN ,LOW);
digitalWrite(DIR_PIN ,LOW);
driver.begin();
driver.toff(4);
driver.blank_time(24);
driver.rms_current(500);
driver.microsteps(16);
driver.TCOOLTHRS(0xFFFFF); // 20bit max
driver.semin(0);
driver.semax(2);
driver.shaft(false);
driver.sedn(0b01);
driver.SGTHRS(STALL_VALUE);
activate_interrupt();
}
void loop() {
static uint32_t last_time=0;
uint32_t ms = millis();
if((ms-last_time) > 100) { //run every 0.1s
last_time = ms;
Serial.print("0 ");
Serial.print(driver.SG_RESULT(), DEC);
Serial.print(" ");
Serial.println(driver.cs2rms(driver.cs_actual()), DEC);
}
}
void activate_interrupt(){
{
cli();//stop interrupts
timer1 = timerBegin(3, 8,true); // Initialize timer 4. Se configura el timer, ESP(0,1,2,3)
// prescaler of 8, y true es una bandera que indica si la interrupcion se realiza en borde o en nivel
timerAttachInterrupt(timer1, &onTimer, true); //link interrupt with function onTimer
timerAlarmWrite(timer1, 8000, true); //En esta funcion se define el valor del contador en el cual se genera la interrupción del timer
timerAlarmEnable(timer1); //Enable timer
sei();//allow interrupts
}
}
After copy if you not find data by your driver change addr
#define DRIVER_ADDRESS 0b00
for
#define DRIVER_ADDRESS 0b01
or 0b10 or 0b11
here are the pins that I use on my ESP
and I have a resistance between TX and RX of 1kohm, and my cable from the TX pin to the PDN pin
See this comment for ESP32 and the UART based drivers https://github.com/teemuatlut/TMCStepper/issues/192#issuecomment-831432951
See this comment for ESP32 and the UART based drivers #192 (comment)
teemuatlut, I've read this topic and others a few times, looked at the datasheet, tried dozens of codes
I can't understand what's wrong with my test, nothing I do works for esp32 and tmc2208 (fysetec) communication via UART. I tested the UART communication of my driver through the computer, it worked perfectly, I can open it via ScriptCommunicator, as described here: https://wiki.fysetc.com/TMC2208/#setting-method
the last code I tested was this
#include <TMCStepper.h>
#define EN_PIN 32
#define STEP_PIN 12
#define SERIAL_PORT Serial1
#define R_SENSE 0.11
TMC2208Stepper driver = TMC2208Stepper(&SERIAL_PORT, R_SENSE);
void setup()
{
Serial.begin(115200);
Serial1.begin(115200);
pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);
driver.begin();
driver.pdn_disable(true);
driver.I_scale_analog(false);
driver.rms_current(800);
driver.mstep_reg_select(1);
driver.microsteps(16);
driver.toff(5);
driver.pwm_autoscale(true);
}
void loop()
{
delay(10000);
uint8_t result = driver.test_connection();
Serial.println(result);
}
The result is always 2
Same here @vitalibr
I had exactly the same problems as @vitalibr with a TMC2208 and ESP8266.
I found the problem using a scope:
I don't know if its the library, or something on the board (D1 Mini).
Solution: Use a lower value resistor between RX and TX, to pull LOW sufficiently low. 500 Ohms wasnt enough for me, but 330 Ohms seems to work fine.
Hi, i wrote a sketch using your library on an Arduino Nano while waiting for an ESP32 to arrive, but when i tried to upload that sketch to the ESP32, VSCode threw an error that your library only supports the
avr
arch, which is a shame because of all the connectivity that the ESP32 provides.Is there any chance you will make it also compatible with the ESP32 architecture?
Thanks!