A thread for finally figuring out sensorless drive strategies

VESC is open source, too, I bet if you look at it you can discern something slightly useful at least, easier than reinventing everything.

My tiny motor was I think 12 millihenries, not micro. So there must be something wrong with that measurement, you can get cheap inductance meters on ebay or use a frequency generator and oscilloscope ( including the test signal from an oscilloscope) to measure inductance although I was never able to get that working quite right. Theoretically the relationship between the phase of the voltage and current when a sine wave is applied should allow one to easily calculate the inductance. Remember the terminal to terminal inductance is what simpleFOC uses, however in some cases some authors use the actual phase inductance, which is half that.

Ah, OK will investigate inductance, I do have a LCR bridge, but was concerned about the effect of the magnetic field on the measured value. So didn’t trust the value above the STM software. IIRC the bridge measured something in the low uH range. Will test again and apply that value. And it’s nice to know about the terminal-terminal value. Where should I look for other such details? For example, should the resistance be per phase or term-term?
I think smaller motors will typically have many more turns of thin wire, so don’t expect large mH values for mine.
Any comment on adapting the simpleFOC B-G431B-ESC1 example? That is closed loop, position control. I have avoided looking into it too closely yet, as it has many things I’m unfamiliar with. Just thought the simpler the better to start with.
I have many distractions from this project at the moment, so work will be slow, but will report back as I progress.
Thanks again.
Cheers.
Pete L.

I have found by looking at the code that SimpleFOC uses the terminal to terminal resistance, which imo is the best way to do things.

The subject of how to proceed with getting a novel combination of hardware working comes up fairly often on this forum I have noticed, and the answer has been evolved to a reasonable degree, but I don’t think we have expressed it in a central location very well. For me, which is probably missing stuff for your situation :

Get things working at very low power and low rpm with voltage based open loop. The use of a current limited power supply is advisable. I used like 1 or 2 volts even as the driving voltage in the code.

Get your sensor reading sensibly.

Get the sensor adjusted so that it is reading accurately, and is coordinated with the electrical angle, simplefoc has calibration stuff and can measure the zero offset. This may be not needed for hall sensors, IDK.

Then try to connect things so that simplefoc loops around reading the sensor and updating the “electrical angle”, at low power.

Then there is pid tuning and a bunch of stuff I never bothered with so can’t really comment on.

Might want to get current sensing working at this stage.

-other stuff??

Then increase speed and power with no load, then add load.

It would be good to have something more detailed for the different drive strategies.

I don’t know in what way inductance is factored in right now, or resistance, I haven’t explored that, however I am under the impression it is often not used and kind of still in development? however for large motors it is more important.

IMO it is important to check operation is proceeding as expected at each stage. It’s possible to have the motor turning and apparently working but you actually are getting poor efficiency or it stops working at higher rpm and so on, if you don’t proceed carefully with eyes open. Check to make sure things are not overheating for instance. I think getting everything working only in clockwise at first is also advisable as it reduces complexity and confusion and adapting things to also work counterclockwise is relatively easy after the other details are worked out.

BTW you should be aware these b-g431b-esc1 boards are hard to solder, I was super careful and still almost ruined one like three times. I carefully tinned the pads and the wire and used small gauge wire from the picoblade kit, I think it was 28 gauge or something. Then hold them together and heat them and inspect carefully.

I had a few minutes to work on it. Measured term-term inductance. 34.7uH was the average of several measurements. And my LCR bridge also said 0.2 Ohms, but it’s not so good at low resistance. I have previously put 1.0Amps term-term and read 30mV, so have been using 0.015 per phase.
Changed to;
BLDCMotor(20, 0.015, 45, 34.7E-6);
And got some movement with 1.5v, about 3.7Rad/S before missed steps and cogging.
Also increased resistance incrementally up to 5.0 and got 6Rad/S, still with 1.5v
I need to have a good block of time to dig down through the code to see these units and learn more. Should get that time next week.
As for soldering, Dad taught me to solder when I was 8 years old, I’m now 67 and for the past 30 years have had a business designing and building electronics devices, hand soldering SMD components. I do have a small reflow oven but never found the need/time to get any experience with it. So yes it was not easy hacking the B-G431B-ESC, and it would be no way reliable enough to move off the test bench, but it proved useful. Gave me the (maybe flawed) confidence to buy $200 worth of Mosfets!
Thanks for your comments and assistance. Cheers. Pete L.

1 Like

Good to hear. I realized we kind of highjacked this thread, that was a mistake. Further posts on your project should probably get their own thread. Sounds like a cool project and chances are good there will be another thing or two!

I didn’t want to work on sensorless because I think there are a lot of other lowest hanging fruits but Elwin reminded me yesterday how easy it is to implement the Flux observer from the MESC firmware I shared in June. David Molony got it implemented in VESC also together with Benjamin Vedder.

All the credit goes to David Molony, it might look complicated here but
apart from the mess I made in SimpleFOC to be able to use Alpha Beta Currents and Voltages, those are the few lines that are needed for the flux observer.
It’s incredibly simple but yet effective, and it’s using only current sensing…
This is not meant for 0 or low speed, velocity open loop could be used for the start up.
This paper is not related to this implementation but explains the formula used for the flux observer.

Here I am only calculating and displaying the angle in the main loop while running in velocity open loop, I am not using the angle for the commutation or anything else:

It needs phase_resistance and phase_inductance, and the flux_linkage that is used to saturate flux_a and flux_b, I calculated it based on the KV for a hoverboard motor but I am not 100% sure about the value.
Maybe you guys want to experiment with it on b-g431b-esc1 to see if it’s worth going further.

2 Likes

Yeah I am game to do this at some point, probably not right now, but it plugs into the HFI thing, you would sort of need one strategy for low speed and one for higher speeds, this could work for higher speed. Do you think it might be possible to calibrate the system in some way using an angle sensor? We can measure inductance and KV cheaply using an oscope and LC meter, but the other three values I know nothing about. Perhaps we can go from things that are easy to measure and infer the things that are hard.

Another approach that could work to get a measurement, while the motor is turning, of the motor timing, is to use an optimization algorithm to adjust the voltage until the current is minimal. If the voltage is too high or too low, a motor spinning under light load will actually draw minimal current when the motor timing is the ideal 90 degrees. If the motor is slightly past, you are of course very close to stall, and the current goes up. If the timing is less than 90 then the current also increases. So there is a dip there, a minima. We could use that to calibrate the rest of the model for a particular motor, perhaps. Possibly even implement some kind of correction at higher rpm etc if needed.

I tried to use this phenomena directly with my fan but it’s too prone to stalling, at least with my crude implementation

Another issue is getting an adequately clean current signal. And filtering would mess up the calculations as it causes lag etc. so we can’t really depend on that very well probably. Any noise would probably mess it up? Some people are saying with the b-g431b-esc1 board they are seeing more noise from the measurements simpleFOC takes than with the MC workbench related tools that ST electronics provides (Although those tools in my experience rarely work and when they don’t there is no hope of getting them working)

I found with my experimeting that one of the issues with sensorless drive is this threat of stalling. If things stall the measurements quickly become a bit borked, the mathematical model isn’t usually sophisticated enough to factor in the additional complexity, or maybe it’s not even possible. HFI might be used to recover from stall. I think most sensorless drivers use a padding margin on the motor timing, i.e. they do not try to regulate it to 90 degrees, because of this issue. The extra margin helps defend against stall, but of course it reduces efficiency and maximal torque etc.

Flux_linkage can be tweaked as I show in the video, until getting sinusoidal waves for flux_a and flux_b.

I did my test on a b-g431b-esc1, I don’t see any noise issue. I only added the ADC calibration, I think the phase currents were more balanced then. Better adc offsets means more balanced phase currents means less noise on d and q currents.

