SimpleFOC and Linuxcnc

Hello all,
I found this project and community yesterday while exploring ways to improve my cnc setups. I have ordered a Nucleo-64 board and some high-power pololu stepper drivers that should deal OK with driving some steppers at 4.5A/48V, to have a play. I have a couple of cnc machines using steppers that run normal open-loop style and one that uses the hbs86h closed-loop driver/stepper/encoder system; all controlled by linuxcnc.

It seems to me that FOC allows us to convert a stepper motor to a very inexpensive servo system by adding an encoder and changing the control method; this would be an amazing upgrade to be able to do at such a low cost. I think the hbs86h use FOC, but they are a nightmare to tune as the software is proprietary, mostly in Chinese, runs only on Windows and doesn’t work for all of the drivers.

Can anyone recommend the best way to interface a SimpleFOC system with Linuxcnc? The easiest by far for me would be step/dir interface, requiring minimal extra hardware and making it a true modular drop-in replacement - using existing parallel port & breakout boards, and existing stepper motors, basically just having to replace the stepper driver. ODrive does this for BLDC motors, where you can set up the drive over serial link to interpret a step pulse as a position setpoint, and have lcnc drive it as in position or velocity mode as needed.

Basically I’m hoping there’s a way to drive a SimpleFOC system using a pulsestream. Is this possible, or is there only interest in a serial interface? Setup and tuning over serial is fine as there’s no realtime requirement, but the motion control would need to be a pulsestream.

Would it work to read a step input pin during the arduino main loop? Has anyone tried this, or implemented it?

Thanks in advance for any help!

1 Like

Some kind of interface based on Step / Dir with Simple FOC would be really very interesting since this opens the door to be able to command BLDC motors with GCODE which connects it to the CNC world :slight_smile:

1 Like

Yes, exactly this! As I say, ODrive allows this with BLDC motors & cheap encoders already, but doesn’t provide for driving the super-common 2-phase stepper motors. Pulsestream/Step-Dir control might be old, inelegant, dumb or limited or whatever, but it’s also an extremely common interface and works with both steppers and servos - if this is available it opens so many use cases.

Hey guys!
I’ll try to implement a simple step-dir interface for next release.
If not an integrated solution, at least a nice example code :smiley:


Great, this is what I was looking for - I look forward to being able to test it :slight_smile:
Thank you Antun!

i wonder how you address the PID since overshoot == crash in CNC land. I’d love to try this out but I’ve not been able to tune the PID well enough to try.

Hey @schoch,
I agree actually, the compliance is not the feature you wish to have from your precision machines. And that is a real problem of the FOC implementation.

Basically in order to have precision and power you need to have very very very precise sensor, and especially with stepper motors which have cca 10x times number of pole pairs.

I am not 100 percent sure that it will work just as a replacement of a stepper motor. And to be honest, I am not sure that the FOC algorithm is the one to go for. For cncs and 3d printers, simple algorithm that would monitor motor position and check if the step has been executed and redo it if not, would be enough to run the cncs well.

This could be done with the simplefoc as well. To run the position control in open loop and then correct if there is some error using the sensor. You would loose the energy efficiency of the FOC control but would not have to implement a well designed control loop. I would be very interested to see this in action though.
But you could imagine to do the same thing with the regular stepper driver. (step+dir) interface. You add the sensor and each few hundreds of milliseconds you check if all the stepps have been executed, if not you make sure they are executed for the next sample time. (especially since there aren’t many cases when this actually happens).

Honestly I think that BLDC motors are much better choice for replacement of stepper motors than FOC controlled stepper motors. Because steppers have not been designed for precision motion control, they have been designed to follow :smiley:
But I still think its a pity that there isn’t more efficient stepper controller boards and algorithms and they definitely have their place in the world of precision controller servo motors.

I’d love to see this working…

I think the overshoot and sensor accuracy is maybe less of an issue depending on the gear-down? If the BLDC is geared down by, say, 50, then an AS5048A (14-bit) sensor attached to the motor, would have a nominal resolution of 0.00044° on the output - smaller than 1/2000th of a degree.
Combined with a control routine that limits acceleration - i.e. slows the motor gradually when approaching the target, I think you could achieve some pretty good accuracy?

Maybe CNC is especially hard since you’d have to tune the solution to handle quite different loads (steel vs foam) - but a laser-cutter could be an easier first test for GCODE -> SimpleFOC?

To add step/dir support in STM32 is simple, use a TIMER had setting the clock source to STEP input, and get the counter when needed. But have no mind how to do it in AVR.

1 Like

@zhangzq71 i guess you’d attach interrupts on the two pins and adjust the angle by ±2PI/200 radians per rising step received on step pin (adjusting for any gearing)

To attach interrupts for STEP signal will cost too much. What I will do is to count the STEP singal by using TIMER, and configurate another TIMER to generate interrupt in a fixed period, such as 20Khz. Read the STEP count and process in 20Khz.

You would need to use a timer which has configurable up down direction base od dir input. Its not trivial to solve it even with the counter.

For the moment the simolefic library will support an interrupt approach, but this is just a simple implementation and it is definitely not the optimal one :smiley: . The code is already implemented in the dev branch. Here is an example:

1 Like

Yes, for STM32 the best solution I think is the encoder function in TIMER which it handles both DIR and STEP in hardware.

For interrupt implementation it will cause the process of every loop not in real time.

@zhangzq71 I’m not sure what you mean by TIMER and how it handles DIR and step in hardware. Are you referring to HAL_TIM functions?

Interrupts and timers both use HAL_TIM on stm. Interrupts are done in hardware and are a super efficient way of detecting a change of pin state.

Arduino has some limitations on interrupt (two interrupts?). Software interrupts might require additional processing but hardware ones do not.

TIMER is a STM32 peripherial device that your used to generate PWM signal to control the motor, TIMER is driven by a clock signal both internal and external. When the clock was configurated to connect to a STEP signal the TIMER will count up/down depends on DIR that will not consume the CPU power.
If you connected STEP to EXTI, each STEP plus causes the CPU go into ISR to count, that will consume much CPU power.