FOC angle precision insufficient for 50 pole steppers?

in this implementation here, which is about using a HobbyKing BLDC for a robot, I see the same in line 35:

https://os.mbed.com/users/bdring/code/Hobbyking_Cheetah_Compact_DRV8323//file/3e056b097c52/PositionSensor/PositionSensor.cpp/

raw = raw >> 2

just recognized that for the Cheetah case the shifting could be a need for the look up table afterwards.

raw = raw>>2; //Extract last 14 bits
GPIOA->ODR |= (1 << 15);
int off_1 = offset_lut[raw>>7];
int off_2 = offset_lut[((raw>>7)+1)%128];
int off_interp = off_1 + ((off_2 - off_1)*(raw - ((raw>>7)<<7))>>7); // Interpolate between lookup table entries
int angle = raw + off_interp; // Correct for nonlinearity with lookup table from calibration

:scream: Oh ugh. No its not deliberate. Looks like its been this way for >1y. Issue is the MagneticSensorSPI class tries to be general, and this code works for the MA730 and other MPS sensors which left-align the data in the 16 bit frame. But all the AS sensor that are 14 bit have the data in bits 13:0 and thus lose two bits.

I’ve been using the hardware-specific sensor classes which don’t have this problem so I didn’t notice. I’ll write one for the AS5147 as soon as I can, it’s a little different to the other AS sensors because of its filtering functions.

And I’ll fix the MagneticSensorSPI class for the next release.

[edit] to test it more quickly yourself, you can just comment out that line. For sensors where the data is already aligned to the MSB it should be a no-op anyway.

[edit] looking at it more closely, (1 + data_start_bit - bit_resolution) = 1 + 13 - 14 = 0, so that’s actually ok, isn’t it?

1 Like

This won’t work (pun intended). Driving current through a motor when the desired position is equal to the actual position doesn’t deliver any actual torque. Simple analogy: pushing hard on the bike pedal when the pedal is already in the lowest position doesn’t impart any torque on the chain.

In order to apply any torque in open-loop mode there must be a displacement between the set position and the actual motor angle. In open-loop mode the torque is proportional to the sine of the angle error in electrical degrees, that’s why the incremental torque of stepper motors is poor. In closed-loop mode the force is whatever the controller wants it to be, the only constraint is that the net force is zero when the desired position is met otherwise it would accelerate away from the desired position :wink:

As far as I can tell this executes a right shift of zero bits, and therefore doesn’t throw away any bits.

If it did threw away any bits, the code tracking the amount of full rotations would definitely not work. I think the code works just fine (not tested).

Yup - it was @husky 's thinking that the data_start_bit==15 that confused things, but it’s not, for AS5147 data_start_bit==13.

I’m not disagreeing with you on the motor physics, but this analogy kind of shows the opposite in the sense that @husky isn’t looking for “driving torque” he wants “holding force”. And if you pushed down on the bike pedal as hard as you could, it would be difficult (for another force) to move it away from the down position.

So the bike pedal analogy (I think) kind of shows exactly what @husky wants - to “push downwards” so the motor can’t easily move from it’s position.

I just don’t know if it is possible to do this with a stepper - its not a bike pedal :wink:

The problem is that pushing downward on the pedal doesn’t provide any resistance against forces in this direction:

image

To provide actual torque you must drive the +q or -q axis, driving +d or -d does nothing. Well, it heats the room and may damp frequencies higher than the control loop frequency (~5Khz), but that doesn’t sound useful?

I disagree with you on the physics of the bicycle example, but not the motor example.

The downward pushing foot does oppose the motion of the arrow indicated, because the pedal must rise to turn. We’re talking about the rotational motion of the pedal/front cogwheel here, not the whole bicycle+cyclist.

But I think we digress. The key point for husky is that motors aren’t like bike pedals in this example, i.e. the motor windings can’t act in a single outward direction.

Ah, now I see that at line 48 the data_start_bit=15 is overwritten with 13, which gives a shift by 0.
I wonder if this is right for all sensors, where individual values have been predefined in the struct.

MagneticSensorSPI has 2 constructors, the one you refer to, which sets data_start_bit to 13, and one that takes a MagneticSensorSPIConfig_s struct as an argument, which allows you to set these values.

I agree it is probably not the most elegant API, but via the config struct you can actually set everything. You’re right that the other constructor won’t work for some sensors, but it looks ok for the AMS 14 bit ones.