-
Notifications
You must be signed in to change notification settings - Fork 2k
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
drivers/bmp180: during init retry getting ID because it may fail #5589
Conversation
Hi @keestux thanks for the PR! Would you try something for me, probably it is interesting in an other context:
b) original code but without compiler optimization (just put I'm referring to issue #5460 |
Interesting, issue #5460. If I had known :-) I blamed my porting work for the Autonomo. It took me three days to get to this point. Read on, it gets interesting. I've tried 4 cases. With and without -O0, with and without the usleep between the write and the read.
In other words, it is the -O0 that makes it fail! And the usleep doesn't make a difference. Yesterday I happen to have tried this myself, also with a 500us sleep. However, if the sleep is done AFTER the read it does help and the problem goes away. I also found out that the BMP device could end up in a failure state, and it takes extra effort to get it out of it. Usually it is enough to keep the reset button pressed for a few seconds. BTW. I was using -O0 to debug the code. That's why I was running into the problem. |
One thing I need to mention is that I am working with a SAMD21 and with a newer set of include files from Atmel (ASF 3.30). That could have influence, but in this case I don't think it does. |
@keestux I'm a bit confused about your results. |
@PeterKietzmann I understand that you are confused. But it is exactly as I described. |
@keestux would you please try the following: add to your Makefile
And compile the application with Have a look at the output of dedicated modules, probably paste them here, and search for the optimization level that was actually used. |
@PeterKietzmann just so you know, I'm using these make commands all the time
Notice that it is not necessary to change the Makefile for a different QUIET setting, nor for CFLAGS_OPT. The ?= is made for that. I use that make command because I want to see compiler flags, optimization level, include dirs, etc). That is also why I know that -Os is the default. So, options (ii) and (iii) are identical. Now to come to your request. I take it that you didn't believe me, and you want me to try this again :-). I understand your suspicion. That why I checked it once again (and again). Guess what? At first, I could get it to fail anymore. WTF? Then I remembered I also enabled ENABLE_DEBUG in auto_init.c. In my setup this seems to be an important factor! Timing? (i) CFLAGS_OPT=-O0, fails (I checked the presence of -O0 on the compiler command). BTW, after it failed with -O0 I had to physically disconnect the BMP and reconnect to make it work again for -Os. Believe me, I went and retried this several times to be sure. Conclusion, to make it fail I need:
|
@keestux sorry, I didn't mean to take you for a fool. Just the behaviour you describe seems so weird :-). One last thing that came to my mind: Could you try to connect external pull-up resistors to the bus lines? Something about 10kOhm. I once notices that the internal pull-ups on the samr21-xplained pro were not enough. I could imagine the there are some signals/flanks on the bus during initialisation which the sensor interprets as (invalid) command. BTW: Have you seen the green lights for restructuring samr21 and samd21?! |
@PeterKietzmann Don't worry. I'm not easily offended :-) I was just trying to be funny. I'm not in a position to do hardware changes. The setup (Autonomo + our TPH board) is used extensively by our (SODAQ) customers. And we use it too. All with Arduino. We haven't seen this bug before. |
For the record, I made several tests with the sensor and it works ok in any cases (with/without ENABLE_DEBUG, with/without the optimisation flag). |
/* Check sensor ID (retry a few times, it may fail at first) */ | ||
char checkid = 0; | ||
for (size_t ix = 0; checkid == 0 && ix < 3; ++ix) { | ||
i2c_write_byte(dev->i2c_dev, BMP180_ADDR, BMP180_REGISTER_ID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
during my tests, I also noticed that this line is not needed one can directly access the ID register with the next line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created #5679. Can you give it a try ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me it does not make a difference. It still fails when building with -O0.
But your changes seems to be correct. With the default -Os it works for me.
BTW. Why didn't you remove
i2c_write_byte(dev->i2c_dev, BMP180_ADDR, (char)BMP180_CALIBRATION_AC1);
It seems useless too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, forget about my last BTW (about leaving out the write_byte). It turns out it is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again.
The above mentioned i2c_write_byte still does not make sense. Why is it needed? I don't think it is. But if I leave it out I'm getting all zeroes for the calibration.
To solve that I need a delay between the BMP180_REGISTER_ID and the BMP180_CALIBRATION_AC1.
Here is a question to you. Can you try the following?
diff --git a/drivers/bmp180/bmp180.c b/drivers/bmp180/bmp180.c
index e772c3a..ad771cc 100644
--- a/drivers/bmp180/bmp180.c
+++ b/drivers/bmp180/bmp180.c
@@ -73,10 +73,10 @@ int bmp180_init(bmp180_t *dev, i2c_t i2c, uint8_t mode)
i2c_release(dev->i2c_dev);
return -1;
}
+ xtimer_usleep(3);
char buffer[22] = {0};
/* Read calibration values, using contiguous register addresses */
- i2c_write_byte(dev->i2c_dev, BMP180_ADDR, (char)BMP180_CALIBRATION_AC1);
if (i2c_read_regs(dev->i2c_dev, BMP180_ADDR, BMP180_CALIBRATION_AC1, buffer, 22) < 0) {
DEBUG("[Error] Cannot read calibration registers.\n");
i2c_release(dev->i2c_dev);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keestux would you report your results in #5679 please? If the delay fixes your problem (and #5679 does not), I would rather merge a solution with a small delay (plus comment) instead of retrying. If @aabadie is nice, he could implement the fix in #5679, you could test it and give your ACK. This would be a bug fixing PR and we could merge it despite of the current feature freeze :-) |
Yes, I confirm that it works. |
This solves a problem I had when testing a RIOT port to a new board (SODAQ Autonomo) in combination with I2C. I connected a SODAQ TPH board.
Somehow the BMP is not ready directly after a reset. I couldn't find anything documented in the BMP datasheet. But retrying it (getting the device ID) seems a harmless solution.