 |
 |
| View previous topic :: View next topic |
| Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 656 Location: Des Moines, Iowa, USA
|
| read_adc ADC_START_ONLY versus ADC_START_AND_READ versus... |
Posted: Tue Feb 03, 2026 4:19 pm |
|
|
I have been inspecting our PIC24 code lately trying to identify anything happening in an interrupt service routine which might conflict with things happening in the main loop.
During this, I came across this:
| Code: | | read_adc (ADC_START_ONLY); |
We have two boards that initialize the ADC like this (instructing it to to one sample):
| Quote: | adc_start_and_read (continually takes readings, this is the default)
adc_start_only (starts the conversion and returns)
adc_read_only (reads last conversion result)
|
Inside a timer interrupt service routine, we read the detector like this:
| Code: | // Read the ADC value.
adc_buffer[g_indexADC++] = read_adc (ADC_READ_ONLY);
// Set the ADC start the next read.
read_adc (ADC_START_ONLY); |
We are reading the last conversion from when the ISR happened last, then telling it to read again.
If I understand the help file, this means our samples are always behind, based on how fast this interrupt service routine is. If we have a 10ms timer, then every reading is what the ADC had 10 ms ago.
That is probably good enough, but wouldn't this be better:
Init with - read_adc (adc_start_and_read )
...then in the timer ISR just do "read_adc (ADC_READ_ONLY)"?
Would this work? Is there a downside, other than maybe using more power (which might be important if this was a battery-powered device)? _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Using: 24FJ256GA106, 24EP256GP202, 24FJ64GA002 and 24FJ1024GA606. |
|
 |
newguy
Joined: 24 Jun 2004 Posts: 1927
|
|
Posted: Tue Feb 03, 2026 10:57 pm |
|
|
Been a while since I've dealt with dsPIC A/D conversion, but if your PIC24 device is similar, from memory the only special quality that the dsPICs had over the PIC18s I normally use was the ability to automatically scan & convert one or more channels and use DMA to grab the samples. Some 8 bit PICs may have that capability now, but I haven't used it.
Given what you describe of the code it appears as though the A/D is being used in a conventional manner: do a conversion when asked. If you look at the A/D settings you'll be able to work out precisely how long a conversion actually takes to complete, and it's likely on the order of us or 10s of us. Depending on how fast you're running your processor this may be only a few clock cycles or may be a relative eternity. I suspect that the code has been structured to avoid the read_adc() function from blocking while a conversion is performed.
Again, from what you've described the code as structured seems "inefficient" from a sample gathering standpoint if the samples are 10ms "out of date" by the time they are actually read and subsequently acted upon. But in the grand scheme of things, does that 10ms matter? I suspect it doesn't.
If, however, it kind of does matter OR you're like me and want to ensure that a sample isn't 10ms old when it's finally acted upon, there's a simple solution: use the INT_AD interrupt. Inside your 10ms timer tick you leave the read_adc(ADC_START_ONLY); command. This ensures that your samples will be absolutely rock solid in the time domain.
Then in your INT_AD isr, you go ahead and read the value of the last conversion and do whatever calculations are necessary, and are presently in the 10ms timer isr.
This approach will only be effective if the number of instruction cycles the A/D actually takes is significant. If it's only a handful there's little downside in blocking while the A/D conversion is performed. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20030
|
|
Posted: Wed Feb 04, 2026 5:25 am |
|
|
No.
The default value is to start the ADC, _wait for the ADC to complete it's
reading_, and then return this. So if you used the default value, your ADC
would delay the exit from the timer routine by the time it takes the
ADC to perform a an acquisition and conversion.
The current approach means it starts the reading and immediately exits
the ISR, leaving the ADC getting on with it's acquisition and reading.
Now a lot depends on how fast the particular ADC is. A lot of the older
ADC's take quite a few mSec to actually do a acquisition, and then perform
the ADC sample. So on these triggering the ADC as you exit the routine,
saves having to wait for this time, and your ADC reading is not 10mSec
ago, but only 10 - (Tacq) ago.
As Jay says, the way to not have to wait for the acquisition and conversion
is to use INT_AD. Trigger the conversion when you want and then perform
the reading when INT_AD triggers. Where this gets really great is that
you could consider triggering the ADC off the timer (a lot of chips allow
this), and then do your current timer interrupt code in the INT_AD routine
with just READ_ONLY, letting the timer then trigger the next reading.
This way you arrive at the ADC handler when the reading is ready for you
with no extra overhead. |
|
 |
allenhuffman
Joined: 17 Jun 2019 Posts: 656 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Feb 04, 2026 8:19 am |
|
|
What about the continuous mode? Doesn't that solve this by having the ADC constantly sampling, so there is always the most recent value available?
Or am I misunderstanding the description -- that call, perhaps, just means "sample and read one time, now"? _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Using: 24FJ256GA106, 24EP256GP202, 24FJ64GA002 and 24FJ1024GA606. |
|
 |
newguy
Joined: 24 Jun 2004 Posts: 1927
|
|
Posted: Wed Feb 04, 2026 8:36 pm |
|
|
| The ordinary read_adc() command is for one sample. The continuous modes require DMA and a deep read of the data sheet. Then often some experimentation too in order to get correct. Out of the realm of read_adc() territory. |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|