bigtreetech/BIGTREETECH-S42B-V1.0

[Feature Request] Sensorless homing support

MiggyMan opened this issue · 24 comments

Given that this unit is able to detect missed steps could this functionality be adapted to allow for sensorless homing ?

AbeFM commented

There's no absolute reference (i.e. the belt could slip a tooth, and it only knows where it is within a given rotation) - you might be able to run it back till it stops moving, then use either absolute rotational position (probably what I'd use)...

I guess the later versions of the board have CAN ports - which yeah, I suppose you would be able to directly command - AND I feel you could drop this lame idea of sending steps.

Quas7 commented

this is not really "sensorless" as we have a magnetic sensor system here. ;)
But, we would need to wire a pin of s42b back to the endstop pins of the controller. I think, it is doable but does not really reduce the wiring as "sensorless" does.

For 3d printers the sensorless homing is normally bound to stallguard (or back-EMF measurement) via TMC drivers.

https://www.trinamic.com/technology/motor-control-technology/stallguard-and-coolstep/

Quas7 commented

@AbeFM
the S42B keeps track of its absoulte position as it is counting rollovers as far as I know.

EDIT: looking at the very similar closed-loop stepper "Servo42B" from MKS, there is already a function that shows high angular deviations via a blue LED (BLUE_LED).
https://github.com/makerbase-mks/MKS-SERVO42B/blob/master/firmware/src/BSP/MKS.c

We also have it on the S42B, the red LED that flashes before and after calibration lights up when the error between the desired and actual angle reaches more than about 36°.

Quas7 commented

@swanepoeljan
yes, you are right - forgot about that.
It should not be too difficult to copy that function and generate a trigger on ~2° and pull one of the extension pins high/low to mimic an endstop for the motion contoller board.

AbeFM commented

Yeah - with the boards that have CANbus, you could run them like trinamic drivers. I know they talk serial, but I don't know if they entirely commanded that way (without step/direction pulses...) - my point was you could implement that set up if you can talk back. You'd save DIR, ENABLE, and STEP and replace with CANH and CANL, plus power/ground, sounds like a 4-wire solution.

I think one thing you could look for, while homing, is a wind up of the I variable - if you get even 1 degree out, wait a short time, if it's winding up I and P is constant, then you know you're hitting a hard stop.

@AbeFM Are you referring to S42B boards?

I guess the later versions of the board have CAN ports

Haven't seen any of them but would be really interesting! Would also mean an upgrade of the MCU since the STM32F030C8T6 does not have a CAN controller onboard. I like the idea of using CAN! Do you know if it's supported in Marlin or any other firmware?

Good idea for also checking I-term windup to detect a hard stop! This could help to distinguish between bumping (or sudden acceleration) of the control surface or hitting a hard stop...

Quas7 commented

@swanepoeljan
You can DIY it in but not on S42B.
I saw a "wiring example" for the STM32F030C8T6 here: makerbase-mks/MKS-SERVO42B#11 ;)
So far, for 3D printing I did not see any CAN-capable yet (Feature request still open here: MarlinFirmware/Marlin#7735).
For CNC the regular highend does use some real time ethernet, I think.
Given the non-linear behavior of the extrusion, I am also not sure, if there is a big benefit of letting the controler know the actual movment. I mean, the extruder will always blob a bit and ruin an "error free" print, if something is going wrong with steps and has to be corrected (slowed down).
But maybe I miss real benefit here in terms of print reliability?

Thanks, looks interesting!

When I think of CAN, I think of a more distributed system. So drivers don't have to be in a box with fans trying to keep them cool but could be mounted on the steppers, like with these close loop solutions. The wiring could be reduced overall and also the noise generated (and picked up) by pulsing steps at a rapid rate (and high currents) through the fairly long motor wires could be reduced. Losses and inductance in the motor wires could also be reduced... Things like the screen and controls are then just nodes and can be mounted anywhere on the bus.
Like you said, for extrusion maybe providing feedback on missing steps would not bring much but maybe there is some other telemetry that it can give back to improve it's operation.

Looks like RepRap firmware has some support for CAN

Quas7 commented

maybe we just wait for this campaign to rum: https://www.ogadget.com/x/ananasstepper3

AbeFM commented

Agreed - and for extrusion, I don't see much value in closed loop. Maybe I'm missing something. If the set up is even close to right, it'll just shred the filament if you force it, perhaps there'd be some small jams you could fix... But at that point I'd want to have full motion feedback so I could run the extruder both directions and even so I think it'd be a few percent chance of fixing it. I doubt you can do a lot worthwhile without the printer being smart enough to wait for you to fix the error - then you're back on bidirectional communications.

I don't know how the Trinamic drivers do it, but they DO talk back, my Prusa's quite happy to rehome as much as it needed. I'd assumed it was i2c or can which is why I was hoping it would be reasonable to do here. Worst case you could build a box to translate it, but my hope was to lower the load on the CPU by sending target position/speed commands. Certainly I won't be rewriting Marlin from scratch. :-)

By the way - check out ODrive, I think it's called. https://odriverobotics.com/ It's been around a bit, I think it would be closer to out-of-the-box than some others.

Quas7 commented

Oh, you should really test what you can do with a geared extruder setup like BMG (my favorite) or a Titan with closed loop.
For my direct drives I run these little tiny and light 0.7A pancake NEMAs with 1.0A limit and I can retract and print as fast as with a double size stepper (given that the, PID will catch some of the high Jerk in this case).
Of course, if I overdo it I strip the filament but normally the pancakes click before that happens in open-loop.
And this setup stays cool to the touch compared to a closed loop with 1A over-current where you risk burning your fingeres (or melt something else close by). Of course, I have to trust the angle-deviation shutdown of the S42B if I get a jam - otherwise, the motor will reach the same critical temperatures as well.

The Trinamics just measure Back-EMF and they use it for their "Stallguard" feature for remote load sensing. Works really nice also for me for precise homing but it only indicates the load not the position.

But honestly, with a cheap SKR1.4 turbo there is not much need to offload anything anymore to save on CPU cycles.
You do not need a Duet anymore to reach 500mm/s on deltas or something like this. ;)

Regarding the ODrive, I do not even have servos yet on my CNC where this would really make more sense!
But thanks for the hint, maybe I still need something for Christmas for myself.

AbeFM commented

You're saying the advantage to closed loop is being able to run lower drive current?

Huh. Well, I was all prepared to call you crazy, and I don't think it's the "right" way to do it, but it does sound like it'd let you run a lot less current. And yeah, if you're on the hairy edge - stallgaurd can be iffy. And if you're not, then you're dumping a lot of heat. Printing in summer on a Prusa is not what printing in winter is on one of those.

Quas7 commented

Maybe you think of it the other way around.
I use a much higher current limit with closed-loop than the rated RMS current of the motors.

In open-loop the drivers always push a higher current into the motor.
The closed-loop does only apply higher currents, if there is a sufficient deviation from the setpoint (small deviations = small currents).

Therefore, I use 50% overcurrent (0.7A rated but I use ~1A RMS current limit) as the higher current is only needed for short time periods and is not overheating the motor.

Quas7 commented

Regarding the FR for sensorless homing one possible way to implement it:

  1. Copy the red-LED function with a lower threshold of ~0.4deg (quater full step sounds ok?)
  2. use either SWCK or SWDO pin on the extension header as "active low" to trigger an endstop on the mainboard
  3. In order to keep SWD programming possible, the used pin should only be an active output, if used by the function and stay an input otherwise.
    Edit: keeping 100% on-the-fly programming seems to be impossible (for me).
Quas7 commented

I implemented the functionality in this PR: #27

If we felt really confident we could also write a UART bootloader which is flashed through SWD. Then after that we could use the SWD pins for these kind of features and just flash our firmware updates using the bootloader (and USB to Serial bridge).

Quas7 commented

