A thread for finally figuring out sensorless drive strategies

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.

You want to see a Magic trick?

2 Likes

Nice! I would need actual code though if I am to do any testing any time soon. The fan and board is still sitting set up ready to go on my desk, so now is a fairly good chance to investigate. But it would take me a long time to reproduce the steps to implement things you have taken thus far. Even if you can just post your code verbatim, I can try to edit it down to the elementals and debug that, but doing everything de-novo I cannot spare the time for, unfortunately.

I don’t get your point.
You have my simplefoc modified code and my sketch on github.

That’s just so nice :slight_smile:

I think we should try to integrate it into SimpleFOC, but this will take a little bit of time before the next release, in order to integrate all of Candas awesome changes…

But I looked at it and I see a section where you calculate the flux linkage, but I don’t see the function that accepts the current values and then spits out the actual rotor angle anywhere…I could peer into the documents you posted and try to follow the steps you took to concoct it but it would take a while.

What’s the actual main.cpp you are running right now, an exactly what libraries need to be present to compile it? The branch of simplefoc I get, I uninstall my old simplefoc library and get that one installed.

It sounds like you are using platformio which could complicate the compiling process, I haven’t tried platformio although it sounds good it also sounds kind of complicated to get started.

I think what we need is a single function that takes the flux linkage value and whateve relse it needs and gives you the rotor angle, or the angle between the electrical and the rotor at some instant.

I know what to do from there, the mystery has always been how to infer rotor angle from current data and whatever other data there is. My understanding of a state observer is that that’s the essence of what it does, it takes what you know, and, over time (may require some time stamped historical data points), tells you something you didn’t know. In this case, the actual rotor angle. Using a model of the physics of the system, basically. Gets complicated, but that’s the essence of it.

We have the data we need, I think with adequately low noise and time resolution.

Oh, I would have to calibrate the adc too, I can try reading up on that but why don’t you just post exactly the main.cpp and whatever you are using? That’s what I always do. It takes time to make and debug even short programs. Many times I have even dug up my old forum posts because I lose track of what the best program is and that’s a known good point, or I wouldn’t bother posting it.

I already shared my branch of SimpleFOC with the flux observer and adc calibration, and I also shared my sketch. Not sure what else I can do.

Maybe you should wait for this change to possibly be in the dev branch then, but it will take time.

I understand it’s not easy to contribute to SimpleFOC, I am trying to help but I hardly get feedback from the community.

1 Like

Can you tell us where the code that does the flux observer stuff is located? I can’t find it anywhere :frowning:

Thanks for the contributions, it is good to have a feather in your cap and it’s also a really good way to learn. The community does contribute but it is a slow moving phenomenon, I agree it would be nice if things were better. There aren’t many of us and the incentives are not aligned very well.

Line 361 in loopFOC https://github.com/Candas1/Arduino-FOC/blob/accda992e5f56f9c1179e944da764679eab86070/src/BLDCMotor.cpp

1 Like

Yes you found it :stuck_out_tongue_winking_eye:

It’s worth learning how to better use github as well:

  • That’s how I share a reference to a particular line of code
  • here you see the commits of this branch. It’s a bit of a mess because I had to revert some changes
  • this should be a comparison between the dev branch of Simplefoc and my branch
1 Like

Ok, I will try to see if I can get it into a single function that is contained and independent, then try to calculate/measure the flux linkage for my motor, and see if I can get it to give me information and see how it compares with the info from the angle sensor.