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!
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);
}