RMT not working while GPIO is
Rimco opened this issue · 13 comments
For the DS18B20 library + example, the RMT driver is unable to find any devices. Switching to the GPIO driver makes it work, but I would like to make use of RMT for the stability.
My environment:
Heltec ESP32 LoRa V2
1x DS18B20 on GPIO23
Code from the example repository with owb aee423c and ds18b20 4c76db4a34634aa1a2dc67a60345072590375012
Replacing:
owb_rmt_driver_info rmt_driver_info;
owb = owb_rmt_initialize(&rmt_driver_info, GPIO_DS18B20_0, RMT_CHANNEL_0, RMT_CHANNEL_1);
With
owb_gpio_driver_info gpio_driver_info;
owb = owb_gpio_initialize(&gpio_driver_info, GPIO_DS18B20_0);
Is all needed to make it work.
Not sure if it may be related, but I did also notice that the DS18B20 library in both cases thinks there is some parasitic sensor, while there is none. The attached sensor is supplied externally.
I also noticed recent commits, so could it be I should take a older/more stable version?
@Rimco thanks for reporting. Which version of the ESP IDF are you using? There's currently a known issue with recent versions, but it has been tested and shown to work with v3.3 and v4.1beta. v4.2 (unreleased) and master are definitely broken.
Please avoid using the GPIO driver as it is deprecated and will be removed soon. It is unreliable and no longer fully supported.
The root cause is related to initialisation of the RMT peripheral, and the same problem causes mis-detection of the parasite power mode. Once the issue is fixed this symptom should disappear.
Please see: DavidAntliff/esp32-ds18b20-example#19
See also espressif/esp-idf#5237
You can try reverting to an older version if you like - would be interesting to hear back - but if you're using a recent IDF version it will probably have the same issue. A fix (to my code) is in the works.
@Rimco please try the master branch of this component (included by the master branch of the ds18b20 example) - I am hopeful that your issue has been fixed. Please let me know.
Thanks @DavidAntliff,
I overlooked the issue already being open in the ds18b20 repository.
Your fixes seem to match the problems I noticed wrt the uninitialized variables, although I didn't think that was related to the RMT problem. I did get a backtrace due to it, pointing at the parasitic power using an uninitialized GPIO number unless you explicitly enable/disable it. I ran into this because I got rid of the broken parasitic power detection, so I would not enable/disable it at all.
I will try to use the latest versions and report back. I recently started with ESP-IDF and apparently used the master (4.2 alpha let's say) from a few days ago. If your fix does not work I will try 4.1, who knows which other bugs I have gotten for free with this cutting-edge version ;)
Latest version is working with the example code.
Thank you for testing!
pointing at the parasitic power using an uninitialized GPIO number unless you explicitly enable/disable it.
Hmm, this could still be an issue - do you have any more info on this?
The backtrace ended up in owb.c:737:
if (bus->use_parasitic_power && bus->strong_pullup_gpio != GPIO_NUM_NC)
{
gpio_set_level(bus->strong_pullup_gpio, enable ? 1 : 0);
I think the uninitialized variables ended to be:
use_parasitic_power = true;
strong_pullup_gpio = random number >= 0
Because random number wasn't equal to GPIO_NUM_NC, it would try to access an non existent one.
You may want to add strong_pullup_gpio < GPIO_NUM_MAX, but solving the uninitialized variables is of course better.
Btw, I'm using your library in a C++ environment and the compiler started complaining in my C++ wrapper that = {0} would not be sufficient to initialize everything, but = {} was. I'm not that used to plain C structs anymore, but maybe something you want to verify.
Ok, thank you, I'll reopen this issue in the meantime so I don't forget about this.
In C, struct foo f = {0}
guarantees that the entire structure will be initialized to zero values, because the standard requires that if one or more fields are initialized, all fields not mentioned must also be initialized to zero. Since a C struct must have at least one field, and all types can be set to zero, this always works.
In C++11, you can use foo f = {}
instead, which is called zero initialization. However for foo f = {0}
there's also copy initialization (before C++11), list initialization (C++11) and aggregate initialization (before and after C++11). It gets complicated fast.
https://en.cppreference.com/w/cpp/language/aggregate_initialization
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.
So the first field will be initialised to zero, and then the rest will be value-initialized, which because no value is specified, will result in zero-initialization.
See Explanation through to Point 4 here: https://en.cppreference.com/w/cpp/language/value_initialization
TL;DR: it should be ok, your C++ compiler might just be warning you that the initialization isn't explicit, so might not do what you expect, if you were expecting something other than zero.
Oddly I can't find any specific discussion online of using that pattern in both C & C++ code. What's the exact text emitted by the compiler when it displays this warning? Maybe I can use that to search for a discussion.
Ah, this was with the GPIO driver, not the RMT one, is that right?
I've fixed the uninitialised GPIO when using the GPIO driver: DavidAntliff/esp32-ds18b20-example#21
As far as I can tell, the RMT driver is OK as long as owb_rmt_initialize
is called.
That one was indeed with the GPIO version, before you did any kind of fixes wrt the uninitialized variables.