Go Down

Topic: code size (Read 3147 times) previous topic - next topic

ardnut

It seems the fasted conversion rate would be 12.8MHz / 64 = 200kHz giving ADC conversion time of 65us : 15.4 kS/s




westfw

Quote
over 1k to blink a LED ?!

Old but still appropriate analysis here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283329855
(Arduino has featureitis.  An empty sketch has grown about 50% since that message.)

Quote
A2D timing

As for A2D conversion...  A successive approximation A2D converter theoretically gives you 1 bit of resolution per clock cycle.  That is, after one clock, you know whether the input is over or under Vref/2, which is exactly the same as 1-bit resolution A2D conversions.  However, I would not expect an A2D "peripheral" buried inside a microcontroller to allow the SA shift register intermediate values to be accessed by the CPU; probably that is transferred into CPU-readable registers at the end of the conversion.

The variable timing of A2D conversion probably comes from this part of the datasheet: "By default, the successive approximation circuitry requires an input clock frequency between 50 kHz and 200 kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200 kHz to get a higher sample rate."  So you can set the clock fast enough to get the 13uS conversion, but your accuracy will suffer.

Quote
dedicated clock domain.

A dedicated clock domain is not the same as a completely separate clock.  If you look at the section describing the system clock (sec 8 in my manual), you can see that the A2D clock is derived from the same system clock as the CPU clock (it's just derived separately, so you can turn of CPU clock while leaving the A2D clock running.)


Quote
before insulting people

There's been a rash of recent postings by people with "experience" showing up and using their first few postings to complain about things they don't like.  "The debugging sucks."  "The IDE needs a complete rewrite."  "Where's my C++11?"  "The code is too big."  "The functions are too slow."  "The board and shield design is lousy."  "Arduino should use a more powerful CPU."  "The Due is late."  "The documentation doesn't include the full C/C++ standard includes and libraries."  "I need an Arduino core for <processor that has never been supported.>"  "Raspberry Pi looks a lot better." (no, not all of these are you...)

It gets tiring.  It's not that none of these complaints have any merit.  It just that most of them have been discussed over and over again, and are relatively orthogonal to the "purpose" of Arduino anyway.  It would be nice if new users, especially the ones with existing experience, took a while to look around and pick up the style of discussion, FAQs, and ... "the spirit of Arduino" before launching into complaints...  Detailed questions on the operation of the A2D converter, beyond the AnalogRead() function, are more appropriate to AVRFreaks (where they're even less ... tolerant.)


ardnut

Quote
Bear in mind the datasheet quotes 2 bits of error even at 200 kHz.


Well you never get accuracy = resolution with ADC ;)

2 LSB of error still leaves 9bit accuracy , which I stated way back near the beginning of this discussion.

That's still 0.125 % , not bad.

Nick Gammon

In the interests of working out how inaccurate the faster conversion would be, I set up a test measuring various voltages with the 125 kHz ADC clock and the 250 kHz clock. The results are:

Code: [Select]

Slow: 1016
Volts: 4.96
Time taken: 112
Fast: 1016
Volts: 4.96
Time taken: 60

Slow: 1016
Volts: 4.96
Time taken: 112
Fast: 1016
Volts: 4.96
Time taken: 60

Slow: 813
Volts: 3.97
Time taken: 112
Fast: 813
Volts: 3.97
Time taken: 60

Slow: 812
Volts: 3.96
Time taken: 112
Fast: 812
Volts: 3.96
Time taken: 60

Slow: 611
Volts: 2.98
Time taken: 112
Fast: 611
Volts: 2.98
Time taken: 60

Slow: 611
Volts: 2.98
Time taken: 112
Fast: 610
Volts: 2.98
Time taken: 60

Slow: 405
Volts: 1.98
Time taken: 112
Fast: 405
Volts: 1.98
Time taken: 60

Slow: 405
Volts: 1.98
Time taken: 112
Fast: 405
Volts: 1.98
Time taken: 60