I would be grateful if someone having a setup with an encoder could compare the electrical angle based on encoder angle and the flux observer electrical angle.
This could show us at what minimum speed we get accurate angle, and if we need to add any offset to this angle.

I am still new to SimpleFOC as a contributor, I have difficulties to see how this would be implemented as a sensor class.
But I think some of the refactoring I did helps simplify the implementation:

  • split the foc algorithm into smaller fonctions (Park, Clarke, …)
  • add members to the BLDCMotor class to store intermediate results (e.g. Alpha beta currents and voltages)
    That way some of those values are available for other algorithms without having to rerun the FOC algorithm partially (e.g. running getDCcurrent does that).

FYI, in the branch of SimpleFOC I shared, I commented out the use of phase_resistance in velocity_openloop because I need phase_resistance for the flux observer but I don’t want to use it for estimating the current.

Then HFI is another topic, we need to go step by step…

2 Likes

I have a fan set up on my desk, and I can set up my calibrated magnetic angle sensor again. I calibrated the sensor by runnign the fan in forward and then reverse direction and collecting about a hundred data pairs in each direction. Each data pair contains the electrical angle and the magnetic angle reading. Then I combined the forward and reverse data sets, assuming the actual angle that should be coming from the sensor was half way between the forward and reverse for a given electrical anlge (at a given RPM and voltage, the fan is very symmetrical so the load is the same in either direction and thus the motor timing should be pretty close to the same under the same voltage and rpm). Then I made a data set that allows me to go backwards from the angle sensor reading to what should be reasonably close to the legit angle. FActors in all the various distortions that these sensors suffer.

so it’s not an optical encoder and it would take me a little while to set it back up again, but I stil lhave the calibration file somewhere.

Then I could plot the angle from your sub system vs the angle from the sensor.

Do you have some code I could run to do the ADC calibration and then later on compute the angle as you describe?

I could get an optical encoder another time which is probably a good idea but they are kind of expensive and I would have to interface it to the motor and stuff. I think my little calibrated angle sensor would help a lot at least.

The angle calibration is done using a raspberry pi pico which communicates with the b-g431 board but the calibration is already done so I don’t need them to communicate any more. The pico would request the electrical angle from the g431 board and then I got it so the timing was good and stuff, I think the calibration is legit good. I tested and inspected things.

Oh, I actually have an optical encoder here, It’s built into a servo motor, which has some cogging which could complicate things potentially. I could use that then, but I would have to design and print an interface to it so I can mount the motor and stuff.

I am willing to do that if you want, if you can do most of the work to write the code you want me to run. IDL how many pulses per revolution it is, I think it’s 512, on the low side. It’s an AB type, two output pins, no index.

edit: I could buy this one Photoelectric Incremental Rotary Encoder 600p/r 6mm Shaft 5-24vdc AB Phase for Length Measurement + Coupling : Amazon.ca: Industrial & Scientific looks like a good quality one at least. I would have to print a system to hold all the parts in position etc.

This branch of SimpleFOC I already shared has:

  • some refactoring of FOC algorithm
  • the adc calibration for g4
  • deadtime compensation (off by default), so that I get smoother openloop on the hoverboard motor for the experimentation
  • commented current estimation for velocity_openloop

This is my b-g431b-esc1 project with the flux observer running in the main loop.

Based on the previous comments about soldering on the b-g431b-esc1, I will get sensorless working before I can manage to solder the hall sensor wires on it lol.

I don’t have the equipment to fit an encoder to a hoverboard motor now.
I should probably invest in a rig with a motor + encoder, any advice is welcome.

I can do the CAD for that encoder and your motor so you can connect them, I can even print parts and mail them to you if you want, they aren’t very heat resistant though. I would need the cad model of your motor and either to buy the encoder and model it or download the cad model. I FI do that I might as well mail you the encoder too.

To solder the wires on the board was remarkably hard and even using a new, sharp soldering iron bit, tinning both areas and carefully connecting them I actually short circuited the 5 volts to ground, they are right next to each other. Fortunately the thermal shutdown of the voltage regulator saved me and I was able to fix it.

