Skip to content

New ADC V2 with Async support #814

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

Open
wants to merge 89 commits into
base: master
Choose a base branch
from
Open

Conversation

rnd-ash
Copy link
Contributor

@rnd-ash rnd-ash commented Jan 23, 2025

Summary

This PR adds a new ADC API, based around a similar system to channels used by EIC and DMA peripherals.

At the moment I'll keep this as a draft PR for feedback whilst I am still finalizing bits and also adding SAMD11/21 support

Features

  • A new settings builder system for configuring the ADC
  • Channels system (Each Analog capable pin has its own channel)
  • Both blocking and Async read support
  • Buffer filling support (Free running continuous mode)
  • CPU temperature reading
  • Internal voltages reading

Progress checklist

  • SAMx51 support
  • SAMx11/21 support
  • Channels API
  • Settings builder (Mostly completed, need to add settings for Vref calibration)
  • Async/Blocking single reads
  • Async/Blocking buffer reads
  • CPU temperature reading (Restricted to primary ADC if applicable to chip)
  • CPU internal voltages reading (Restricted to primary ADC if applicable to chip)

rnd-ash and others added 30 commits January 5, 2025 11:14
Automatically convert pins to correct mode in Channel::with_pins
`wait_flags` and buffered read methods
@rnd-ash rnd-ash requested a review from jbeaurivage March 10, 2025 05:05
@jbeaurivage
Copy link
Contributor

jbeaurivage commented Mar 11, 2025

@rnd-ash, if you're happy with this, I am too. I think you've been doing extensive testing recently. Only two things to get CI green and get this merged:

  • Fix a small clippy lint in calibration/d11.rs (line 44).
  • Fix the pygamer examples

@rnd-ash
Copy link
Contributor Author

rnd-ash commented Mar 12, 2025

I'll be able to fix these next week or this weekend when I'm back in the UK and have access to all my test boards (SAMD21 I need to verify it doesn't read old results in the ADC during sequential reads)

@rnd-ash
Copy link
Contributor Author

rnd-ash commented Mar 19, 2025

@ianrrees @jbeaurivage As far as I am concerned now, this is ready to Merge. If you guys want to do 1 final review feel free.

As discussed with Ian, I fixed the pygamer example my deleting the neopixel examples

Copy link
Contributor

@ianrrees ianrrees left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With stable Rust, I note cargo doc flags several dead links in the documentation, so please do have a look at those and ensure the rendered docs are what you intend.

Thanks for all this work! Looks pretty good.

// The double trigger here is in case the VREF value changed between
// reads, this discards the conversion made just after the VREF changed,
// which the data sheet tells us to do in order to not get a faulty reading
// right after changing VREF value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment - why not have start_conversion() just do one conversion and handle triggering+discarding that faulty reading when VREF is changed?

My concern is that this could be used in settings with tight timing requirements, so probably shouldn't spend time on things that aren't strictly necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ill do some testing tomorrow, since this was to prevent stagnant readings from the ADC when cycling between channels very quickly (Read 1 sample, cycle to another channel,...), but since then, I found the powering down the ADC and powering it up between samples helped, so Ill test without this double trigger and see if the problem is still gone


let adc_settings = Config::new()
.clock_cycles_per_sample(5)
// Overruns if clock divider < 128 in debug mode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we shouldn't re-work the example, so that it's a little more robust - eg maybe just get one sample at a time so that it is impossible to get an overrun scenario. That limitation could motivate using DMA, which I think a lot of practical ADC applications will need to use anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, DMA is my next thing to work on with the ADC generally speaking

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in rnd-ash#10


/// This adjusts the number of ADC clock cycles taken to sample a single
/// sample. The higher this number, the longer it will take the ADC to
/// sample each sample.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the maximum value, and assuming it's not 8b what happens if a config is specified that's over it?

/// * Single accumulation (No averaging or summing)
///
/// ## Additional reading settings by default
/// * Use VDDANA as reference voltage for a full 0.0-3.3V reading
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the implementation actually uses the 1V reference

Copy link
Contributor Author

@rnd-ash rnd-ash Mar 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intvcc1 - VDDANA reference voltage (Refselselect register), but ill modify the comment to show this is the case

@jbeaurivage
Copy link
Contributor

jbeaurivage commented Apr 16, 2025

@rnd-ash, @ianrrees still had a few comments that are worth being addressed. I've fixed a bunch in rnd-ash#10. The only outstanding item that might require more discussion is the handling of the sampling parameters, ie, if we should force users to explicitly specify everything or not.

To simplify things a bit, I suggest that if you want add convenience methods to setup the ADC to a specific number of cycles per sample, it could be done in a follow-up PR.

@jbeaurivage jbeaurivage mentioned this pull request Apr 17, 2025
2 tasks
@ianrrees
Copy link
Contributor

I've been working on an ESP32 based project for a couple weeks now, and TBF it's reinforced my feelings that for things like UARTs (and I'd say ADC/DAC as well - just haven't used them in ESP32), it's really best to make the API explicit about settings where there is no clear default. However, I'm just one person, and I respect that the ESP32 HAL is quite successful, so maybe it's not worth worrying too much about...

@rnd-ash - it would be great to get this merged, what's your feeling about the next steps with it? If changing the config builder is too much of a pain, I'm happy either leaving it as-is or having a crack at it myself if you'd like.

@rnd-ash
Copy link
Contributor Author

rnd-ash commented May 15, 2025

@ianrrees i think we are ready to merge this, just 1 minor bug with the SAMD21's temperature sensor not reading accurately, but I can (For now at least), just disable the cpu temperature function for SAMD21 if it proves to be a blocker.

I have not tested this on a D11 target either, as I don't have one, would it be possible for you to verify functionality?

@ianrrees
Copy link
Contributor

Awesome, thanks! Yep, my next few days are going to be a bit variable in terms of computer time, but will try to get to it soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants