Skip to main content
Bumped by Community user
edited title
Link
Dave X
  • 2.3k
  • 14
  • 28

Arduino fast ADC Free-running pause controlsampling--which burst control bit is best?

Add ADATE option per Gerben's comment
Source Link
Dave X
  • 2.3k
  • 14
  • 28

The auto-trigger enable bit bitClear(ADCSRA,ADATE) & bitSet(ADCSRA,ADATE),

or do you need some more complicated combination of the bits?

or do you need some more complicated combination of the bits?

The auto-trigger enable bit bitClear(ADCSRA,ADATE) & bitSet(ADCSRA,ADATE),

or do you need some more complicated combination of the bits?

Source Link
Dave X
  • 2.3k
  • 14
  • 28

Arduino ADC Free-running pause control--which control bit is best?

If one wants to do quick bursts of free-running ADC conversions, should one pause and restart using:

The ADC enable bit: bitClear(ADCSRA,ADEN) & bitSet(ADCSRA,ADEN),

The interrupt enable bit bitClear(ADCSRA,ADIE) & bitSet(ADCSRA,ADIE),

The start conversion bit bitClear(ADCSRA,ADSC) & bitSet(ADCSRA,ADSC),

or do you need some more complicated combination of the bits?

Here's some code where I'm trying to trigger a pulse and burst of samples and then report back to the host computer:

const int numSamples = 20;
const byte startPin = PD0; // start signal (pullup)
const byte pulsePin = PD6; // Normally low
const int pulse_us = 10 ; // output pulse length

int16_t sampleData[numSamples]; 
volatile int sample;
unsigned long t0, t;

// state machine:
typedef enum { STATE_NONE,  // idle
               STATE_SAMPLING, // record ADC
               STATE_DONE, // report data
 } states;
// current state-machine state
volatile states state = STATE_NONE;

void setup()
{
  Serial.begin(115200);

  pinMode(startPin,INPUT_PULLUP);
  pinMode(pulsePin,OUTPUT);
  // Clear ADC
  ADCSRA = 0;
  ADCSRB = 0;
  ADMUX = 0;
  ADMUX |= (0b0000 << MUX0); // Choose ADC channel 0
  ADMUX |= (0b01 << REFS0);  // Choose VCC reference voltage
  bitSet(ADMUX,ADLAR);  // ADC left align ADC result into ADCH register

  // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]
  // for Arduino Uno ADC clock is 16 MHz and a conversion takes 13 clock cycles
  //ADCSRA |= (0b101 << ADPS0); // /32 : 16M/32/13=38461Hz 26us
  //ADCSRA |= (0b100 << ADPS0); // /16 : 16M/16/13=76923Hz 13us 10 bit precision
  ADCSRA |= (0b011 << ADPS0); // /8  : 16M/8/13=153.8KHz 6.5us low precision
  //ADCSRA |= (0b010 << ADPS0); // /4  : 16M/4/13=307.6KHz 3.2us lower precision
  //ADCSRA |= (0b001 << ADPS0); // /2  : 16M/2/13=615.4Hz 1.6us  bad precision

  ADCSRB |= (0b000 << ADTS0); // Choose free running trigger mode
  
  bitSet(ADCSRA,ADATE); // enable auto trigger mode per ADSCRB:ADTSx 
  bitSet(ADCSRA,ADIE);  // enable interrupts when measurement complete
  bitSet(ADCSRA,ADEN);  // enable ADC
  bitSet(ADCSRA,ADSC);  // start ADC measurements
  
}

ISR(ADC_vect) // Record samples
{
  sampleData[sample++] = ADC;  // read 10bit value from ADC
  if (sample >= numSamples) {
    bitClear(ADCSRA,ADEN); // stop recording
    state = STATE_DONE;
  }
}

void report(){
  t = micros()-t0;  // calculate elapsed time
  Serial.print("Sampling frequency: ");
  Serial.print((float)1000000/t);
  Serial.println(" KHz");
  for (int i = 0; i < numSamples; i++){
    Serial.print(i);
    Serial.print(' ');
    Serial.print(sampleData[i]);
    Serial.println();
  }
}

void startSampling(){
  sample = 0;
  t0 = micros();
  digitalWrite(pulsePin,HIGH);
  bitSet(ADCSRA,ADEN); // start ADC
  delayMicroseconds(pulse_us);
  digitalWrite(pulsePin,LOW);
  
}
  
void loop()
{
  switch (state){
    case STATE_NONE:
      if(digitalRead(startPin)==LOW){
        startSampling();
        state = STATE_SAMPLING;
      }
      break;
    case STATE_SAMPLING:
      break;

    case STATE_DONE:
        report();
        state = STATE_NONE;
        break;
    default:
    ;;
  }
}

Toggling ADEN was my first thought, but ADIE seems as if it would be faster, and ADSC seems cleanest, if it works to modulate free-running ADC mode. Which would be fastest and cleanest?

I have a Nano on order, but nothing available for testing right now.