Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: ADC conversion time

  1. #1

    ADC conversion time

    Hi guys,

    I'm using a teensy 3.5 to measure an incoming signal using the ADC library. Does anyone know how fast I can read from the ADC with the fastest setting? Theoretically I would need to take a measurement every 6.25uS using a timer interrupt. Do you reckon that's feasible?

    Thanks

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,074
    Read the comments at the end of pedvide's ADC library sketch
    https://github.com/pedvide/ADC/blob/...inuousRead.ino
    there is also a DMA example

  3. #3
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    If you want a consistent sampling rate / sample timing, you can't use a timer interrupt and do a read in the interrupt (jitter due interrupt triggering delays). Teensy 3.5 has the PDB timer block which can trigger a periodic ADC conversion with 0-jitter timing. You can get an interrupt when the conversion is finished.

    Here is some sample code that does an ADC conversion at 200'000Hz (5 microseconds). A 50'000 Hz PWM output is measured.

    Code:
    #include <ADC.h>
    #include <array>
    
    // connect out_pin to adc_pin, PWM output on out_pin will be measured
    // via adc_pin.
    
    const uint8_t adc_pin = A9;
    const uint8_t out_pin = 2;
    
    ADC adc;
    
    std::array<volatile uint16_t, 4096> buffer;
    volatile size_t write_pos = 0;
    
    volatile uint16_t adc_val = 0;
    
    void setup() {
        pinMode(adc_pin, INPUT);
        Serial.begin(9600);
        delay(2000);
        Serial.println("Starting");
    
        adc.setAveraging(1);
        adc.setResolution(12);
    
        adc.setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED);
        adc.setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED);
        adc.adc0->analogRead(adc_pin); // performs various ADC setup stuff
    
        adc.enableInterrupts(ADC_0);
    
        if(adc.adc0->fail_flag) {
            Serial.print("ADC error: ");
            Serial.println(adc.adc0->fail_flag, HEX);
        }
    
        adc.adc0->stopPDB();
        const uint32_t pdb_trigger_frequency = 200000;
        adc.adc0->startPDB(pdb_trigger_frequency);
        
        analogWriteFrequency(out_pin, 50000);
        analogWrite(out_pin, 100);
    }
    
    void loop() {
        // Print first 100 measurements in buffer.
        for(size_t i = 0; i < 100; i++) {
            Serial.print(buffer[i]);
            if(i % 20 == 19) Serial.println();
            else Serial.print(" ");
        }
        Serial.println();
    
        if(adc.adc0->fail_flag) {
            Serial.print("ADC error: ");
            Serial.println(adc.adc0->fail_flag, HEX);
        }
        delay(1000);
    }
    
    void adc0_isr() {
        size_t write_pos_ = write_pos;
        buffer[write_pos_] = adc.adc0->readSingle();
        write_pos_++;
        if(write_pos_ >= buffer.size()) write_pos_ = 0;
        write_pos = write_pos_;
    }
    
    void pdb_isr(void) {
        PDB0_SC &=~PDB_SC_PDBIF; // clear interrupt
    }
    Expected output:
    4095 1 1 1 4095 1 3 1 4095 1 1 4 4095 1 3 1 4095 1 2 3
    4095 1 1 1 4095 1 1 1 4095 3 1 1 4095 2 2 1 4095 1 1 1
    4095 2 1 1 4095 3 1 2 4095 1 1 1 4095 1 1 1 4095 3 1 1
    4095 1 3 2 4095 2 1 1 4095 1 2 1 4095 3 1 2 4095 1 2 1
    4095 2 3 1 4095 2 1 1 4095 1 1 5 4095 2 1 3 4095 1 4 1
    ...

    Instead of the interrupt, it would also be possible to do DMA transfer.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •