Closed dead5ailor closed 1 year ago
Thanks for the issue, Will look into it asap, i hope this week.
Thanks for the detailed info, that gives food for thought (no solution yet)
I'm interested in the absolute position of the motor
OK, maybe this functionality should be build in the library to hold a cumulative counter of the steps.
Has somebody experienced the same problem?
Not seen before or heard of.
Or can somebody give me a hint what the cause for the jumps is?
Need some test to get a better understanding what happens.
OK, code looks straightforward, I see no error in that.
(Note: adding cpp to the backquotes in your post gives syntax highlighting)
Can you run the following tests?
so far my first thoughts
I also tried different motor speeds but the distance between the jumps in the angle stays at about 2945 measuring points.
OK that answers test 2 and 3 (at least enough for now).
I just tested it with a different AS5600. The issue still exists. I also tried the Seeed AS5600 library and with this library the same jumps are present.
The jump is at regular intervals. ==> word that pops up is interference but of what? how?
This is the detail that surprises me the most.
I will also try another microcontroller (Esp8266) tomorrow. I think its a problem related to the ESP32 because its also present with the Seeed library.
Q: how much time is 2945 measuring points? ~2.9 seconds?
Q: are there other processes running e.g. webserver? (no expert) The ESP needs to call yield() every so much time to give background processes some runtime. Could be a source of interference.
There is a simple test you can do.
Make a plot of the rawAngle() and millis() % 1000
It might be that at there is also a jump in time at the moment of jump in angle. (because of whatever).
It should show a broken line for millis() if this is the case.
(the % 1000 is to keep it inside a graph)
I think its a problem related to the ESP32 because its also present with the Seeed library.
Could be, still interested in the cause.
top is millis() % 1000 bottom is rawAngle()
your assumption was right. It seems like something stops the processor so that like 8 measurement points are skipped during the stop.
Q: how much time is 2945 measuring points? ~2.9 seconds?
I have to check this, but when i use delay(1) at the end of loop(), there are still jumps. The number of measurement points between the jumps is then smaller (around 1995)
Q: are there other processes running e.g. webserver? (no expert) The ESP needs to call yield() every so much time to give background processes some runtime. Could be a source of interference.
No, the loop() from post 1 is all that is running
Can you add a call to yield() after every call to rawAngle().
The printing of the data fills the send buffer and blocks when it is full.
Printing is a background process, that is driven by interrupts. As it roughly prints a same amount of bytes every iteration of loop() it continues to send data. If the output buffer is not empty when new prints start it gradually fills.
Do these affect the anomalie?
(Back to sleep )
Another test Increase speed of Serial port to e.g. 500000
I made some tests.
I used this statement to only print every 3rd value:
if (counter == 3)
{Serial.print(ang);
Serial.print("\t");
Serial.print(raw_ang);
Serial.print("\t");
Serial.print(abs_ang);
Serial.print("\t");
Serial.print(revs);
Serial.print("\t");
t = millis();
Serial.print(t);
Serial.println();
counter = 0;
}
counter++;
But due to printing the time in millis:
t = millis();
Serial.print(t);
I now can check the time in millis between two jumps. Here you see the millis() over the measuring points for the test were I put yield() after every raw angle: So by calculating the difference in Y values for two back-to-back jumps in the figure we now have the time between two jumps. For the first two points in the above figure we get 17751 ms - 15750 ms = 2001 ms. There is a two second time period between every pair of jumps.
I also checked it for the test were I only printed every third value. Here the time span is also two seconds between every jump:
The same goes for the test with baudrate = 1 000 000. There is also a interrupt every 2 seconds.
It seams like some background task is blocking the ESP every 2 seconds for about 5 ms. In this 5 ms some measurements get skipped and therefore the jumps in angle occur.
I made some tests. Baudrate 500 000 -> jumps still present Baudrate 1 000 000 -> jumps still present Baudrate back to 115 200 and yield() after every rawAngle() -> jumps still present Only printing every 3rd value -> jumps still present
==> So that eliminates the printing as cause of the jump.
there is a two second time period between every pair of jumps.
Perfect observation! ==> so this looks something timer controlled.
Googling "Xiao ESP32C3 2 seconds" did not provide any clue.
just a guess - maybe it relates to wifi?
add this line in setup() to disable it. (found on a forum, not tested)
esp_err_t results = esp_wifi_stop();
esp_err_t results = esp_wifi_stop();
did not compile in the arduino IDE. Maybe it needs some libraries.
I tried this code:
void disableWiFi(){
WiFi.disconnect(true); // Disconnect from the network
WiFi.mode(WIFI_OFF); // Switch WiFi off
}
from https://www.mischianti.org/2021/03/06/esp32-practical-power-saving-manage-wifi-and-cpu-1/.
It compiled but the problem is still present. Also i don't use WiFi in my current sketch. I also think that the WiFi is off until i turn it on explicitly.
Thanks for testing - sorry for wrong code if other ideas / insights pop up I'll let you know. For now pretty clueless.
Thank you too for your hints and help, I appreciate it. I will post these investigations in the Seeed forum - maybe someone there can help.
Please post a link to your post on the Seeed forum here (so people can follow it)
@dead5ailor
just a question, does the function getAngularSpeed() works well for you? It is a function that has been tested minimally (not at such speed) so additional feedback is welcome.
Test program: AS5600_angular_speed.ino Expected output: 1400 RPM ==> 8400 degrees per second
I just tried it out. In the first figure you can see the rawAngle over the time in millis(). For ten revolutions the duration is (27793 - 27350) ms = 0.443 s/10revs. This equals to 1363 rpm or 8178°/s. The second figure shows the values of getAngularSpeed() over the time. It's quite fluctuating but the time span shown is only 0.5 s. I calculated the mean speed over 3000 measuring points of getAngularSpeed() and it lead to an average of 8212°/s.
EDIT: here is the log file if you want to check it out yourself. speed_test.txt
Thanks, looks not too bad on first sight - I'll dive into it later.
I am working today on a cumulative counter in the library based upon rawAngle() .
It has been asked for before, you use it too and it is not difficult to implement.
First tests failed hopelessly 😎 but the 3rd or 4th gave reasonable results.
POS REV
3644 0
3640 0
4100 1
4458 1
4458 1
4458 1
...
7818 1
8075 1
8346 2
8368 2
...
// and reverse
217 0
134 0
78 0
2 0
-116 -1
-213 -1
-248 -1
This is the additional interface - function names can change - what names do you prefer?
// EXPERIMENTAL CUMULATIVE POSITION
// not working yet.
int32_t getCounter(); // getPosition() ?
int32_t getRotations(); // getRevolutions() ?
int32_t resetCounter(); // resets counter returns last value. // resetCumulativePosition.
What is missing is an offset to set position to zero. now it just takes over rawAngle() so there is an offset difference. For a first (experimental) version this is quite acceptable imho.
Average result is acceptable 8212°/s - 8178°/s = 34°/s 34 / 8178 ==> 0.416 %
the variation of 2400 (highest - lowest) is not good (bad).
@dead5ailor
what makes more sense to you when the cumulative position / counter goes from positive to negative
POS REV
217 0
134 0
78 0
2 0
-116 -1
-213 -1
-248 -1
...
-4096 -2
or
POS REV
217 0
134 0
78 0
2 0
-116 0
-213 0
-248 0
...
-4096 -1
the variation of 2400 (highest - lowest) is not good (bad).
Looking at the test log, this is probably caused by the high frequency of the calls ~3 ms apart relative to e.g. fluctuations in I2C communications, and the speed of the internal sensor read out.
At 1400 RPM = 23.33 rev/s = 8400°/s ==> 8400 / 300 is about 28° per measurement in theory. Sampling 4x less often would reduce the impact of the I2C fluctuations. e.g. a delay of 10 ms between calls.
Thanks for testing.
@dead5ailor https://github.com/RobTillaart/AS5600/tree/develop has the experimental getCounter() if you want to "play"
I will also try another microcontroller (Esp8266) tomorrow.
Still interested in this test ..
For the cumulative angle (for example 732°) i would use something like getPosition()
or getCumulativePosition()
or getAbsolutePosition()
maybe.
To get the number of Revolutions (for example 2 at 721°) i would use something like getNumberRevolutions()
.
what makes more sense to you when the cumulative position / counter goes from positive to negative
If the rawAngle goes in positive direction then the counter for the revolutions should also go in positive direction. Vice versa for rawAngle in negative direction.
For the cumulative angle (for example 732°) i would use something like getPosition() or getCumulativePosition() or getAbsolutePosition() maybe. To get the number of Revolutions (for example 2 at 721°) i would use something like getNumberRevolutions().
OK, will update those in develop branch asap
If the rawAngle goes in positive direction then the counter for the revolutions should also go in positive direction. Vice versa for rawAngle in negative direction.
That already works, but the question is more subtle, If you go negative does the revolutions
So there is a rationale for both, the first makes sense if you want to do math with them (crossing zero) The second is feels more logical but math will fail
So I have a preference for model 1
I will also try another microcontroller (Esp8266) tomorrow.
Still interested in this test ..
I just tested it with a Wemos D1 Mini (ESP8266). No jumps are present with this controller: Due to the lower speed (i guess), the sampling rate is also lower compared to the ESP32 and so the angle distance between two measuring points is higher with around 25°:
But no repeatable jumps every 2 seconds
@dead5ailor
I merged the develop branch into master with the experimental getRevolutions() and getCumulativePosition() functions. It time permits, please verify if these works for you.
found a bug in the experimental code - https://github.com/RobTillaart/AS5600/issues/26 Not evaluated all scenario's.😒 Fix will be available later today.
Sorry I was busy the last days.
That already works, but the question is more subtle, If you go negative does the revolutions
- become -1 immediately (which makes sense if you are coming from a positive value)
- become 0 first (which makes sense if you start from zero)
How do you calculate the cumulative angle? If you do it like me: abs_ang = revs * 360 + ang; //cumulative angle over several revolutions
then you need to have revs
(the number of revolutions) go from 1 to 0 and start at zero. With this, the math will always be correct. For example: you start the microcontroller and the position is 20° and revs is zero because we just started. Then you go back 30°, so the cumulative angle should state -10°. Because of the angle jumping from 0° to 360° revs goes to -1. The current sensor reading is 350° at this position. Abs angle is then -1 * 360° + 350° = -10° so the math is correct.
I will check the new getRevolutions() and getCumulativePosition() functions asap.
No need to apologize,
Please note that the cumulative position is not based upon degrees but the raw values 0..4095. That is (1) fastest and (2) allows people to convert to degrees, radians or even RPM whatever they need.
Furthermore it does provide negative angles for CCW rotation
Looking forward to your feedback,
@dead5ailor What is the status (your opinion) of this issue? As it is not a library problem I prefer to close it. However if you have found the cause I would like to know to update in the documentation.
Found only this as possible cause - https://esp32.com/viewtopic.php?t=22955
Hi @RobTillaart, I think you can close the issue here. I posted in the seeed studio forum but there is no solution yet: https://forum.seeedstudio.com/t/xiao-esp32c2-5-ms-pause-freeze-every-2-seconds/267707
Due to limited time, I couldn't do further testing but i will inform you, if I found a solution. Maybe I will try another ESP32 from another brand to check if this problem is manufacturer related.
Hello
I use this library in with a Seeed Xiao ESP32C3. The AS5600 measures the angle of a DC motor (rpm: about 1400 rpm). I'm interested in the absolute position of the motor (i.e. values will continue at 360° and not start again at 1° after each rotation). Therefore im using the if-statement in my loop function to detect a full rotation and calculate the cumulative angle:
In my tests, I use the motor at constant speed and log the values seen in the Serial.print part of the loop via PuTTY. The problem can be seen if the logged data is plotted. At all of the red markers in the plot, the angle value jumps about 45° from on measurment to the next. The normal delta between two back-to-back measurements is 4° to 5°. Detail view of a jump: This problem is also seen in the plot of the raw sensor angle and the angle in degrees: The strange thing is, that the distance in time respectively the number of measuring points between two jumps is always almost identical. (This can be seen by the x values in the first picture. The distance between two red markers is about 2945 points every time).
Has somebody experienced the same problem? Or can somebody give me a hint what the cause for the jumps is?
I also tried different motor speeds but the distance between the jumps in the angle stays at about 2945 measuring points.