# How can you speed up the ADC on an ATtiny85?

I'm reading input from a camera and trying to reach a fast frame rate. Problem is my ATtiny85 has a pretty slow conversion time (65 - 260 µs Conversion Time). Is there any way to make this faster? I heard that you can set-up a prescaler for the `analogRead()` method by doing the following:

``````#define FASTADC 1

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup()
{
// set prescale to 16
#endif

/*Rest of the code goes here.*/
}
``````

I can't really make sense of the code and I found it on a less then reliable website so I was wondering if any of the gurus on here could let me know if what I'm attempting is possible and if this is the proper way of achieving my goal.

Also, would this also work for the Arduino Mega? I'm currently using it to test and debug my project since the ATtiny84 doesn't have serial output.

• How many bits of precision do you need? You can speed up the conversion at the cost of loosing precision in the lower bits down to 1us/conversion. – bigjosh Jul 7 '16 at 20:21
• Can you explain what bits of precision is? This is my first Arduino Project and first time working with a camera so I'm a little confused on the lingo. – sgmm Jul 7 '16 at 20:25
• The ATTINY ADC normally gives 10 bits of precision- so you get a value between 0 and 2^10 (1024) and each number is different, so (say) 787 (1100010011) is always bigger than 786 (1100010010) even though 787 and 786 only differ by the lowest bit. You can make the ADC go faster, but the bottom bits start to not matter so you can only care about the topmost bits - so in our case if you only had 9 bits of precision then 786 and 787 would be the same (both would be (110001001x where the x means don't know or care). Make sense? – bigjosh Jul 7 '16 at 20:30
• Makes a lot of sense. So when you set a prescaler you are reducing the number of bits used we can get the ADC to be faster but we will have less accuracy. – sgmm Jul 7 '16 at 20:33
• The prescaler just divides the clock that goes into the ADC. So if you start with a 1MHz clock and a prescaler of `/2`, then the lock that goes into the ADC will be 500Khz. The ADC clock (after the prescaller) needs to be 50-200Khz to get all 10 bits of precision, but you can run it up to 1mhz but more of the bottom bits will start being wrong the faster you go. How much precision do you need and how fast you do need samples? – bigjosh Jul 7 '16 at 20:45

The ADCs in the ATtiny85 and ATmega2560 (the chip powering the Arduino Mega 2560) are pretty similar, except for the Mega having more inputs. In particular, the way you set the clock prescaler is the same, namely the bits ADPS2:0 in the register ADCSRA. You could use the same code to set the prescaler on both chips, but you probably don't want to unless your ATtiny is clocked at 16 MHz, like your Mega. I would normally just set the control register to the value I want, rather than touching only a few bits, but that is a matter of personal preference. So, to set the ADC clock of the Mega to 1 MHz, I would

``````ADCSRA = _BV(ADEN)    // enable the ADC
| _BV(ADPS2);  // clock at F_CPU / 16 = 1 MHz
``````

The same code would do the same thing on an ATtiny clocked at 16 MHz. If the ATtiny runs at 8 MHz, I would instead

``````ADCSRA = _BV(ADEN)    // enable the ADC
| _BV(ADPS0);  //     F_CPU / 8 = 1 MHz
``````

If you want to be generic:

``````#if F_CPU >= 12000000
#else
#endif

| ADPS_SETTING;  // clock somewhere near 1 MHz
``````

As bigjosh explained in comments, the prescaler setting is a trade-off between speed and accuracy. I recommend you read the article on the Arduino ADC by Nick Gammon. He did some tests at various speeds which showed that you can get decent results with clock speeds up to 1 MHz, then it becomes pretty bad at 2 MHz and mostly useless beyond. You may want to run the same tests with your particular setup.

Except for the very first conversion, which takes longer, an ADC conversion takes 13 cycles of the ADC clock. If you run that clock at 1 MHz, that is 13 µs per reading. If you get the readings with `analogRead()`, you won't get one reading every 13 µs, because the CPU needs extra time to execute the code you have between successive calls of `analogRead()`. You can save time by having the CPU and the ADC work in parallel, maybe along these lines:

``````ADCSRA |= ADSC;     // start the first conversion
for (int i = 0; i < NB_READINGS; i++) {
• @CrystalPritzker: No. The prescaler sits between the CPU clock and the ADC clock. C.f. section 17.5 of the datasheet. If your CPU runs at 16 MHz (which is the case on the Mega), setting the prescaler to 2 would clock your ADC at 8 MHz, way too fast. The Arduino core sets it to 128, which clocks the ADC at 125 kHz, which is fine but too slow for your needs. I suggest you clock your ADC at 1 MHz, which means setting the prescaler to 16 on the Mega (I do not know `F_CPU` on your Tiny). – Edgar Bonet Jul 8 '16 at 15:52