-
Notifications
You must be signed in to change notification settings - Fork 215
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
ADC raw values calibration #555
Conversation
@katyo Thank you very much for working on this, is it something I can help you at this stage? |
@JurajSadel, |
d53f1ce
to
464e46a
Compare
054e556
to
1236249
Compare
I know my opinion here isn't very important, but I'm pretty happy with where this is heading. From a pure design standpoint, I would be happier if the algorithms weren't tied to the efuses, but having calibration coupled to the ADCs here isn't bad either. I am slightly worried about the hardcoded constants in curve fitting - how confident can we be that a single set of constants work well across different production runs? |
@bugadani |
b244042
to
d700f09
Compare
Now this PR uses efuse fields access from #567. |
d700f09
to
4edaa65
Compare
Because #567 is merged I rebased this pr and mark it ready for review. |
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.
Thank you very much for working on this!
I tried it, the C3 is working fine!
C6 example (adc_cal
) is panicking for me with
!! A panic occured in 'C:\Users\JurajSadel\rust_test\esp-hal\esp-hal-common\src\analog\adc\cal_line.rs', at line 34, column 46
PanicInfo {
payload: Any { .. },
message: Some(
No reference point V1 found in efuse,
),
location: Location {
file: "C:\\Users\\JurajSadel\\rust_test\\esp-hal\\esp-hal-common\\src\\analog\\adc\\cal_line.rs",
line: 34,
col: 46,
},
can_unwind: true,
}
Backtrace:
No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)
On C2, I think the voltage values are not correct (compared with my toy voltmeter and would be nice if someone could give it a try) and I couldn't compare it with the ESP-IDF because of revision mismatch.
C2 and C6 have a bunch of unused constants warnings, would be nice to clean them as well
062884e
to
f48ddeb
Compare
@JurajSadel Could you test it again? |
I've confirmed that the examples build and run successfully on the C2, C3, and C6. The values for the C2 and C6 looked correct, however for me the C3 was reporting closer to 2.8V. Other than that seems good, though. |
58af83a
to
49abd51
Compare
I just tried it and it works fine for me on C2 and C3. However C6 crashes in development mode with this
And in release-mode it certainly shows weird values because of this |
@bjoernQ Looks strange. Seems let gain = ((mv as u32 * GAIN_SCALE * 2 / code as u32 + 1) * 4096 / atten.ref_mv() as u32 + 1) / 2; May be calibration data is missing (or version check failed) @bjoernQ Cound you give me a values which return |
Maybe adding some debug or trace logs might help identifying what is going on here. We already have the |
@elpiel The fact is that ADC input impedance on Espressif SoCs relatively low compared to many other MCUs (KOhms not MOhms). |
Testing on the Olimex board with soldered jumpers for the battery meassurement on GPIO 3 indeed shows good results! On the embassy project I still get a panic but I will check whether this is because of unhappy embassy crate versions |
abf5dba
to
d26c95a
Compare
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 would like to see the eFuse calibration versions (I commented on a few, but not all) named (a plain 1
is a bit confusing to read), but apart from that, this PR is in a really promising state.
I can see a few grammar issues (mine is probably incorrect, too!), and a few comments that look like they were copied from C or written to explain the C code during development. Really nothing major.
It would be nice if this PR could be merged in the near future 🙏
pub fn get_rtc_calib_version() -> u8 { | ||
let (major, _minor) = Self::get_block_version(); | ||
if major == 0 { | ||
1 |
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.
This 1
needs to be a named constant IMO.
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 would like avoid introduce new constants.
Ok, I'll think about it.
pub fn get_rtc_calib_init_code(_unit: u8, atten: Attenuation) -> Option<u16> { | ||
let version = Self::get_rtc_calib_version(); | ||
|
||
if version != 1 { |
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.
This 1
needs to be the same constant as above, I think.
pub fn get_rtc_calib_cal_code(_unit: u8, atten: Attenuation) -> Option<u16> { | ||
let version = Self::get_rtc_calib_version(); | ||
|
||
if version != 1 { |
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.
Same here
pub fn get_rtc_calib_cal_code(_unit: u8, atten: Attenuation) -> Option<u16> { | ||
let version = Self::get_rtc_calib_version(); | ||
|
||
if version != 1 { |
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.
Version here should also be replaced by a const
0039905
to
3f0e414
Compare
I just want to say that I'm working on implementing this PR for the S3, just so others don't waste their time on that :) I'll post the results once this one gets merged. |
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.
After thinking some more, I don't think the consts are that big of a deal, we can always reference the ESP-IDF code to actually understand what's going on.
I think a quick rebase on main and this should be good to go from my perspective :).
Honestly, I think the Buuuuut I also don't want to delay the PR 🫣 |
- `AdcCalScheme<ADCI>` implemented for each calibration scheme (basic, linear, curved) - `AdcCalEfuse` implemented for each ADC unit to get calibration data from efuse bits
Basic calibration is related to setting some initial bias value to ADC unit. Such values usually is stored in efuse bit fields but also can be measured in runtime by connecting ADC input to ground internally.
This scheme also includes basic calibration and implements gain correction based on reference point. Reference point is a pair of reference voltage and corresponding mean raw ADC value. Such raw values usually is stored in efuse bit fields for each supported attenuation. Possibly it also can be measured in runtime by connecting ADC to reference voltage internally.
This scheme also includes basic and linear and implements final polynomial error correction.
This example uses line fitting calibration scheme by default. It periodically prints both raw measured value and computed millivolts.
This example uses curve fitting calibration scheme by default. It periodically prints both raw measured value and computed millivolts.
This example uses curve fitting calibration scheme by default. It periodically prints both raw measured value and computed millivolts.
3f0e414
to
d2e2816
Compare
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 think we could introduce some new constants here, as others have suggested, but in the interest of getting this PR merged I'm gonna say LGTM and we can come back to it at a later date. I also noticed that the H2 is missing from this, but again that can wait. I will create an issue to remind us, and may end up just tackling that myself.
Thanks for all your hard work on this, will be great to actually be able to use our ADCs now! 😁
@jessebraham Because esp-idf still does not support calibration for H2 so I don't know how we can add support for it just now. |
* adc_cal: c2: Add efuse functions for reading calibration * adc_cal: c3: Add efuse functions for reading calibration * adc_cal: c6: Add efuse functions for reading calibration * adc_cal: Add extra traits to support calibration - `AdcCalScheme<ADCI>` implemented for each calibration scheme (basic, linear, curved) - `AdcCalEfuse` implemented for each ADC unit to get calibration data from efuse bits * adc_cal: Add basic ADC calibration scheme Basic calibration is related to setting some initial bias value to ADC unit. Such values usually is stored in efuse bit fields but also can be measured in runtime by connecting ADC input to ground internally. * adc_cal: Add line fitting ADC calibration scheme This scheme also includes basic calibration and implements gain correction based on reference point. Reference point is a pair of reference voltage and corresponding mean raw ADC value. Such raw values usually is stored in efuse bit fields for each supported attenuation. Possibly it also can be measured in runtime by connecting ADC to reference voltage internally. * adc_cal: Add curve fitting ADC calibration scheme This scheme also includes basic and linear and implements final polynomial error correction. * adc_cal: riscv: Add ADC calibration implementation for riscv chips * adc_cal: c2: Add calibrated ADC reading example This example uses line fitting calibration scheme by default. It periodically prints both raw measured value and computed millivolts. * adc_cal: c3: Add calibrated ADC reading example This example uses curve fitting calibration scheme by default. It periodically prints both raw measured value and computed millivolts. * adc_cal: c6: Add calibrated ADC reading example This example uses curve fitting calibration scheme by default. It periodically prints both raw measured value and computed millivolts. * adc_cal: riscv: Add changelog entry for ADC calibration
Based on #550
Related issue #326
This PR implements ADC calibration based on ESP IDF. The following schemes supported:
First two schemes uses factory values stored in efuse fields when it available.
As a fallback a runtime calibration is made by connecting ADC input to ground or reference voltage internally.
Third scheme uses pre-defined polynomial coefficients derived from IDF.
Also applied useful optimizations for runtime calculations and to coefficients representation to reduce operations and avoid division.
NOTE: Currently calibration supported only for riscv chips because I haven't xtensa-based boards for testing, but it will be relatively easy add support for such chips later.
Must
errors
orwarnings
.cargo fmt
was run.CHANGELOG.md
in the proper section.Nice to have