My main control is ESP32, and I have run the open loop test and close loop test, both they were ok(yes, voltage control close loop is ok). i use two I2Cs connecting to AS5600s, use dual bus example.
At first i suspected that my pull up resistors’ value are high, and i change the speed of I2c to 100K, and sitll not OK. i checked the rising edge of SCL and SDA with OSC, it’s about 650ns, and didn’t exceed 1000ns.
I have not seen this happen myself. But many people have problems with the AS5600 - it isn’t so accurate. There is at least one other forum post I have read in the past that describes the same problem as you have. Not sure it was resolved.
It seems like the issue is the algorithm in the MagenticSensorI2C class.
There we are counting the number of revolutions and calculating the angle of the motor more or less as:
The tricky bit is knowing when to say that the rotation happened so for that we have a simple line of code line 88:
// tracking the number of rotations
// in order to expand angle range form [0,2PI]
// to basically infinity
float d_angle = angle_data - angle_data_prev;
// if overflow happened track it as full rotation
if(abs(d_angle) > (0.8*cpr) ) full_rotation_offset += d_angle > 0 ? -_2PI : _2PI;
This number 0.8 means that if the difference in between current reading and the previous one differs +0.8*2*PI ( +288degrees) when we say that the positive revolution happened if its -0.8*2*PI ( -288degrees) then we say that the negative revolution happened. So 0.8 is an arbitrary number that worked fine with most of the testings we’ve done so far. But if the sensor is noisy maybe it is a bit too low/high. So you can try fiddling with this number to try to get rid of the jump.
But as you said, since for the FOC the only important part of the senor anlge is the relative one (0-2*PI) then even if the number of rotations is wrong the motor will not loose the alignment.
If you have time to test it out, we’d be very interested to know which value worked best for you!
Hi Antun~
Many Thanks for helping with my question~ I changed the value from 0.8 to 0.5 and 1, then i found both of them are disappointing. if you rotated the motor fast, they would give even worse data than 0.8
However, it would not impact the alignment, I’d better try to improve my hardware design to avoid the noise~
Thanks again~
I also had data jumps from the AS5600 once! It was related to a magnet that came loose and misaligned. Only your hardware setup already looks great so I think it should not be the problem for you!
It is not necessary for SimpleFOC but from my own experience: many inconsistencies of the AS5600 went away when connecting the direction port to ground. It seems like not connecting this port can cause some disturbances.
Hi,
Finally I was able to resolve this issue please use this clone of library that I have modified.
Unlike what @runger kept saying it was not the sensor’s problem!
Looking at your code changes it doesn’t really make sense to me.
Firstly, you change the handling of the msb and lsb masks is the constructor. I think your fix may actually be correct here, I can’t quite figure out at the moment why the code is shifting 0x2 instead of 0x1 like your version. It may be an error. It would not actually make a difference to the AS5600 LSB mask, but for the MSB it looks like an extra bit is being included that should not be.
But anyways it does not matter, since later on in the code you drop the use of the bit masks altogether:
while (wire->available() < 2); // Wait for 2 bytes to become available
// Read the two bytes
readArray[0] = wire->read(); // High byte
readArray[1] = wire->read(); // Low byte
// Combine the bytes into a single 16-bit value
readValue = (readArray[0] << 8) | readArray[1];
Not using the bit masks could cause problems for other I2C sensors, even if it is working for AS5600. The MagneticSensorI2C driver is not supposed to be specific to AS5600.
You add a check for wire->available() to the code - but I am not sure this makes a difference unless the sensor is misbehaving. When you call wire->requestFrom() the data is already exchanged and it is already known how many bytes are waiting in the wire buffer. Normally, if the sensor is working well, it should always be the two bytes that you requested.
If it were less than 2, the original code would get back -1 from wire->read() and give a wrong result.
If it were less than 2, your code would wait forever at this point.
And then changing the readValue calculation to remove the bit masks would also not explain any improvement in your results - at best, the result is the same as before, at worst you now get incorrect data from the extra MSB bits not supposed to be in the calculation…
What do you think is the important change that has made it work?
I don’t think it’s really material though, at least not for the AS5600, as this sensor seems to return 0 for the MSB bits we’re not supposed to be using anyways.