That would be one nice solution. But I did not yet try this with a full mechanical setup but only with a small lever.
But without Boot0 accessable we would require a time window approach, right?

We could also maybe free the RX/TX and switch them over to the SWD pins but a software UART is maybe eating up too many cycles given the small STM32 here.

But without Boot0 accessable we would require a time window approach, right?

Also think so, or maybe the bootloader can check one of the buttons. So when you power up or reset while holding a button down the bootloader detects it and waits for new program upload, else continue with normal program execution.

To fast track things we could maybe even look at something that's already available. Quickly Googling I found OpenBLT which looks promising.

One challenge might be to fit everything on the 64kB of flash memory we have on the STM32F030C8. The calibration table takes the last 32kB, just before that sits the parameters which blocks another 1kB and it seems OpenBLT would take the first 5kB. So we are left with 26kB for the actual code.

Can't remember what size the original firmware was but my fork sits at 28kB so would need to do some serious optimization to fit it all in.

Another option we could try is to jump from user code to the existing UART bootloader in ROM. Would then be almost the same as having BOOT0 available. Have never tried it but seems to be possible and also mentioned in AN2606. The big advantage here would be that we don't have to give up precious flash memory for another bootloader.

Another nice thing about this last option would be that we can invoke the bootloader whenever we want, like from the OLED menu or even a serial command...

It works! The last option, its possible to jump to the system bootloader and then upload through UART1!

I created an InvokeBootloader() function which performs the jump and made it accessible through a serial command. So then in the Terminal program I used this command to call the jump function. Then I disconnected the Terminal and used the Flash Loader Demonstrator to upload the .bin file and it worked!

Here is the code:

void InvokeBootloader()
{
  // Function pointer to bootloader in system memory
  // Referenced from AN2606 Rev.44 Table 141. 
  // The first word is the stack pointer and therefore the 4 byte offset.
  void (*BootMemJump)(void) = (*((uint32_t*) 0x1FFFEC04));

  // De-initialize UART1 as it will be used by the bootloader
  LL_USART_DeInit(USART1);

  // De-initialize RCC
  LL_RCC_DeInit();

  // Stop SysTick timer
  SysTick->CTRL = 0;
  SysTick->LOAD = 0;
  SysTick->VAL = 0;

  // Disable interrupts
  __disable_irq();
  
  __DSB();  
  __ISB();
  
  // Set Main Stack Pointer
  __set_MSP(0x20001000);
  
  // Jump to bootloader
  BootMemJump();
}

and here the confirmation from Flash Loader Demonstrator:
image

So over the weekend I will try to add the upload functionality to the Terminal program so that it can be done without the Flash loader. Something like this:
image

Quas7 commented

@swanepoeljan are you kidding me!? This idea was not older than 24h and there was no weekend in between!
I was not even able to comment fast enough that I am of the same opinion to save every 'bit' of the precious flash for some clever ideas coming up later. ;)

haha... I must admit the idea of jumping to the system bootloader was really fascinating, even left work early to come and try it out! Sounds like you are working on something interesting there... ;)

Quas7 commented

hrhr, that is the right attitude!
I am really not a programming guy but this PID autotuning is something for the Christmas time to get a bit more skilled, I think. One needs challenges to grow, you know. ;)

Yeah - with the boards that have CANbus, you could run them like trinamic drivers. I know they talk serial, but I don't know if they entirely commanded that way (without step/direction pulses...) - my point was you could implement that set up if you can talk back. You'd save DIR, ENABLE, and STEP and replace with CANH and CANL, plus power/ground, sounds like a 4-wire solution.

I think one thing you could look for, while homing, is a wind up of the I variable - if you get even 1 degree out, wait a short time, if it's winding up I and P is constant, then you know you're hitting a hard stop.

I'm working on prototype of such board =)
So it has stm32g4 cpu, tmc51xx stepper driver and 15bit encoder,
can be powered with usb-c with pd, has CAN-FD (up to 8 mbit) and s,d,e, error pins to interface with legacy hw.

Board can be powered from 4.5 to 34 V