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.