I compared the electrical_angle generated by velocity_openloop and the flux observer angle and it seemed ok, so I went ahead even if it’s too early, I couldn’t resist:

Over 3 volts the d axis current becomes really bad. That’s bad sensorless but that’s still sensorless :sweat_smile:

I had to hack SimpleFOC to:

  • not fail in InitFOC because there is no sensor
  • not do any sensor alignment
  • use the flux observer angle

That was just for fun, this would need proper implementation but it gives hints what would need to change for sensorless.

1 Like

I posted some code for this board that just impements open loop, but with ramped voltage and stuff. Good for testing. You could run it without load in each direction, open loop, and print the electrical angld and the flux observer angle. Then graph them with the arduino serial tool, see if the angle accrding to the flux observer consistently says it’s slightly behind the electrical, which we know the rotor must be in open loop. You could then run it the other direction, or load it with your finger and see if it responds appropriately i.e. the angle between electrical and the flux observer should increase.

As long as it increases with motor timing and the relationship betwen motor timing is consistent across rpm and current etc, it could be used. Some kind of calibration could be done to mop up whatever source of error there is, as long as it’s repeatable.

I was running this in voltage mode and with lag compensation because of the phase_inductance parameter. That was probably a mistake.

Tomorrow I will try with FOC, and compensate with an angle offset if needed.

If the flux observer angle turns out to work well, it means:

  • no need for an interrupt for the sensor
  • no need for smoothing
1 Like

Let me know if I can help.

1 Like

I think I also understood how HFI works now, or at least one method.

Salient motors have a different inductance on q axis (Lq) and d axis (Ld).
When you measure the inductance and spin the motor, the inductance goes higher when aligned with q axis and lower with d axis.

HFI injects a high frequency square wave, basically you add a voltage to the dq voltages before the SVPWM on one PWM cycle, and substract it on the alternate cycle.
Then you calculate the dq currents difference between the highs and lows.
This let’s you calculate the inductance as we discussed here.

Once you know the inductance, you can derive the angle. For example
if Lq is 300 uH and Lq is 250 uH, and I measure 275 uH, I am half way.
The less salient the motor is, the worse this will work.

So with this SimpleFOC would be able to measure the inductance.
But I think for that it should be interrupt based as I mentionned here.

[EDIT] I might be missing some details about inductance measurement and converting it to an angle, I will update when I know more.

Another nice paper about flux observer.

And more details about that particular flux observer in MESC book.

1 Like

Now I integrated the flux observer in foc_current.
I made a motor.sensorless variable to switch sensorless on or off.
This defines if the flux observer angle should be used for foc, otherwise it’s using the hall/encoder angle if available.
I added an offset variable for my tests but it’s useless, the raw angle from the observer is good enough.
Added a faster _atan2 function but it would work without it.

The flux observer seems to be sensitive to the flux linkage value.
This formula can be used to calculate it:
Flux linkage = 60/ (sqrt(3) * pi * kv * pole count)
After tweaking it, I could run a hoverboard motor at 13v, I haven’t tried higher.

It’s probably good enough to try now. With a power supply of course :laughing:

1 Like

Nice, I could try it with my fan at some point. I would have to try various KV values as I can measure the peak to peak back emf per rpm the motor produces, but it does not seem to be the same.

Do you have example arduino code you can post that is good for a quick test? I can try to weave it together into a testing program that can be controlled over serial by combining it with my open loop tester program.

Now I am calculating the flux linkage here based on the formula I previously shared.

And my sketch doesn’t have anything special anymore, I am just calling BLDCmotor with pole_pairs, KV, phase_resistance and phase_inductance.

I am initializing Hall sensor so the init doesn’t complain but I don’t even have the wires soldered.

What you have to do is only set motor.sensorless to 1 when using foc_current mode.
The flux observer is only used for commutation now, shaft velocity will be zero.
I will check now if I could add the flux observer as a sensor.