-
Notifications
You must be signed in to change notification settings - Fork 171
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
Broken ADC readings on esp32c3 with read_raw()
and read()
#468
Comments
On the esp32c3, with 0 DB attenuation (that you are using) applying 900mV is already out of range. It is difficult for me to dig up a proof from the esp32c3 Technical Reference Manual, but it is documented clearly here (i.e., for the old/legacy 4.4.X ADC driver, but it uses the same hardware after all). It seems to me that you are expecting out-of-range voltages to "max out" (in your wording) to a returned raw value of 4095, but isn't this just a speculation? Also, without applying calibration (with Why don't you first try with a voltage value which is in-range for your chosen attenuation (or lack thereof)? I.e. 500mV or so with esp32c3 and 0DB atten? Otherwise, and with regards to bugs, while it is always possible that there is a bug in the Rust wrappers, with |
I investigated further. I'm not even sure this is a bug within the libs, could also be a miscompilation. I certainly can't see how such behaviour could be caused by my code or my setup, I'm using no unsafe code anywhere and doing nothing too special. Currently I have the following setup:
Depending on the exact structure of my code I still see completely wrong values, reproducible. For example, I can tweak the code to either read |
There is one bug in the driver I just noticed, which is that it does not even bother to release the internal ESP IDF calibration handle on driver drop. This I'll fix, but it is very unlikely that you are affected by that, as you are not dropping the driver in your test anyway. And it is more of a memory leak issue. I am also very pessimistic that this could be a code generation issue, because the riscv32imc targets live upstream in Rust/LLVM, and they are pretty popular. Also you don't use FP emulation, which is one place where compiler output might create issues. I don't have brilliant ideas, but how about you just flash the native C ESP IDF ADC oneshot example? You need to download ESP IDF and everything, but at least that way you will eliminate all of the Rust glue code and your potential worries about miscompilation (on the LLVM level, that is; GCC would still be in the game). You can also play with the C example to see if it also returns wrong values when you push it (as in taking oneshot readings in a rapid sequence, as you are doing in the Rust code). If you feel lazy w.r.t. going down the C route, you can also re-create the example (or a minimal part of it - without the cleanup logic) by using raw calls into |
Heh. Look here. They claim the issue is fixed, but the original poster never replied to confirm. Maybe it is just that the ESP IDF ADC oneshot driver is simply unreliable in the presence of WiFi? If that's the case you can of course always do a rapid sequence of readings (say - 10 or 16), and then remove the outliers from the set, and assume the rest represent correct values. Lame workaround, I know, but that might be the only option with WiFi turned on, if the original bug is not really fixed yet. |
(The above bug is esp32 related, not esp32c3, but who knows, maybe they have something similar going on with the c3 as well.) |
read_raw()
read_raw()
and read()
One more suggestion: can you change from pin0 to pin2? (UPDATE: in the C example they use ADC channels 2 and 3 which is gpio2 and gpio3...) |
Test setup
Problem
When I use
read_raw()
in a loop to collect 16 samples and then averaging over thoseI get unreliable results. The applied voltage of 0.9V seems to max out the ADC since I see no fluctuation in the values anymore. However, the value I get is not
4095
, but instead3839
, which converts to binary0b111011111111
. If I slightly change the code, and, for example log the individual sub-samples in thefor
-loop, or log thesamples
array, or add a small 10ms sleep to the for loop, then I suddenly see the correct reading of4095
.The
read()
function, however, seems to behave correctly, returning reliable and accurate voltage readings. A user in IRC suggested, this might be some timing issue, that is magically right in read() all the time, but in my read_raw() setup sometimes is wrong.If you need any more information, please ask.
The text was updated successfully, but these errors were encountered: