Sammy C21 support for 2 TMC2209 drivers with UART com
-
PS - in your SAMMYC21.h file you should not need the line "constexpr IRQn TMC22xxSercomIRQn = SERCOM3_IRQn;". Also you should enable stall detection in that file, to match the configuration used by working TMC2209 configurations.
-
@dc42 The board has a LMP78 regulator so VIN should be there at the same time of possibly before 5V if not the 100uF capacitors delays things.
Here's the changes I made in Platform.cpp to make it compile.
I agree, should continue with one driver and see
-
@dc42 Hi again. One thing before I put this aside for a while.
I see now that you (1LC and mini5+) pull PDN_UART high whilst the step sticks pulls it low.
That suggest to me that I might have to invert the signal to make it work. I might be barking up the wrong tree here but is that possible to do?
1LC:
BTT TMC 2209 Stepstick
-
@dc42 Yes!!! Win
Well, sort of anyway. I removed the pulldown resistor on the step stick and added this ugly 20k pullup resistor and now it works anyway.
2022-01-30 22:46:11 M122 B124 Diagnostics for board 124: Duet SAMMYC21 firmware version 3.4.0beta7+8 (2022-01-30 19:28:27) Bootloader ID: not available Never used RAM 4808, free system stack 2745 words Tasks: Move(notifyWait,0.0%,127) HEAT(notifyWait,0.0%,117) CanAsync(notifyWait,0.0%,65) CanRecv(notifyWait,0.0%,74) CanClock(notifyWait,0.0%,65) TMC(delaying,1.9%,49) MAIN(running,97.8%,471) IDLE(ready,0.0%,40) AIN(delaying,0.3%,154), total 100.0% Last reset 00:05:31 ago, cause: power up Last software reset time unknown, reason: HardFault, available RAM 224, slot 2 Software reset code 0x0060 ICSR 0x00000003 SP 0x20007f00 Task MAIN Freestk 6126 ok Stack: 20001048 200037b4 ff0030e8 200030e0 00000000 00017cf5 00018a28 0100000f 00000000 20003064 20001d70 a5a5a5a5 a5a5a5a5 a5a5a5a5 a5a5a5a5 00000000 20001d40 00000000 a5a5a5a5 00018307 00000000 00017471 00000000 fffffffd 20003058 00000000 00000002 Driver 0: pos 16000, 160.0 steps/mm,stalled, standstill, SG min 0, read errors 0, write errors 0, ifcnt 14, reads 6229, writes 2, timeouts 0, DMA errors 0, CC errors 0, steps req 16000 done 16000 Moves scheduled 1, completed 1, in progress 0, hiccups 0, step errors 0, maxPrep 401, maxOverdue 0, maxInc 0, mcErrs 0, gcmErrs 0 Peak sync jitter -1/12, peak Rx sync delay 200, resyncs 0/0, no step interrupt scheduled MCU temperature: min 24.5C, current 26.8C, max 26.8C Last sensors broadcast 0x00000000 found 0 114 ticks ago, 0 ordering errs, loop time 0 CAN messages queued 2327, send timeouts 0, received 3743, lost 0, free buffers 37, min 37, error reg 0 dup 0, oos 0/0/0/0, bm 0, wbm 0, rxMotionDelay 300, adv 37058/37058
2022-01-30 22:50:56 m569.2 P124.0 R1 Register 0x01 value 0x00000001
Now, I don't know what to do about this later, can't remove resistors from step sticks and running jumpers.
-
@gixxerfast try using a pullup resistor of 4.7K or 3.3K. That might be enough to defeat the two 20K pulldown resistors without causing a problem for the Tx signal passing through the 1K series resistor.
-
@dc42 Thank you for the suggestion.
I added a 3.3K pullup and it seems to work great..
I have now two working motors with UART control.
Thank you for taking an interest in this and for all the help.
(Now, on to the next problem, I need to get a servo motor)
2022-01-31 11:57:21 M122 B124 Diagnostics for board 124: Duet SAMMYC21 firmware version 3.4.0beta7+8 (2022-01-31 11:32:38) Bootloader ID: not available Never used RAM 192, free system stack 3843 words Tasks: Move(notifyWait,0.0%,107) HEAT(notifyWait,0.1%,117) CanAsync(notifyWait,0.0%,64) CanRecv(notifyWait,0.0%,73) CanClock(notifyWait,0.0%,64) TMC(delaying,3.0%,45) MAIN(running,96.6%,490) IDLE(ready,0.0%,41) AIN(delaying,0.3%,154), total 100.0% Last reset 00:10:25 ago, cause: software Last software reset time unknown, reason: HardFault, available RAM 224, slot 2 Software reset code 0x0060 ICSR 0x00000003 SP 0x20007f00 Task MAIN Freestk 6126 ok Stack: 20001048 200037b4 ff0030e8 200030e0 00000000 00017cf5 00018a28 0100000f 00000000 20003064 20001d70 a5a5a5a5 a5a5a5a5 a5a5a5a5 a5a5a5a5 00000000 20001d40 00000000 a5a5a5a5 00018307 00000000 00017471 00000000 fffffffd 20003058 00000000 00000002 Driver 0: pos 112000, 160.0 steps/mm,stalled, standstill, SG min 0, read errors 0, write errors 1, ifcnt 28, reads 25370, writes 14, timeouts 0, DMA errors 0, CC errors 0, steps req 112000 done 112000 Driver 1: pos 96000, 160.0 steps/mm,stalled, standstill, SG min 0, read errors 0, write errors 1, ifcnt 26, reads 25370, writes 13, timeouts 0, DMA errors 0, CC errors 0, steps req 96000 done 96000 Moves scheduled 7, completed 7, in progress 0, hiccups 0, step errors 0, maxPrep 695, maxOverdue 0, maxInc 0, mcErrs 0, gcmErrs 0 Peak sync jitter -1/11, peak Rx sync delay 210, resyncs 0/0, no step interrupt scheduled MCU temperature: min 25.8C, current 26.5C, max 26.6C Last sensors broadcast 0x00000000 found 0 119 ticks ago, 0 ordering errs, loop time 0 CAN messages queued 5042, send timeouts 0, received 8123, lost 0, free buffers 37, min 37, error reg 0 dup 0, oos 0/0/0/0, bm 0, wbm 0, rxMotionDelay 426, adv 36934/37057
-
@dc42 said in Sammy C21 support for 2 TMC2209 drivers with UART com:
It's not going to work without the voltage monitoring if you power up 5V before VIN, because the drivers won't respond to the UART data until VIN is present. You may be able to get round this by sending M999 B124 to restart the board after powering it up.
Hi again. I'm exploring the voltage monitoring but as expected I run into trouble.
As seen above the Vin value is way to large (should be 24 V ish).
The only AD-port left is PB08 and I'm using that for voltage monitoring and as I am running the Sammy with 3.3V I'm using this in the configuration:
Edit: Tried the PA03 with the same result
I measure 1.7V at the monitoring point which matches the calculation with () the top resistor at 61Kohm and the bottom at 4.7Kohm.
(4.7*24)/61+4.7) = 1.71V
So, now I'm left with the question if PB08 is unsuitable for measuring the voltage?
I also see that PB08 is supplied from VDDANA whilst the PA08 is supplied from VDDIO.Any clue to why I don't get the correct reading?
Also, why is there so little memory left compared to the 1LC? They should have the same amount of memory as it's the same MCU (ATSAMC21G18A).
The firmware binary for the Sammy is small 118 kB and the 1LC binary slightly larger at 129kB -
@DC42 Might be of interest.
I have now temporarily replaced the Sammy C21 with a Seeduino XIAO extending Klipper.It has no problem communicating via UART with the TMC2209 without any pullup resistor (and with the 20k pulldown intact).
I'm going to look at the UART signal later. The Duet UART transmission without the pullup is shifted somehow. I can see that it's transmitted but it's sort of shifted so that the startbits comes last in the start byte instead of first. I'll add some pictures from the logic analyzer tomorrow.
22:00:07 SG_RESULT: 00000000 22:00:07 PWM_AUTO: 000e0024 pwm_ofs_auto=36 pwm_grad_auto=14 22:00:07 PWM_SCALE: 0000001d pwm_scale_sum=29 22:00:07 PWMCONF: c80d0e24 pwm_ofs=36 pwm_grad=14 pwm_freq=1 pwm_autoscale=1 pwm_autograd=1 pwm_reg=8 pwm_lim=12 22:00:07 DRV_STATUS: c0190000 cs_actual=25 stealth=1 stst=1 22:00:07 CHOPCONF: 34030053 toff=3 hstrt=5 tbl=2 vsense=1 mres=4(16usteps) intpol=1 dedge=1 22:00:07 MSCURACT: 00f7000c cur_a=12 cur_b=247 22:00:07 MSCNT: 00000008 mscnt=8 22:00:07 TSTEP: 000fffff tstep=1048575 22:00:07 FACTORY_CONF: 0000000c fclktrim=12 22:00:07 IOIN: 21000041 enn=1 pdn_uart=1 version=0x21 22:00:07 OTP_READ: 0000000c otp_fclktrim=12 22:00:07 IFCNT: 00000008 ifcnt=8 22:00:07 GSTAT: 00000001 reset=1(Reset) 22:00:07 GCONF: 000001c0 pdn_disable=1 mstep_reg_select=1 multistep_filt=1 22:00:07 ========== Queried registers ========== 22:00:07 SGTHRS: 00000000 22:00:07 TPOWERDOWN: 00000014 tpowerdown=20 22:00:07 TPWMTHRS: 00000003 tpwmthrs=3 22:00:07 IHOLD_IRUN: 00081919 ihold=25 irun=25 iholddelay=8 22:00:07 SLAVECONF: 00000200 senddelay=2 22:00:07 ========== Write-only registers ========== 22:00:07 DUMP_TMC STEPPER=gear_stepper
With Duet and Sammy C21 and no pullup on UART-line:
With Klipper and Seeeduino XIAO and no pullup:
-
@gixxerfast I think the reason is that in the TMC22xx driver on the SAMC21 we disable the transmitter for a short while in function TmcDriverState::StartTransfer. My guess is that this sets the output to high impedance. You could probably rewrite it to just reset the receiver, if you also defer enabling the transmit DMA until the very end.
-
@dc42 Thanks (very appreciated as always), yes I've been looking at this for a while as I suspect it could "drop the line" for a short moment:
#if TMC22xx_USES_SERCOM sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // disable transmitter and receiver, reset receiver while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else
Not sure if it's exactly there but I was thinking of trying to alter it a bit. Not that I know what I'm doing but it's per usual
-
OK, so far so good! It's been stable for a while now so maybe I can trust it
I don't totally trust it. I had to change in a few more places.@dc42 Well, that look promising
So now (I really hope it lasts):
Driver 0: pos 80000, 80.0 steps/mm,standstill, SG min 16, read errors 0, write errors 0, ifcnt 70, reads 13761, writes 1, timeouts 0, DMA errors 0, CC errors 0, steps req 0 done 0 Driver 1: pos 574280, 574.3 steps/mm,standstill, SG min 16, read errors 0, write errors 0, ifcnt 68, reads 13762, writes 1, timeouts 0, DMA errors 0, CC errors 0, steps req 0 done 0
$ git diff src/Movement/StepperDrivers/TMC22xx.cpp diff --git a/src/Movement/StepperDrivers/TMC22xx.cpp b/src/Movement/StepperDrivers/TMC22xx.cpp index 4b8a1acb..b301af8e 100644 --- a/src/Movement/StepperDrivers/TMC22xx.cpp +++ b/src/Movement/StepperDrivers/TMC22xx.cpp @@ -1441,7 +1441,7 @@ void TmcDriverState::AbortTransfer() noexcept #if TMC22xx_USES_SERCOM DmacManager::DisableChannel(DmacChanTmcTx); DmacManager::DisableChannel(DmacChanTmcRx); - sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); + sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN/* | SERCOM_USART_CTRLB_TXEN*/); //UER while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else uart->UART_IDR = UART_IDR_ENDRX; // disable end-of-receive interrupt @@ -1497,17 +1497,18 @@ inline void TmcDriverState::StartTransfer() noexcept regnumBeingUpdated = regNum; #if TMC22xx_USES_SERCOM - sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // disable transmitter and receiver, reset receiver + sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN /*| SERCOM_USART_CTRLB_TXEN*/); // disable /*transmitter <--- UER*/ and receiver, reset receiver while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver #endif const uint8_t regNumber = (regNum < WriteSpecial) ? WriteRegNumbers[regNum] : specialWriteRegisterNumber; - SetupDMASend(regNumber, writeRegisters[regNum]); // set up the DMAC + //SetupDMASend(regNumber, writeRegisters[regNum]); // set up the DMAC <---UER #if TMC22xx_USES_SERCOM dmaFinishedReason = DmaCallbackReason::none; DmacManager::EnableCompletedInterrupt(DmacChanTmcRx); - sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // enable transmitter and receiver + sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN /*| SERCOM_USART_CTRLB_TXEN*/); // enable transmitter and receiver <--- UER + SetupDMASend(regNumber, writeRegisters[regNum]); #else uart->UART_IER = UART_IER_ENDRX; // enable end-of-transfer interrupt uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and receiver @@ -1520,19 +1521,20 @@ inline void TmcDriverState::StartTransfer() noexcept AtomicCriticalSectionLocker lock; #if TMC22xx_USES_SERCOM - sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // disable transmitter and receiver, reset receiver + sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN/* | SERCOM_USART_CTRLB_TXEN*/); // disable transmitter and receiver, reset receiver while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver #endif const uint8_t readRegNumber = (registerToRead < NumReadRegisters) ? ReadRegNumbers[registerToRead] : specialReadRegisterNumber; - SetupDMARead(readRegNumber); // set up the DMAC + //SetupDMARead(readRegNumber); // set up the DMAC #if TMC22xx_USES_SERCOM dmaFinishedReason = DmaCallbackReason::none; DmacManager::EnableCompletedInterrupt(DmacChanTmcRx); - sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // enable transmitter and receiver + sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN/* | SERCOM_USART_CTRLB_TXEN*/); // enable transmitter and receiver + SetupDMARead(readRegNumber); #else uart->UART_IER = UART_IER_ENDRX; // enable end-of-receive interrupt uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and rec
-
-
-