The answer: A little over twice as fast on STM32 without FPU.
I spent today converting all the essentials over in the hopes of getting my Lepton to run fast enough to replace the noisy drone ESC on my CNC spindle, but alas nowhere near what I’d hoped. Loop time has gone from 480us to 220us, and max RPM from around 900 to 1900 (21k electrical). I’d like to double that again, but it would require hacking everything together into a specialized firmware rather than retaining the modularity of SimpleFOC.
you may get even faster if you go for integer math and indexed lookup tables.
thats a massive effort though. also if i run it on my h755 your fixed point will execute 20us, so 20k rpm? 200k electrical will need at least 1mhz pwm though to be effective.
the skin effect will kill your motor. you will need expensive litz wire motor.
STM32G031, 64MHz. I do agree 220us seems awfully high for how little there is to do, but I don’t think I’ve made any mistakes in my measurement, assuming _micros() is reliable. About half is loopFOC and half is motor.move (velocity mode). I need to do some disassembly to make sure the compiler’s not doing anything stupid.
EDIT: It is. Calling a function __aeabi_lmul which I presume does a full 64x64 multiply, instead of using smull which is perfectly valid since the operands were cast to 64-bit just before the operation and the result to 32-bit after. I’m fairly sure GCC used to do this properly on ARM7 and ARM9.
EDIT2: Nevermind, I forgot smull is not available in thumb mode. I’ll have to see if I can get it to compile in ARM, and if it will fit in the limited flash space available…
lol, of course it would be faster with a faster CPU, but then there would be no need for fixed-point. I can’t do much with lookup tables since G031 only has 64kb of flash. Current program size is 59kb.
The motor (Racerstar BR4114, 400kv, 11 pole pair) claims to be rated for 4-8S lipo, so my 12V power supply shouldn’t be anywhere near enough to worry about high frequency issues.
Lepton doesn’t have current sense, so this is just using the voltage-based current limiting.
I haven’t gotten it to compile in ARM yet. I removed the -thumb flags in platform.txt, and tried faster optimization modes, but the assembly output is still thumb. No -thumb flag showing in the build command line, so I’m not sure what the problem is. I should probably just abandon this project. Compiler wrangling is my most hated part of programming.
EDIT: Wow, I tried adding -marm in platform.txt and got an error that this CPU doesn’t even support ARM mode. I guess fixed-point is out then.
Isn’t fix-point just integer math ? Or is it depending on specific instructions rather than shifting bits ?
On G0 you could get the floating point math faster with QFPLIB, that’s also what RP2040 is using I believe.
Yes it’s just integer math, but without the 64-bit multiply I don’t think I can get it as fast as I need without a lot of effort. SimpleFOC uses a ton of multiplies, so that’s where I was hoping to get my easy speed increase. I suppose I’ll try writing an assembly 32x32=64 multiply before I give up though. Perhaps I can speed it up a bit since I don’t need the lower 16 bits of the result.
It is possible there’s still something wrong with the clock configuration or something. I’m using the generic G031G8Ux board definition, which defaults to 16MHz without a custom SystemClock_Config(). It’s been a long time since I dealt with that, but I do remember it being much faster after adding it, and F_CPU reports 64MHz, so I think it’s working properly.
I wrote a custom C++ multiply in preparation for the assembly version, but I’m still getting 220us loop time, so I don’t think it would make enough difference to continue. Also one of my transistors went incandescent during a few seconds test which maxed out at 2500RPM. I guess the bad timing when pushing the limit resulted in the back EMF not cancelling the applied voltage as expected. Surprisingly it still works, but I think it’s best not to try for high speed without current sense.
I’ll go back to the drone ESC for now. I could use a B-G431B-ESC1, but it has no exposed analog pins so I’d have to use digital halls, and they’re not so easy to get mounted on this motor. I’ve already spent more time on this than I wanted to, and it’s not like making a milling machine’s motor quieter really matters anyway since cutting is noisy too.
EDIT: Now wait just a chicken pickin’* minute here… aside from the slow loop rate, I’m maxed out on voltage. I’ve been testing with my usual 2S lipo battery, not the final 12V supply. I always forget that the motor voltage can only go to around half the power supply. Top speed is reached around 4V in SVPWM mode, just as it should be. I tried bumping it to 5V and got no increase, and that’s why. Probably contributed to my transistor light-up, too. But still, I don’t think I’m going to get twice as fast without significant risk of burning.
*The usual term is cotton pickin’ minute, but I really was picking apart a piece of chicken.