Hello everyone, I am still new to Teesy. I am working on an acoustic project on Teensy 4.1, this project requires two piezo sensors and a very high sampling rate.
I want to continuously monitor the piezo sensors and write the values to the serial.
What I want to do, is to have a uniform synchronous sampling, with preferably the highest rate possible (so in the range of 100 KHz to 400 KHz ). I tried several codes that I found on the internet though I am not achieving this rate. I know that writing to the serial is quite slow (or that's what I think), so I can use the compare function on the ADC to only convert values that are higher than a threshold, though I don't know if it impacts the sampling speed or not.
Also, if I want to use the synchronized reading, should I attach both sensors to the same ADC or to different ADC, like one of them to ADC 0 and one to ADC 1?
Thank you all in advance for your help, it is much appreciated.
My code:
#include <ADC.h>
const int readpin1 = A14; // First analog input pin
const int readpin2 = A16; // Second analog input pin
ADC *adc = new ADC(); // ADC object
#define SAMPRATE 200000 // Sampling rate 200 000 Hz
#define AVERAGING 1
#define RESOLUTION 12
#define ADCSAMPLES 10000 // Number of samples to collect
uint16_t adcbuffer1[ADCSAMPLES]; // Buffer for first analog input
uint16_t adcbuffer2[ADCSAMPLES]; // Buffer for second analog input
volatile uint32_t adcidx = 0; // Must be volatile as it is changed in interrupt handler
const char compileTime[] = "ADC Timer test Compiled on " __DATE__ " " __TIME__;
void setup() {
delay(500);
Serial.begin(200000);
delay(1000);
pinMode(readpin1, INPUT_DISABLE);
pinMode(readpin2, INPUT_DISABLE);
delay(1500);
Serial.print("\n\n");
Serial.println(compileTime);
Serial.println("Press <n> to collect and display data");
adc->adc0->setAveraging(AVERAGING); // Set number of averages
adc->adc0->setResolution(RESOLUTION); // Set bits of resolution
adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // Set the conversion speed
adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // Set the sampling speed
adc->adc1->setAveraging(AVERAGING); // Set number of averages
adc->adc1->setResolution(RESOLUTION); // Set bits of resolution
adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // Set the conversion speed
adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // Set the sampling speed
}
void loop() {
char ch;
if (Serial.available()) {
ch = Serial.read();
if (ch == 'n') GetADCData();
}
}
// This ISR reads both ADCs
void adc0_isr() {
uint16_t adc_val1, adc_val2;
// Read analog values from both ADCs
// Read analog values from both ADCs
adc->adc0->startSingleRead(readpin1);
adc_val1 = adc->adc0->readSingle();
adc->adc1->startSingleRead(readpin2);
adc_val2 = adc->adc1->readSingle();
if (adcidx < ADCSAMPLES) { // Storage stops when enough samples collected
adcbuffer1[adcidx] = adc_val1;
adcbuffer2[adcidx] = adc_val2;
adcidx++;
}
}
void GetADCData(void) {
delay(100); // Wait for USB serial to finish
adc->adc0->stopTimer();
adc->adc0->startSingleRead(readpin1); // Setup everything before the Timer starts, differential is also possible
adc->adc1->startSingleRead(readpin2);
delay(1);
adc->adc0->readSingle();
adc->adc1->readSingle();
adcidx = 0;
// Now start the ADC collection timer
adc->adc0->startTimer(SAMPRATE); // Frequency in Hz
adc->adc0->enableInterrupts(adc0_isr);
// do {
// // You could process a sample here with multiple buffers or copying to a new buffer
// // for processing while collection is in progress
// } while (adcidx < ADCSAMPLES);
adc->adc0->stopTimer();
Serial.println("Collection complete.");
// The data is in the global adcbuffer arrays.
ShowADC();
}
// Display the start of data in counts. Send 10 values per line
// Data is in the global variables adcbuffer1 and adcbuffer2.
void ShowADC(void) {
uint32_t i;
Serial.println("ADC Data in Counts");
for (i = 0; i < ADCSAMPLES; i++) {
if ((i % 10) == 0) {
Serial.printf("\n% 3d: ", i);
}
Serial.printf("% 5d, % 5d", adcbuffer1, adcbuffer2);
if ((i + 1) % 10 == 0) {
Serial.println();
}
}
Serial.println();
}
I want to continuously monitor the piezo sensors and write the values to the serial.
What I want to do, is to have a uniform synchronous sampling, with preferably the highest rate possible (so in the range of 100 KHz to 400 KHz ). I tried several codes that I found on the internet though I am not achieving this rate. I know that writing to the serial is quite slow (or that's what I think), so I can use the compare function on the ADC to only convert values that are higher than a threshold, though I don't know if it impacts the sampling speed or not.
Also, if I want to use the synchronized reading, should I attach both sensors to the same ADC or to different ADC, like one of them to ADC 0 and one to ADC 1?
Thank you all in advance for your help, it is much appreciated.
My code:
#include <ADC.h>
const int readpin1 = A14; // First analog input pin
const int readpin2 = A16; // Second analog input pin
ADC *adc = new ADC(); // ADC object
#define SAMPRATE 200000 // Sampling rate 200 000 Hz
#define AVERAGING 1
#define RESOLUTION 12
#define ADCSAMPLES 10000 // Number of samples to collect
uint16_t adcbuffer1[ADCSAMPLES]; // Buffer for first analog input
uint16_t adcbuffer2[ADCSAMPLES]; // Buffer for second analog input
volatile uint32_t adcidx = 0; // Must be volatile as it is changed in interrupt handler
const char compileTime[] = "ADC Timer test Compiled on " __DATE__ " " __TIME__;
void setup() {
delay(500);
Serial.begin(200000);
delay(1000);
pinMode(readpin1, INPUT_DISABLE);
pinMode(readpin2, INPUT_DISABLE);
delay(1500);
Serial.print("\n\n");
Serial.println(compileTime);
Serial.println("Press <n> to collect and display data");
adc->adc0->setAveraging(AVERAGING); // Set number of averages
adc->adc0->setResolution(RESOLUTION); // Set bits of resolution
adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // Set the conversion speed
adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // Set the sampling speed
adc->adc1->setAveraging(AVERAGING); // Set number of averages
adc->adc1->setResolution(RESOLUTION); // Set bits of resolution
adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // Set the conversion speed
adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // Set the sampling speed
}
void loop() {
char ch;
if (Serial.available()) {
ch = Serial.read();
if (ch == 'n') GetADCData();
}
}
// This ISR reads both ADCs
void adc0_isr() {
uint16_t adc_val1, adc_val2;
// Read analog values from both ADCs
// Read analog values from both ADCs
adc->adc0->startSingleRead(readpin1);
adc_val1 = adc->adc0->readSingle();
adc->adc1->startSingleRead(readpin2);
adc_val2 = adc->adc1->readSingle();
if (adcidx < ADCSAMPLES) { // Storage stops when enough samples collected
adcbuffer1[adcidx] = adc_val1;
adcbuffer2[adcidx] = adc_val2;
adcidx++;
}
}
void GetADCData(void) {
delay(100); // Wait for USB serial to finish
adc->adc0->stopTimer();
adc->adc0->startSingleRead(readpin1); // Setup everything before the Timer starts, differential is also possible
adc->adc1->startSingleRead(readpin2);
delay(1);
adc->adc0->readSingle();
adc->adc1->readSingle();
adcidx = 0;
// Now start the ADC collection timer
adc->adc0->startTimer(SAMPRATE); // Frequency in Hz
adc->adc0->enableInterrupts(adc0_isr);
// do {
// // You could process a sample here with multiple buffers or copying to a new buffer
// // for processing while collection is in progress
// } while (adcidx < ADCSAMPLES);
adc->adc0->stopTimer();
Serial.println("Collection complete.");
// The data is in the global adcbuffer arrays.
ShowADC();
}
// Display the start of data in counts. Send 10 values per line
// Data is in the global variables adcbuffer1 and adcbuffer2.
void ShowADC(void) {
uint32_t i;
Serial.println("ADC Data in Counts");
for (i = 0; i < ADCSAMPLES; i++) {
if ((i % 10) == 0) {
Serial.printf("\n% 3d: ", i);
}
Serial.printf("% 5d, % 5d", adcbuffer1, adcbuffer2);
if ((i + 1) % 10 == 0) {
Serial.println();
}
}
Serial.println();
}