Closed troth530 closed 1 year ago
If using a single pin for communication then a soft UART has to be implemented, at least for one direction? Or you have to remap the pin on the fly as TX or RX as required?
Hi @terjeio . PDN_UART pin is being used on BTT 2209's. Other stepper manufacturers like FYSETC may pull these pins out separately and provide the 1k resistor. It's probably built into the TMC UART libraries and the TMC drivers. I just don't see the way it should be implemented with your code yet.
The current TMC UART driver code supports the connection mode shown above and uses the secondary UART channel for communication. It is possible to use a single pin for RX/TX either by adding soft UART support or remapping a hardware UART pin between sending and receiving messages (if possible) - code has to be added for that. This code would then be an alternative to the current TMC UART driver code.
Hi @terjeio awesome, but it's still not clear how to implement. Do you have a specific set of settings in CMakeList.txt and _map.h which includes the necessary settings? Thank you!
Example... I'm sure I've missed many of the settings. "# define TRINAMIC_UART_ENABLE 1
In your map file:
#undef TRINAMIC_ENABLE
#undef TRINAMIC_UART_ENABLE
#define TRINAMIC_ENABLE 2209
#define TRINAMIC_UART_ENABLE 1
If your board is supporting more than one driver type then enabling TMC2209 should be added to CMakeLIsts.txt as an option instead.
Hi @terjeio I would like to use a common pin for all drivers (using MS1/MS2 to set the addresses). Is this possible and what is the syntax. Thank you!
What exactly do you mean by "a common pin" - one common pin for both TX and RX or separate pins for RX and TX as shown in the schematic above?
Both is possible but the first option (one common pin) will require additional code.
All drivers (up to 4) wired in parallel to the same pair of pins (single TX pin and a single RX pin), then each driver requires an address. Each address is set by the MS1/MS2 for that driver. For instance X driver is address 0, MS1/MS2 are left open. Y driver address is 1, MS1 is set high, MS2 is open. How are the addresses designated in your code? Thank you!
All drivers (up to 4) wired in parallel to the same pair of pins (single TX pin and a single RX pin),
Ok, I got confused by your wording - I was thinking you wanted to use a single pin for both TX and RX.
How are the addresses designated in your code?
All has to be addressed as driver 0 when using MS1/MS2- but the current ESP code does not support that. Easy to fix though, by adding a few lines of code - same as done in the STM32F4xx driver. Current code support up to four drivers, the drivers will be addressed in the transmitted messages.
This is the STM32F4xx code , bits from that has to be added to _trinamicif.c at line 221:
void driver_preinit (motor_map_t motor, trinamic_driver_config_t *config)
{
config->address = 0;
}
and at line 240:
driver.on_driver_preinit = driver_preinit;
I guess I should add this as a compile time option...
Hi @terjeio, unfortunately making only these changes in _map.h results in this compilation error. I have not yet confirmed the changes to trinamic_if.c.
Thank you!
[1293/1294] Linking CXX executable grbl.elf
FAILED: grbl.elf
cmd.exe /C "cd . && C:\Users\troth530.espressif\tools\xtensa-esp32-elf\esp-2021r1-8.4.0\xtensa-esp32-elf\bin\xtensa-esp32-elf-g++.exe -mlongcalls -Wno-frame-address @CMakeFiles\grbl.elf.rsp -o grbl.elf && cd ."
c:/users/troth530/.espressif/tools/xtensa-esp32-elf/esp-2021r1-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: esp-idf/main/libmain.a(driver.c.obj):(.literal.driver_init+0x8c): undefined reference to trinamic_init' c:/users/troth530/.espressif/tools/xtensa-esp32-elf/esp-2021r1-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: esp-idf/main/libmain.a(driver.c.obj): in function
driver_init':
c:\users\troth530\esp\esp-idf\esp32\build/../main/driver.c:2079: undefined reference to `trinamic_init'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
ninja failed with exit code 1
Have you modified CMakeLists.txt to enable TMC2209 support? I keep forgetting that this file has to be modified to add the relevant source code.
@terjeio 1) I'm still unsure of the syntax for defining the UART pins in the map file. 2) it seems most of the settings are in /motors/trinamic.h, but are there any changes needed in /trinamic/tmc2209.h ? I would like to use stallguard 4 which seems to be set in trinamic.h line 63. 3) I turned on the trinamic option in CMakeLists.txt, but now get these errors below.
Thank you!
snipped ...
.obj.d -o esp-idf/main/CMakeFiles/__idf_main.dir/driver.c.obj -c ../main/driver.c
In file included from ../main/./driver.h:153,
from ../main/driver.c:33:
../main/./motors/trinamic.h:70:14: error: unknown type name 'TMC_coolconf_t'
static const TMC_coolconf_t coolconf = { .semin = 5, .semax = 2, .sedn = 1 };
^~~~~~
../main/./motors/trinamic.h:70:42: error: field name not in record or union initializer
static const TMC_coolconf_t coolconf = { .semin = 5, .semax = 2, .sedn = 1 };
^
../main/./motors/trinamic.h:70:42: note: (near initialization for 'coolconf')
../main/./motors/trinamic.h:70:54: error: field name not in record or union initializer
static const TMC_coolconf_t coolconf = { .semin = 5, .semax = 2, .sedn = 1 };
^
../main/./motors/trinamic.h:70:54: note: (near initialization for 'coolconf')
../main/./motors/trinamic.h:70:63: warning: excess elements in scalar initializer
static const TMC_coolconf_t coolconf = { .semin = 5, .semax = 2, .sedn = 1 };
^
../main/./motors/trinamic.h:70:63: note: (near initialization for 'coolconf')
../main/./motors/trinamic.h:70:66: error: field name not in record or union initializer
static const TMC_coolconf_t coolconf = { .semin = 5, .semax = 2, .sedn = 1 };
^
../main/./motors/trinamic.h:70:66: note: (near initialization for 'coolconf')
../main/./motors/trinamic.h:70:74: warning: excess elements in scalar initializer
static const TMC_coolconf_t coolconf = { .semin = 5, .semax = 2, .sedn = 1 };
^
../main/./motors/trinamic.h:70:74: note: (near initialization for 'coolconf')
../main/./motors/trinamic.h:71:14: error: unknown type name 'TMC_chopper_timing_t'
static const TMC_chopper_timing_t chopper_timing = { .hstrt = 1, .hend = -1, .tbl = 1 };
^~~~~~~~
../main/./motors/trinamic.h:71:54: error: field name not in record or union initializer
static const TMC_chopper_timing_t chopper_timing = { .hstrt = 1, .hend = -1, .tbl = 1 };
^
../main/./motors/trinamic.h:71:54: note: (near initialization for 'chopper_timing')
../main/./motors/trinamic.h:71:66: error: field name not in record or union initializer
static const TMC_chopper_timing_t chopper_timing = { .hstrt = 1, .hend = -1, .tbl = 1 };
^
../main/./motors/trinamic.h:71:66: note: (near initialization for 'chopper_timing')
../main/./motors/trinamic.h:71:74: warning: excess elements in scalar initializer
static const TMC_chopper_timing_t chopper_timing = { .hstrt = 1, .hend = -1, .tbl = 1 };
^
../main/./motors/trinamic.h:71:74: note: (near initialization for 'chopper_timing')
../main/./motors/trinamic.h:71:78: error: field name not in record or union initializer
static const TMC_chopper_timing_t chopper_timing = { .hstrt = 1, .hend = -1, .tbl = 1 };
^
../main/./motors/trinamic.h:71:78: note: (near initialization for 'chopper_timing')
../main/./motors/trinamic.h:71:85: warning: excess elements in scalar initializer
static const TMC_chopper_timing_t chopper_timing = { .hstrt = 1, .hend = -1, .tbl = 1 };
^
../main/./motors/trinamic.h:71:85: note: (near initialization for 'chopper_timing')
../main/./motors/trinamic.h:207:5: error: unknown type name 'trinamic_mode_t'
trinamic_mode_t mode;
^~~~~~~
../main/./motors/trinamic.h:225:74: error: unknown type name 'tmchal_t'
typedef void (trinamic_on_driver_postinit_ptr)(motor_map_t motor, const tmchal_t driver);
I have just uploaded a new build that compiles for me (but I have not tested it).
Enable TMC2209 with hardware adressing mode here by setting both to ON
:
You have to add
#define HAS_BOARD_INIT
to your board map and change this line to add the needed code for compilation.
I'm still unsure of the syntax for defining the UART pins in the map file.
An example:
#define UART2_RX_PIN GPIO_NUM_33
#define UART2_TX_PIN GPIO_NUM_25
it seems most of the settings are in /motors/trinamic.h, but are there any changes needed in /trinamic/tmc2209.h ? I would like to use stallguard 4 which seems to be set in trinamic.h line 63.
Normally you do not have to change these files unless fine tuning parameters. Getting stallguard to work properly is not easy, I strongly recommend that you read up on that in the datasheet/manual.
Hi @terjeio, I will be testing soon. It seems that in CMakeLists.txt you called it TMC2209_HWADDR, but in trinamic_if.c you're using TRINAMIC_UART_HWADDR.
Now I am unsure of setting of each address. Is it to be assumed first motor is 0, second motor is 1, third motor is 2 and fourth motor is 3.
I have read the relevant sections of the trinamic datasheet and consequently expect a lot of tuning.
Thank you!.
in CMakeLists.txt you called it TMC2209_HWADDR, but in trinamic_if.c you're using TRINAMIC_UART_HWADDR
If you look further down in the file you can see that the options are used to set compiler symbols used in the code.
Is it to be assumed first motor is 0, second motor is 1, third motor is 2 and fourth motor is 3.
Yes.
Hi @terjeio, yes it compiles. However, when attempting to set $338 (and $339) it indicates no communication to the driver. With less sophisticated firmware, I've verified the drivers are communicating and can see the diag pin go high when a stall is detected so I believe the wiring is correct. For debug I used a single driver only on X, and cannot set $338=1 due to the communications error. Thank you!
Is there any output on the TX pin on startup? You may use M122I to resend the initialization messages anew when debugging.
I assume you have your own board map, I can try debugging if you add it to a comment (zipped please).
I have now run some tests - and it is the UART that is misbehaving (there is another crazy guru in there?). After tweaking the UART code sometimes the driver initialization works - randomly... There must be a way to make it work, but I give up for today.
Hi @terjeio,
the latest changes helped but it was intermittent at best
When Trinamic UART communications working
1) unable to compile with WebUI turned ON - just wanted to mention it although not related to this issue
2) Even with #define HAS_BOARD_INIT in my BOARD_MAP and ensuring trinamic_if.c had #if defined(my BOARD_MAP), UART communications would not initialize, but would initialize with an additional M122I command.
3) Was unable to verify Addressing is working, as it worked only on 1 axis when it did work
4) Sometimes it would communicate, sometimes not.
This is the UART2 trace at startup
This is the UART2 trace after issuing M122I
When Trinamic UART communications not working The data on UART2 when not working was high on startup, in fact it seems the code is pulling high whatever pins are assigned to #define UART2_RX_PIN
Trace on UART2 after issuing M122I command
Thank you!
M122I
- usually I could send 20+ M122I
s before failure. How often does a M122I
fail for you when issued in a row?This is the UART2 trace at startup
Is the driver motor power on at this point? The drivers are unresponsive if not.
Trace on UART2 after issuing M122I command
Odd, is both the driver and the MCU trying to transmit simultaneously? I've did not see such a trace when I debugged.
The response on reading from a driver is always 8 bytes, and with the code changes I made this never failed (many hundreds of M122I
commands sent). Can you add debug output to check the same on your end?
At line 194 add:
if(tmc_uart.get_rx_buffer_count() != 8)
hal.stream.write("Fail!" ASCII_EOL);
I suspect the random failures I had is due to the driver receiving a corrupted message and the check I have on startup for the transaction count is failing. Or a CRC check on the response fails... Both are in the TMC2209 code and is where I desperately want to set breakpoints and inspect values.
Is the driver motor power on at this point? The drivers are unresponsive if not.
I power up the MCU and drivers simultaneously. Bad things happen to the ESP devices if they get power from USB, then from a main board powering motors. So I'm forced to power up both simultaneously, but for debug I will try to power up the drivers first, then the MCU.
Odd, is both the driver and the MCU trying to transmit simultaneously? I've did not see such a trace when I debugged.
I don't know. But it is possible.
Currently I'm locked out of UART communications and cannot get back in. I always get the 3rd trace when issuing the M122I command and get this error when trying to set $338 [MSG:Warning: Could not communicate with stepper driver!]. So I'm locked out for now and double checking all my wiring.
TMC datasheet does say we have to keep the communications below 500k without a clock and I believe you limited it to about half that in trinamic_if.c.
I'll do more testing and report back. Thank you!
Hi @terjeio I found that the issues is likely related to addressing. Single axis works for X, with only sometimes communications error on M122I command. If the Y axis UART pin is connected it will give communications error 100% of the time and will not set do simple things like set microstepping regardless of $338 set to 1 or addressing off. When I disconnect the Y driver UART wire I can again communicate with UART on X axis. I verified that the Y driver UART works when installed in the X axis slot and it's the only driver installed. Also as far as wiring, I've made sure that X axis has MS1 and MS2 =Open or gnd Y axis has MS1=5v, MS2=Open or gnd
Is the code looking for responses only from motors defined by $338? I would expect that it should only attempt to communicate with defined motors.
Thank you!
If the Y axis UART pin is connected it will give communications error 100% of the time and will not set do simple things like set microstepping regardless of $338 set to 1
$338 set to 1 enables the X motor, 2 enables the Y motor...
Is the code looking for responses only from motors defined by $338?
Yes I think so - but with hardware adressing it is not possible for code to know which one is responding. With software addressing the CRC check of the response message will fail as the slave address is part of the response (IIRC).
I would expect that it should only attempt to communicate with defined motors.
Correct.
Y axis has MS1=5v, MS2=Open or gnd
Are you running the drivers with 5V VIO? The ESP32 is a 3.3V device and not 5V tolerant.
Hi @terjeio, I had previously tried 3.3V VIO, but hard limits were not triggering, so I reverted to 5V. With the correct wiring That weird trace would show 3.3V coming from the controller and 3.3-5V signal coming from the driver (not 0-5V).
With the updated code and 3.3V VIO I now get these results using addressing and only X Y installed. Set $338 to 2 or 3 (I had previously been using 3 with X and Y installed) Hooking up Y driver no longer causes M122I to fail M122I sent 20x sometimes has a single comms failure (same as with addressing off and Y UART not connected) I'm using microstepping as an indicator of proper communications. $150 has no effect on either driver, $151 affects only X driver Y driver seems to be operating at 1/32 microstepping regardless of settings. With $338 set to either 2 or 3 I get the same results $339 setting effect has not been tested yet
Thank you!
- Yes, I know. I keep looking at the ESP32 and wonder where to connect the debug probe... Recompile/reflash for everything I want to check is tiresome.
Forgive me if I have misunderstood your question, but could you not use JTAG ? eg
I found a bug in the TMC2209 driver code that will affect repeated initializations, but I forgot to update this issue. Sorry about that. And I have implemented the TMC2209_HWADDR option the wrong way around? It is also a bit hard for me to test this as I do not have a suitable board available.
Forgive me if I have misunderstood your question, but could you not use JTAG
The ESP32 boards I have does not have a JTAG or SWD connector, are there any boards available that has? Without limiting the number of available GPIO pins?
@terjeio thank you for updating this issue. I will report back my findings in a few days as I have hardware now I can test with that no longer looks like this.
Issue resolved. Thank you.
I'm using BigTree Tech 2209s. The User Manual for this 2209 informs to use the solder jumper to enable UART on the driver pin for TX and a 1k ohm resistor on that same pin for RX. I have a limited number of available pins on the ESP32 (not using any IO expansion) and I would like to use a common pin for all drivers (using MS1/MS2 to set the addresses). I don't really see how to configure this as no option in CMakeLists.txt and no examples.