I know it's been a while but I wanted to finally post this. This is an updated version of my previous "tutorial". That thread however has gotten too long and I don't want to go and completely change my original post. I'm hoping to address all the concerns that came up there...
While this is posted in the "AVR Tutorials" forum, it is not a tutorial on using this code. This, as was the previous version, is a description of a more advanced way to scan all of the ADC inputs in the background and I have included my implementation only as an example. I cannot make any commitment to maintain or help anyone with this software.
This software is provided completely without warranty. It is an example implementation of an advanced A/D converter scanner. I take no responsibility for it's function or helping other use it.
- 10 bit!
- not pointer based
I originally used pointers to variables from the main loop to combine the need for marking which lines were enabled (non-null ptr) and to get the data out. This however led to needing a second variable to hold a latched value for the main loop because otherwise it would change during the loop.
So when I extended this to 10-bit I decided to change the structure. Now I store a byte who's bits are the enabled lines and then an array of current values.
// Initialization ADC_init(); ADC_setEnabled(0xff); // Enable all the pins sei(); ADC_startScan(); uint16_t motorPosition, armPosition; // Retrieve values motorPosition = ADC_get(0); // returns most recent value of ADC0 armPosition = ADC_get(1); // returns " " ADC1 ...
I have not written the software for this yet but there is a simple way to virtually increase the ADC's resolution:
I noticed while using this code that the ADC is actually taking ~80 measurements per 100Hz main loop (128 ADC prescaler, 16Mhz F_CPU). If instead of always storing the last read value, we stored the sum of the last 8 values read. Then, you effectively get a 13-bit ADC! :-D
A similar implementation stores the current sum and then returns the count with the sum for variable (maximum) resolution every main loop.
A more advanced implementation of the above that we've been playing with in excel is to store a running weighted average. Then you don't need to store the last eight values. It would also be simple to implement a velocity estimate at this low level.
I have since re-written these as a c++ class based adc, similar to the classes used in Arduino but for "power users". I don't like the complete abstraction from the underlying hardware (ie. pin #0-32 over PORT[A-G][0-7]) but I do like the c++ syntax and abstraction. It is not complete and completely untested. I hope to release is on AVRFreaks eventually.
Another place for expansion is to support more MUX settings. We currently only support individual reading of the inputs. It would be nice to support differential measurements, the internal bandgap, etc.