Replies: 7 comments 2 replies
-
|
I have found a reference to an 'SPD' bit in the ADCSRC register that says: 0= ADC low speed conversion mode 1= ADC high speed conversion mode, only used for analog input with low resistance Though there's no other reference to this setting anywhere, what speeds it supports, or what an appropriate resistance is. Setting this bit has no impact on my results, though. I am using 100k pots between Vcc and GND, so I don't know if they qualify as 'low resistance' |
Beta Was this translation helpful? Give feedback.
-
|
Just an idea : does it work better if you don't use the automatic triggering ?
|
Beta Was this translation helpful? Give feedback.
-
|
Hmm - you might be on to something. I was first starting to optimize the ADC functions yesterday, and the first thing I tried was to update the prescaler, and use the analogRead() routines (with no interrupt or triggers). This worked up to 8MHz (I think, though, I'm less than certain about it, I never did benchmark it to see if it was actually doing what I expected). I'll think about this, and maybe tweak my ISR a bit. Maybe update the ADMUX at the very end of the function |
Beta Was this translation helpful? Give feedback.
-
|
Yeah - you're definitely on to something. With an prescaler of 8, I'm not actually getting a 'garbage' result, it's reading a good value, just from the wrong pot! With a slower prescaler, it reads the expected pot. Definitely a timing thing somewhere that I need to sort. I'm still trying to understand how I'm supposed to do this: "Note that the most simple way is to change channels after conversion is complete." - to me, that means that it's OK to update the ADMUX in the ISR, because we're only ever IN the ISR "after a conversion has been complete." But that does not seem to be the case. Further experimentation is called for. |
Beta Was this translation helpful? Give feedback.
-
Is it possible that a new interruption occurs before the end of an ISR ? I don't remember if it was on an AVR or onto an other MCU/CPU or onto an event based programming language, but I had a similar issue once, and the solution was to temporarily disable interruptions when entering the ISR, and to re-enable them at the end of the ISR. |
Beta Was this translation helpful? Give feedback.
-
|
I don't think that's the problem, it doesn't seem to be missing any of the pots that I have connected. Does AVR even support nested interrupts? Although, I might try disabling interrupts in the ISR, and see what happens. EDIT: done. Doesn't have any noticeable impact. Some math here says: at a 32MHz CPU, with a prescaler of 8 I have a 4MHz ADC clock. According to the datasheet, it takes 15 ADC cycles to complete a conversion. That's 15 cycles * 8 prescaler = 120 CPU cycles to get through my ISR before the next interrupt is triggered. That's not a ton, although my ISR I think should squeak in under that; I'd need to look at the assembly, but gut feel is that I should be ok. [EDIT: Maybe not. Most the ISR is lightweight, but scanning the buttons in the final 'case:' uses digitalRead(), potentially 7 times. IIRC, digitalRead() costs about 50 cycles. Still, this is the last 'case' before it disables the ADC, so, I'd guess it's not causing problems. Even so, I'll whip up a 'fastread' macro to read the registers directly., I hate spending too much time inside ISR's :)] Thanks, food for thought |
Beta Was this translation helpful? Give feedback.
-
|
On classic ATmega MCUs the ADC clock is recommended to stay within 125–200 kHz for best accuracy. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I've been playing with the ADC on my board recently, and am getting some results that don't align with what the datasheet suggests.
The datasheet says "By default, the successive approximation circuitry requires an input clock frequency between 300kHz and@ 3MHz to get maximum resolution. If a lower conversion accurancy than 12 bits is needed, the input clock@ frequency to the ADC can be higher than 3MHz to get a higher sample rate."
Any time I go past 500kHz (prescaler of 64 for F_CPU of 32MHz), the ADC just returns garbage (a fairly steady value of ~2048, regardless of the actual voltage applied to the pin). With a prescaler set to 64 (or 128), I get a good reading, from 0-4095.
See here: https://github.com/prosper00/arpeggiator/tree/master - Specifically, setupADC() and ISR(ADC_Vect) functions in the .ino file. What they do is setup the ADC to iteratively scan (in an interrupt) each pin I'm interested in, and then reset. This is way more efficient than using the (blocking) analogRead() function, and lets my code do other stuff while asynchronously scanning user inputs.
I don't REALLY care about the ADC speed, even at it's slowest setting, it more than fast enough. Still, I find it odd that it's not performing like the datasheet claims.
Beta Was this translation helpful? Give feedback.
All reactions