Teensy 3.6 ADC interval timer read problems

Status
Not open for further replies.

esumld999

New member
Hello, I am trying to design Teensy 3.6 to run and collect data simultaneously from a few sensors based on the ADC analgueRead interval timer example code (my code posted below), but I am running into some problems:

1) I am using all four interval timers, for each timer_callback function, is there a limited number of adc->startSingleRead functions I can use? As in the code below, I commented adc read for pin DATA_7. If I uncommented that, the data from that pin will be some crazy numbers. I tried with different timer period, but it didn't help.

2) PIN 16 & 17 on 3.6 are differential pins and can be used for either ADC0 or ADC1. But when I am trying to use it as normal ADC pin and use ADC read code as I did for other pins, it doesn't seems to work. I tried it on pin DATA_3 as shown in the code below. It may work right after uploading the code, but won't work after that.

Could anyone help me with that? Thank you!

Code:
#include <ADC.h>
#include <ADC_Module.h>
#include <RingBuffer.h>
#include <IntervalTimer.h>

const int DATA_1 = A20;   //ADC1
const int DATA_2 = A6;   //ADC0
const int DATA_3 = A3;    //A3, OR A2, ADC0 OR ADC1
const int DATA_4 = A7;   //ADC0
const int DATA_5 = A13;    //ADC1
const int DATA_6 = A12;    //ADC1
const int DATA_7 = A13;    //ADC1
const int DATA_8 = A1;     //ADC0
const int DATA_9 = A14;     //ADC0
const int DATA_10 = A15;   //ADC0

String mydata;
ADC *adc = new ADC();
IntervalTimer timer0, timer1, timer2, timer_read;
int period0 = 300, period1 = 300, period2 = 200, readtimer = 10000;
int startTimerValue0 = 0, startTimerValue1 = 0, startTimerValue2 = 0;

RingBuffer *BUFFER_1 = new RingBuffer;
RingBuffer *BUFFER_2 = new RingBuffer;
RingBuffer *BUFFER_3 = new RingBuffer;
RingBuffer *BUFFER_4 = new RingBuffer;
RingBuffer *BUFFER_5 = new RingBuffer;
RingBuffer *BUFFER_6 = new RingBuffer;
//RingBuffer *BUFFER_7 = new RingBuffer;
RingBuffer *BUFFER_8 = new RingBuffer;
RingBuffer *BUFFER_9 = new RingBuffer;
RingBuffer *BUFFER_10 = new RingBuffer;

void setup() {
  Serial.begin(115200);
  setup_pin();
  delay(100);

  //  Serial.println("Begin ADC setup");

  ///// ADC0 ////
  // reference can be ADC_REFERENCE::REF_3V3, ADC_REFERENCE::REF_1V2 (not for Teensy LC) or ADC_REFERENCE::REF_EXT.
  //adc->setReference(ADC_REFERENCE::REF_1V2, ADC_0); // change all 3.3 to 1.2 if you change the reference to 1V2
  // adc->setReference(ADC_REFERENCE::REF_3V3, ADC_0);
  adc->setAveraging(8, ADC_0); // set number of averages
  adc->setResolution(12, ADC_0); // set bits of resolution

  // it can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
  // see the documentation for more information
  // additionally the conversion speed can also be ADACK_2_4, ADACK_4_0, ADACK_5_2 and ADACK_6_2,
  // where the numbers are the frequency of the ADC clock in MHz and are independent on the bus speed.
  adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED, ADC_0); // change the conversion speed
  // it can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
  adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED, ADC_0); // change the sampling speed

  // always call the compare functions after changing the resolution!
  //adc->enableCompare(1.0/3.3*adc->getMaxValue(ADC_0), 0, ADC_0); // measurement will be ready if value < 1.0V
  //adc->enableCompareRange(1.0*adc->getMaxValue(ADC_0)/3.3, 2.0*adc->getMaxValue(ADC_0)/3.3, 0, 1, ADC_0); // ready if value lies out of [1.0,2.0] V

  // If you enable interrupts, notice that the isr will read the result, so that isComplete() will return false (most of the time)

  ////// ADC1 /////
#if ADC_NUM_ADCS>1
  //adc->setReference(ADC_REFERENCE::REF_3V3, ADC_0);
  adc->setAveraging(8, ADC_1); // set number of averages
  adc->setResolution(12, ADC_1); // set bits of resolution
  adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED, ADC_1); // change the conversion speed
  adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED, ADC_1); // change the sampling speed
