I needed to watch multiple AD inputs but didn't want to wait for each reading when I needed them. I looked into the Free Running mode but that only watches one input at a time. This is what I came up with:
This works by using the ADC_vect ISR. A conversion is started and when it finishes, the ISR fires, advances to the next input, and starts a new conversion. Very simple really.
This however leaves out how to access and store the values. They could easily be stored in a private array and then pulled when needed, eliminating the delay waiting for the conversion to finish. This code however, goes one step further. The "ADC_result" array is actually an array of pointers to where the values should be stored. This lets the ADC put the read values directly into registers in use by the main loop. A NULL ptr indicates that that value should be skipped (eliminating unused conversions), letting this system work for any combination of AD pins that are in use.
How to use: (in main init)
int8_t topSensor; int8_t motorSensor; int8_t voltage; ADC_init(); ADC_result = &voltage; ADC_result = &topSensor; ADC_result = &motorSensor; ADC_startScan();
Now, in the main loop we can just read values from "voltage", "topSensor", and "motorSensor". They will always have the most recently read value in them.
Attached are the source and header files.
- Starting a scan before assigning the pointers will do nothing
- Stopping the scan before NULLing last ptr will get AVR stuck in the ISR
- Care must be taken when using values in mail loop as they can be changed by ISR
- Don't forget to enable interrupts
- I've had issues getting good values from the A/D with no prescaler. Values seem to get stuck and you get very bad data.