Slow: 202
Volts: 0.99
Time taken: 112
Fast: 201
Volts: 0.98
Time taken: 60

Slow: 202
Volts: 0.99
Time taken: 112
Fast: 202
Volts: 0.99
Time taken: 60

Slow: 0
Volts: 0.00
Time taken: 112
Fast: 0
Volts: 0.00
Time taken: 60

Slow: 0
Volts: 0.00
Time taken: 112
Fast: 0
Volts: 0.00
Time taken: 60


Two samples per voltage from 0 to 5V in steps of 1V. There only seems to be a difference of 1 unit maximum.

Code:

Code: [Select]

// Example of taking ADC readings at different ADC clock frequencies
// Author: Nick Gammon
// Date: 13 July 2012

#include <avr/sleep.h>

const byte adcPin = 0;
const byte switchPin = 8;

volatile int adcReading;
volatile boolean adcDone;
boolean adcStarted;
boolean slow;
unsigned long startTime;
volatile unsigned long finish;

void setup ()
{
  Serial.begin (115200);
  // set the analog reference (high two bits of ADMUX) and select the
  // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
  // to 0 (the default).
  ADMUX = _BV (REFS0) | (adcPin & 0x07);

  pinMode (switchPin, INPUT);
  digitalWrite (switchPin, HIGH);
}  // end of setup

// ADC complete ISR
ISR (ADC_vect)
  {
  byte low, high;
  finish = micros ();

  // we have to read ADCL first; doing so locks both ADCL
  // and ADCH until ADCH is read.  reading ADCL second would
  // cause the results of each conversion to be discarded,
  // as ADCL and ADCH would be locked when it completed.
  low = ADCL;
  high = ADCH;

  adcReading = (high << 8) | low;
  adcDone = true;
  }  // end of ADC_vect

void loop ()
{
  // if last reading finished, process it
  if (adcDone)
    {
    adcStarted = false;
    ADCSRA &= ~ _BV (ADIE);  // no more interrupts for now

    // do something with the reading, for example, print it
    Serial.println (adcReading);
    float volts = (float) adcReading / 1024.0 * 5.0;
    Serial.print ("Volts: ");
    Serial.println (volts, 2);
    Serial.print ("Time taken: ");
    Serial.println (finish - startTime, DEC);
    delay (500);

    if (!slow)
      Serial.println ();
     
    adcDone = false;
    }
   
  // if we aren't taking a reading, start a new one
  if (!adcStarted)
    {
     
    if (slow)
      {
      slow = false;
      Serial.print ("Fast: "); 
      delay (100);  // let that print
      ADCSRA &= ~ _BV (ADPS0);  // 250 kHz clock
      }
    else
      {
      // no switch pressed? do nothing
      if (digitalRead (switchPin) != LOW) 
        return;
       
      slow = true;
      Serial.print ("Slow: "); 
      delay (100);  // let that print
      ADCSRA |= _BV (ADPS0);  // 125 kHz clock
      } // not just done slow
   
    // do a few reads to prime the damned thing
    for (byte i = 0; i < 5; i++)
      analogRead (adcPin);
     
    adcStarted = true;
    startTime = micros ();
    // start the conversion
    ADCSRA |= _BV (ADSC) | _BV (ADIE) | _BV (ADIF);
   
//   set_sleep_mode (SLEEP_MODE_ADC);    // sleep during sample
//   sleep_mode ();

    }   // not taking reading

  // do other stuff here

}  // end of loop


I had to take the sleep out because it also stopped the micros() clock.  I wanted the clock there to be certain I was in fact doing the faster ADC conversion.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

ardnut

Nick, thanks for the openmusic links, that was very helpful indeed. I'm not doing audio but that is the sort of sampling frequencies I am looking for.

http://www.openmusiclabs.com/wp/wp-content/uploads/2012/01/adc_freq_test1.jpg

I had pretty much concluded that Arduino would be too slow for what I needed but since the effects of stepping outside the spec are a lot less dramtic than one would have to assume without specific information, it looks like it will fit the bill.

thanks.

Go Up