#endif
  //adc->setReference(ADC_REFERENCE::REF_1V2, ADC_1);

  // always call the compare functions after changing the resolution!
  //adc->enableCompare(1.0/3.3*adc->getMaxValue(ADC_1), 0, ADC_1); // measurement will be ready if value < 1.0V
  //adc->enableCompareRange(1.0*adc->getMaxValue(ADC_1)/3.3, 2.0*adc->getMaxValue(ADC_1)/3.3, 0, 1, ADC_1); // ready if value lies out of [1.0,2.0] V

  //  Serial.print("Start timers");
  // If you enable interrupts, note that the isr will read the result, so that isComplete() will return false (most of the time)
  startTimerValue0 = timer0.begin(timer0_callback, period0);
  delayMicroseconds(50);
  startTimerValue1 = timer1.begin(timer1_callback, period1);
  delayMicroseconds(50);
  startTimerValue2 = timer2.begin(timer2_callback, period2);
  delayMicroseconds(50);
  timer_read.begin(timer_read_callback, readtimer);
  delayMicroseconds(50);

  adc->enableInterrupts(ADC_0);
  adc->enableInterrupts(ADC_1);
  //  Serial.println("Timers started");
  //  Serial.println("End ADC setup");
  delay(50);
}

void loop() {}

void timer0_callback(void) {
  adc->startSingleRead(DATA_1, ADC_1);
  adc->startSingleRead(DATA_2, ADC_0);
  adc->startSingleRead(DATA_3, ADC_1);
  adc->startSingleRead(DATA_4, ADC_0);
}
void timer1_callback(void) {
  adc->startSingleRead(DATA_5, ADC_1);
  adc->startSingleRead(DATA_6, ADC_1);
  //  adc->startSingleRead(DATA_7, ADC_1);
  adc->startSingleRead(DATA_8, ADC_0);
}
void timer2_callback(void) {
  adc->startSingleRead(DATA_9, ADC_0);
  adc->startSingleRead(DATA_10, ADC_0);
}

void timer_read_callback(void) {
  if (!BUFFER_1->isEmpty()) {
    mydata += String((BUFFER_1->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_2->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_3->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_4->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_5->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_6->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    //    mydata += String((BUFFER_7->read() * 3.3 / adc->getMaxValue()), 4);
    //    mydata += ",";
    mydata += String((BUFFER_8->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_9->read() * 3.3 / adc->getMaxValue()), 4);
    mydata += ",";
    mydata += String((BUFFER_10->read() * 3.3 / adc->getMaxValue()), 4);
    Serial.println(mydata);
    mydata = "";
  }
}

void adc0_isr() {

  uint8_t pin = ADC::sc1a2channelADC0[ADC0_SC1A & ADC_SC1A_CHANNELS]; // the bits 0-4 of ADC0_SC1A have the channel

  // add value to correct buffer
  if (pin == DATA_2) {
    BUFFER_2->write(adc->adc0->readSingle());
  } else if (pin == DATA_4) {
    BUFFER_4->write(adc->adc0->readSingle());
  } else if (pin == DATA_8) {
    BUFFER_8->write(adc->adc0->readSingle());
  } else if (pin == DATA_9) {
    BUFFER_9->write(adc->adc0->readSingle());
  } else if (pin == DATA_10) {
    BUFFER_10->write(adc->adc0->readSingle());
  } else { // clear interrupt anyway
    adc->readSingle();
  }

  // restore ADC config if it was in use before being interrupted by the analog timer
  if (adc->adc0->adcWasInUse) {
    // restore ADC config, and restart conversion
    adc->adc0->loadConfig(&adc->adc0->adc_config);
    // avoid a conversion started by this isr to repeat itself
    adc->adc0->adcWasInUse = false;
  }
}

void adc1_isr() {
  uint8_t pin = ADC::sc1a2channelADC1[ADC1_SC1A & ADC_SC1A_CHANNELS]; // the bits 0-4 of ADC0_SC1A have the channel
  // uint8_t pin = ADC::sc1a2channelADC1[]; // new version, gives directly the pin number
  // add value to correct buffer
  if (pin == DATA_1) {
    BUFFER_1->write(adc->adc1->readSingle());
  } else if (pin == DATA_3) {
    BUFFER_3->write(adc->adc1->readSingle());
  } else if (pin == DATA_5) {
    BUFFER_5->write(adc->adc1->readSingle());
  } else if (pin == DATA_6) {
    BUFFER_6->write(adc->adc1->readSingle());
    //  }  else if (pin == DATA_7) {
    //    BUFFER_5->write(adc->adc1->readSingle());
  } else { // clear interrupt anyway
    adc->readSingle();
  }
  // restore ADC config if it was in use before being interrupted by the analog timer
  if (adc->adc1->adcWasInUse) {
    // restore ADC config, and restart conversion
    adc->adc1->loadConfig(&adc->adc1->adc_config);
    // avoid a conversion started by this isr to repeat itself
    adc->adc1->adcWasInUse = false;
  }
}

void setup_pin() {
  pinMode(DATA_1, INPUT);
  pinMode(DATA_2, INPUT);
  pinMode(DATA_3, INPUT);
  pinMode(DATA_4, INPUT);
  pinMode(DATA_5, INPUT);
  pinMode(DATA_6, INPUT);
  pinMode(DATA_7, INPUT);
  pinMode(DATA_8, INPUT);
  pinMode(DATA_9, INPUT);
  pinMode(DATA_10, INPUT);
}
 
Status
Not open for further replies.
Back
Top