ADC_ISR not turning back on after burst

Status
Not open for further replies.

1101

New member
Hi guys,

As the title suggest, I'm running a short bit of code that reads ADC values into a buffer on a Teensy 3.5. The ADC is configured in single-shot mode, differential read and uses the PDB.

The framework for the code was pretty much butchered from post #3 from this thread: https://forum.pjrc.com/threads/43233-ADC-conversion-time. I'm pretty sure I'm missing something really simple, but my experience with interrupts is lacking at best.

In essence, what the program is supposed to do, is repeatedly fill a buffer with samples from the ADC. This is done by firstly configuring the ADC in single-shot differential mode (in the setup section), enabling the interrupt and starting the PDB. From there adc0_isr stores the read ADC values into a buffer. This ISR is disabled once the buffer is full (but it gets re-enabled in the main loop). Note that at the end of the main loop, the write_pos variable is reset to 0 in order to restart the buffer indexing.

I've also added several ways to check if the adc0_isr is called. Firstly, I've simple added a serial output in this ISR. I've also added a global variable (called simply isr_count) that increments each time this isr is called; this global variable gets printed at the end of the main loop. The global buffer write position (write_pos) also gets printed at the beginning and end of each loop.

What I'm finding is that the first loop (referring to the continually running main loop) runs normally and the ADC samples just fine. But I've found that the adc0_isr does not get activated again after the first loop. This can be seen by the fact that the serial print in the interrupt doesn't print after the first loop and the fact that the isr_count variable doesn't increment after the first loop either.

Code below:

Code:
#include <ADC.h>
#define MEM_LEN 20

const uint8_t adc_pin1 = A10;
const uint8_t adc_pin2 = A11;
const uint32_t pdb_trigger_frequency = 1000;
uint16_t loop_count = 1;

ADC adc;

volatile int32_t write_pos = 0;
uint16_t delay_time, isr_count = 0;
volatile int16_t buff[MEM_LEN];


void setup() {
  uint8_t i;
  Serial.printf("Start program\n");

  // SERIAL COMMS SETUP
  // ==================
  Serial.begin(9600);
  delay(2000);
  //=================================================

  // ADC Setup
  // =========
  pinMode(adc_pin1, INPUT);
  pinMode(adc_pin2, INPUT);
    
  adc.setAveraging(5);
  adc.setResolution(16);

  adc.setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED);
  adc.setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED);

  adc.adc0->analogReadDifferential(adc_pin1, adc_pin2);
}

void loop() {
  
  uint8_t i;

  Serial.printf("Loop: %i\n",loop_count++); 
  Serial.printf("Write pos before ADC run: %i\n",write_pos); 

  adc.enableInterrupts(ADC_0); 
  adc.printError();

  adc.adc0->stopPDB();
  adc.adc0->startPDB(pdb_trigger_frequency); 
  delay_time = (1000*MEM_LEN/pdb_trigger_frequency)+200;
  delay(delay_time);

  if(adc.adc0->fail_flag) {
      Serial.print("ADC loop error: ");
      Serial.println(adc.adc0->fail_flag, HEX);
  }
  
  for(i=0;i<20;i++){
    Serial.printf("%i\n",buff[i]);  
  }

  Serial.printf("ADC ISR count: %i\n",isr_count); 
  Serial.printf("Write pos after ADC run: %i\n\n",write_pos);  

  write_pos = 0;

  delay(5000);
  
  
}

// ADC ISR
// =======
void adc0_isr() {
    isr_count++;
    int32_t write_pos_ = write_pos;

    Serial.print("Inter!\n");
    
    write_pos = write_pos_;
    
    buff[write_pos_] = adc.adc0->readSingle();
    write_pos_++;
    if(write_pos_ >= MEM_LEN-1) adc.disableInterrupts(ADC_0);
    write_pos = write_pos_;
}

void pdb_isr(void) {
    PDB0_SC &=~PDB_SC_PDBIF; // clear interrupt
}

This is the critical piece of code that I isolated and can't get working properly. The rationale is that I want to repeatedly trigger the ADC at a convenient time to fill this buffer. These triggers won't be at regular intervals.

Any help would be much appreciated. As I mentioned, I really don't have much experience with interrupts. A couple of hours' worth of internet searches have really only confused me further. Let rip if I'm being an idiot somehow.
 
Last edited:
Status
Not open for further replies.
Back
Top