-
-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
i2c reading gets stuck sometimes #28
Comments
Thanks for the issue, I will look into it asap. |
You're welcome! The ESP32 might need to attend some background processes (wifi, BLE or timers?) and blocks your code to process these. You might try if adding yield() solves this. In short this gives explicit control to pending background processes. Something like this void loop()
{
yield(); // handle background processes
uint32_t start = micros();
rEncoderRaw = rAs5600.readAngle();
uint32_t duration = micros() - start;
if (duration > 1000)
{
Serial.print("angle time: ");
Serial.println(duration);
}
// process measurement
} If this extra yield() does not solve the issue you might need to dive into RTOS. Another option is to have a logic analyzer on the I2C bus to measure the time between I2C request and response. If the delay is in the sensor you should see a relative long time between request and answer. |
(math note)
3800 RPM is less than 70 rounds per second ==> 1 rotation per 14 milliseconds. |
Thanks for your response! Sadly, adding the yield time did not solve the problem, but thanks to your updated code I now do have the time in μs: 1001274 to execute the Also, you are right to note that I need a sample very often, I am hoping to find a mechanical solution for this by putting the encoder on another shaft, but I'm not sure yet if this is possible in my project. I wish I owned a logic analyser, would love to see what is going on! For now I'm first going to try if the pwm output signal solves my issues... |
After a multimeter it is maybe the second most important tool to analyze communication between processor and devices. or do a project like these - https://www.instructables.com/Arduinolyzerjs-Turn-your-Arduino-into-a-Logic-Anal/ Newer oscilloscopes often have logic analyzers too, but that is another price range. |
mmm back to the original problem The readAngle() call blocks for a full second, the extra decimals do not provide more insight (yet). Can you adjust your code to void loop()
{
uint32_t start = micros();
rEncoderRaw = rAs5600.readAngle();
uint32_t duration = micros() - start;
if (duration > 1000)
{
Serial.print(millis());
Serial.println("\t");
Serial.println(duration);
}
// process measurement
} And post a log, What I hope to see is that the blocking call happens e.g. every X seconds. |
I am more confused than before. Here is a log, but I think it's irrelevant, I'll explain below:
To clarify some more about my setup: I am outputting two pwm signals to a motor controller, and controlling the motor speed with a remote that connects over ESP-NOW. I only realize (or was it perhaps this test session only?) that the glitch only happens in one of the two directions of the motor, when the sensor spins clockwise. This suggests to me that there is something different going on altogether. Despite using In the end of the test, the ESP froze up completely. The motor kept spinning, no more output came to the serial (I was outputting other stuff too at regular intervals, which I removed from the log above)... I let it run for a minute and then shut off the power. So this of course convinced me that there must be something else really odd with my code, and that the tests I had done earlier must have been misleading, and that I should write a more minimal version of my script for testing... But then I figured I could replace my pwm signals with some physical switches, and the same thing happened! When I sent pwm signals to the now disconnected pins, the motor reading would not get stuck. When the motor was spinning clockwise (not controlled by the ESP), there was a high likelihood that the reading got stuck. So it's the actual physical spinning of the magnet that causes this issue somehow? Is it not designed to rotate that fast? I am so confused now. |
Its getting late here, so a short response for now. The primary function of the sensor is to determine the orientation. Derived from that comes angular velocity. |
I will need to check the datasheet if it mentions measuring rpm. (Coming week) |
Think I found a possible cause here If this is the cause you should check the connection
|
https://forum.arduino.cc/t/arduino-ide-esp32-i2c-timeout-problem/1040744/14 More discussion about it. |
What might be part of a solution is add an error check in readReg uint8_t AS5600::readReg(uint8_t reg)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_error = _wire->endTransmission();
If (_error != 0) return 0; <<<<<<<<<
_wire->requestFrom(_address, (uint8_t)1);
uint8_t _data = _wire->read();
return _data;
} Dont know if it catch errors before the timeout sets in. |
idem in uint16_t AS5600::readReg2(uint8_t reg)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_error = _wire->endTransmission();
If (_error != 0) return 0;. <<<<<<<<<
_wire->requestFrom(_address, (uint8_t)2);
uint16_t _data = _wire->read();
_data <<= 8;
_data += _wire->read();
return _data;
} in case of error the value 0 is consistent over both readReg() and readReg2() |
furthermore one need patching of the functions calling readReg() to verify if a 0 return indicates error or not. |
Note: Recalled this one - RobTillaart/PCF8575#20 |
A check with isConnected() might also be a workaround. (I have no test setup to verify) void loop()
{
if (rAs5600.isConnected() == false)
{
Serial.println("Connection problem!");
}
else
{
uint32_t start = micros();
rEncoderRaw = rAs5600.readAngle();
uint32_t duration = micros() - start;
if (duration > 1500)
{
Serial.print(millis());
Serial.println("\t");
Serial.println(duration);
}
// process measurement
}
} |
Thanks so much for diving into this so thoroughly! This is incredibly helpful. You found the issue! Of course, my breadboard setup with the vibrating motor, that makes so much sense that the connection fails every now and then at certain motor frequencies. Sadly, we don't have a solution yet. I mean, I will have a solution for my project, which is that in the end all will be wired up properly (and I might still use PWM instead of i2c just to be safe). However, the two proposed solutions did sadly not work. I modified the library as you recommended, and I can report that when the esp times out it still returns data, not a 0. |
When it does catch an error and returns 0 (which it also does sometimes even when it checked for |
Thanks for doing the tests. So conclusion is that the problem is (1) outside the library scope, and (2) the library cannot fix it as far as we know. (although I am still interested when a working solution pops up) |
I agree! Thanks so much for your time, and I'll let you know if I learn more. |
Hi, thanks so much for this library!
As you mentioned "Please share your experiences.", I figured I post here about an issue I'm having.
Every now and then (about once every half minute on average) the reading code blocks and stops for 1002ms.
I put this in my loop:
And it outputs 1002 every now and then.
This is especially problematic as my sensor is on a shaft that spins up to about 3800rpm, and multiple revolutions may pass in this 1 second so I have lost track of the amount of full revolutions it has made.
I am using the sensor on a wiper motor, from this tutorial: https://hackaday.io/project/187675-strong-servo-motor-with-a-wiper-motor
And the code runs on an ESP32.
I am clueless why
readAngle()
times out, nor do I have any idea on how to reduce the timeout time.I will attempt to solve this issue by switching to pwm output, as suggested to me on the Arduino discord, but perhaps someone can look into this to help others in the future!
Thanks
The text was updated successfully, but these errors were encountered: