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

Thread: sample rate jitter with modified adc_pdb example, Teensy 3.2

  1. #1
    Junior Member
    Join Date
    Sep 2019
    Posts
    2

    sample rate jitter with modified adc_pdb example, Teensy 3.2

    I would like to sample a single ADC channel at a constant frequency of about 100 kHz and began with the adc_pdb example.

    I've simplified the example code as well as I understand it, and it seems to work reasonably well. Monitoring the LED pin using my old 100 MHz analog scope shows that the adc isr is activated at the correct frequency but with occasional surprisingly large jitter of +/- 2 usec. The jitter gets worse if I print the values in loop (unsurprisingly).

    I would appreciate suggestions to remove the jitter, or an explanation! Code follows.

    Additional questions:

    Are my choices of sample and conversion rates appropriate? The voltage source is low (~100 Ohms) impedance.

    In the stock adc_pdb example code, why is the ADC value read in loop(), but read and ignored in the adc isr?

    Thanks!

    Code:
    #include <ADC.h>
    // based on adc_pdb example
    const int readPin = A9; // ADC0
    
    ADC *adc = new ADC(); // adc object;
    
    void setup() {
    
      pinMode(LED_BUILTIN, OUTPUT);
      pinMode(readPin, INPUT);
    
      Serial.begin(115200);
      while (!Serial);
      Serial.println("Begin setup");
    
      ///// ADC0 ////
      adc->setAveraging(0); // set number of averages
      adc->setResolution(12); // set bits of resolution
      adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); // change the conversion speed
      adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // change the sampling speed
    
      int freq = 100000;
      Serial.print("Start pdb with frequency ");
      Serial.print(freq);
      Serial.println(" Hz.");
      adc->adc0->stopPDB();
      adc->adc0->startSingleRead(readPin); // call this to setup everything before the pdb starts, differential is also possible
      adc->enableInterrupts(ADC_0);
      adc->adc0->startPDB(freq); //frequency in Hz
    
      // Print errors, if any.
      adc->printError();
      adc->resetError();
    }
    
    volatile uint16_t value;
    volatile uint8_t new_val = 0;
    volatile uint8_t led_stat = 0;
    
    void loop() {
      if (new_val) {
        new_val = 0;
        //    Serial.println(value);
        //    digitalWriteFast(LED_BUILTIN, (led_stat = !led_stat));
      }
    }
    
    // Make sure to call readSingle() to clear the interrupt.
    void adc0_isr() {
      value = (uint16_t) adc->adc0->readSingle();
      //adc->adc0->readSingle();
      new_val = 1;
      digitalWriteFast(LED_BUILTIN, (led_stat = !led_stat));
    }
    
    
    // pdb interrupt is enabled in case you need it.
    void pdb_isr(void) {
      PDB0_SC &= ~PDB_SC_PDBIF; // clear interrupt
      //  digitalWriteFast(LED_BUILTIN, (led_stat = !led_stat));
    }
    Last edited by jremington; 09-16-2019 at 04:31 PM.

  2. #2
    Junior Member
    Join Date
    Sep 2019
    Posts
    2
    In case anyone is interested, after a number of experiments I decided that 12 bits/VERY_HIGH_SPEED/100 kHz was too noisy, with obvious sampling artifacts, and settled on 10 bits/HIGH_SPEED.

    I'm not sure that the observed jitter is detrimental for this particular application, which is peak detection for a gamma ray spectrometer. Overall ADC performance/data collection is quite satisfactory.

    For bunch data processing and output, while continuing to sample data, I added the ring buffer (part of the ADC package), after increasing the ring buffer size for 8 to 256.

Posting Permissions

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