If the A/D clock is stable enough, just drive a cheap analog switch that has time-to-off of ~1ns, into a 10pF hold cap, and from there an opamp can drive the Teensy. Getting the RC time constant into the hold cap below 1ns is not hard. A GPIO could be used to drive the analog switch enable, though I would prefer to use continuous sampling mode.
--------------------------------------------------------------------------------
arm-none-eabi-g++ -o .pioenvs/teensy31/src/main.o -c -std=gnu++98 -fno-rtti -fdata-sections -ffunction-sections -Wno-unused-parameter -fno-exceptions -Wextra -fno-delete-null-pointer-checks -fmessage-length=0 -mthumb -Wno-missing-field-initializers -c -fno-builtin -O2 -fomit-frame-pointer -Wall -MMD -mcpu=cortex-m4 -DMBED_BUILD_TIMESTAMP=1464364165.29 -DTARGET_TEENSY3_1 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_K20DX256 -DTARGET_CORTEX_M -DTARGET_LIKE_MBED -DTARGET_LIKE_CORTEX_M4 -DTARGET_M4 -D__MBED__=1 -DTARGET_Freescale -D__CORTEX_M4 -DARM_MATH_CM4 -DTARGET_K20XX -D__MK20DX256__ -DPLATFORMIO=021100 -I.pioenvs/teensy31/FrameworkArduino -I.pioenvs/teensy31/FrameworkMbedInc248832578 -I.pioenvs/teensy31/FrameworkMbedInc-213564679 -I.pioenvs/teensy31/FrameworkMbedInc-250686161 -I.pioenvs/teensy31/FrameworkMbedInc-1845648957 -I.pioenvs/teensy31/FrameworkMbedInc-666725808 -I.pioenvs/teensy31/FrameworkMbedInc357213333 -I.pioenvs/teensy31/FrameworkMbedInc1049033388 -I.pioenvs/teensy31/FrameworkMbedInc-194069199 -I.pioenvs/teensy31/Led -I.pioenvs/teensy31/SerialPanel -I.pioenvs/teensy31/ADC -Isrc src/main.cpp
In file included from .pioenvs/teensy31/ADC/ADC.h:44:0,
from src/main.cpp:5:
.pioenvs/teensy31/ADC/ADC_Module.h:302:2: error: #error "F_BUS must be 108, 60, 56, 54, 48, 40, 36, 24, 4 or 2 MHz"
#error "F_BUS must be 108, 60, 56, 54, 48, 40, 36, 24, 4 or 2 MHz"
It works without any problems for me.
```
$ mkdir /tmp/teensy
$ platformio init -d /tmp/teensy -b teensy31
$ git clone https://github.com/pedvide/ADC.git /tmp/teensy/lib/ADC
$ cp /tmp/teensy/lib/ADC/examples/readPin/readPin.ino /tmp/teensy/src/readAllPins.ino
$ platformio run -d /tmp/teensy
```
The result: http://pastebin.com/xNY8C33D
P.S: I've jsut created an issue and we will add this library to our registry.
... I don't understand why once the Buffer is full, only the first half become full and the second stay the same.
I noticed that the GitHub repo has an issue ticket logged for that --
/* Example for synchonized measurements using both ADC present in Teensy 3.1
You can change the number of averages, bits of resolution and also the comparison value or range.
*/
#include<TimerOne.h>
#include<ADC.h>
#include<MsTimer2.h>
#include<FlexiTimer2.h>
const int led = LED_BUILTIN;
const int readPin = A1;
const int readPin2 = A3;
int count;
bool x = HIGH;
ADC *adc = new ADC(); // adc object
int value = 0;
int value2 = 0;
unsigned long blinkCopy; // holds a copy of the blinkCount
volatile unsigned long blinkCount = 0; // use volatile for shared variables
int ledState = LOW;
ADC::Sync_result result;
const int led_pin = 13;
void get_ADC();
void flash();
void setup()
{
pinMode(led_pin, OUTPUT);
pinMode(readPin, INPUT);
pinMode(readPin2, INPUT);
Timer1.initialize(500); //250microseconds = 4Khz
Timer1.attachInterrupt(get_ADC);
Serial.begin(9600);
adc->setAveraging(1); // set number of averages
adc->setResolution(8); // set bits of resolution
adc->setConversionSpeed(ADC_VERY_HIGH_SPEED); // change the conversion speed
adc->setSamplingSpeed(ADC_VERY_HIGH_SPEED); // change the sampling speed
adc->setAveraging(1, ADC_1); // set number of averages
adc->setResolution(8, ADC_1); // set bits of resolution
adc->setConversionSpeed(ADC_VERY_HIGH_SPEED, ADC_1); // change the conversion speed
adc->setSamplingSpeed(ADC_VERY_HIGH_SPEED, ADC_1); // change the sampling speed
adc->startSynchronizedContinuous(readPin, readPin2);
FlexiTimer2::set(500, 1.0/1000, flash); // call every 500 1ms "ticks"
// FlexiTimer2::set(500, flash); // MsTimer2 style is also supported
FlexiTimer2::start();
}
void loop()
{
}
void get_ADC(void)
{
result = adc->readSynchronizedContinuous();
result.result_adc0 = (uint16_t)result.result_adc0;
Serial.println(result.result_adc0 * 3.3 / adc->getMaxValue(ADC_0), DEC);
}
void flash()
{
static boolean output = HIGH;
digitalWrite(led_pin, output);
output = !output;
}
Hi All,
Firstly, thank you very much for this library and hard work Pedvide, it truelly is excellent. Long time lurker on this thread as I'm trying to improve the sample rate I'm seeing on my teensy. Ideally I'm trying to get to 10KHz(ish) but currently I run into issues with data rate above 4KHz.
I've modified some sample code and added in interrupt based sampling. I've also used FlexiTimer2 (also MsTimer2 to see if it made a difference) to run a blink interupt to give the ADC something to sample.
The issue I run into is that at higher interupt rates I stop getting reliable readings (shown in the included picture).
Is this an issue with using the ADC in an interupt routine at a high rate, or is it that I'm running up against the Teensy sampling limit?
I've tried reading the rest of this thread but I can't seem to find anyone with a similar issue.
Running up to date Teensyduino and teensy 3.2
View attachment 7800
Appreciate any help given.
I'm sampling pin 14 + 15 (A0 & A1) as I need to read simultaneously, but I'm only using 15 (A1) at the moment. There's just a wire between that and Pin 13, the LED, so that I'm reading something. Didn't want to generate a signwave/pwm in case the additional processing requirements impinged on the sample rate.
Hmm, if your using the serial then try upping the baud rate..
You can easily get sampling speeds as low as 5uS or less. So you need to look at things other then the ADC
The Baud rate has had no affect on the data quality so far, I have increased it to its maximum, although IIRC somewhere Paul was saying that the Teensy does what it wants with the baud rate? Might be making that up.
While i've seen plenty of claims that the Teensy will do 5uS sampling, I've not come across anyone that's actually doing it successfully, if you know of anyone/any threads please point me in the right direction.
*Edit*
Is there maybe a more efficient way of storing data than just flinging values onto the serial port?
#include <ADC.h>
const int aThrottle = A10; //Throttle
const int aCurrent = A18; //Current
const int aBusV = A11; //BusV
const int aBattV = A19; //BattV
const int aMotorT = A12; //MotorTemp
const int aHST = A20; //HS-Temp
ADC *adc = new ADC(); // adc object
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(aThrottle, INPUT);
pinMode(aCurrent, INPUT);
pinMode(aBusV, INPUT);
pinMode(aBattV, INPUT);
pinMode(aMotorT, INPUT);
pinMode(aHST, INPUT);
Serial.begin(9600);
///// ADC0 ////
//adc->setReference(ADC_REF_INTERNAL, ADC_0); change all 3.3 to 1.2 if you change the reference
adc->setAveraging(1); // set number of averages
adc->setResolution(12); // 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
adc->setConversionSpeed(ADC_HIGH_SPEED); // 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_HIGH_SPEED); // change the sampling speed
////// ADC1 /////
adc->setAveraging(1, ADC_1); // set number of averages
adc->setResolution(12, ADC_1); // set bits of resolution
adc->setConversionSpeed(ADC_HIGH_SPEED, ADC_1); // change the conversion speed
adc->setSamplingSpeed(ADC_HIGH_SPEED, ADC_1); // change the sampling speed
delay(500);
Serial.println("end setup");
}
int value[16] = {0};
int value2[16] = {0};
int value3[16] = {0};
int value4[16] = {0};
int value5[16] = {0};
int value6[16] = {0};
int testtime;
ADC::Sync_result result;
void loop() {
int i;
elapsedMicros sinceStart; // start the clock
for (i = 0; i < 16; i++) {
result = adc->analogSynchronizedRead(aThrottle, aCurrent);
value[i] = result.result_adc0;
value2[i] = result.result_adc1;
result = adc->analogSynchronizedRead(aBusV, aBattV);
value3[i] = result.result_adc0;
value4[i] = result.result_adc1;
result = adc->analogSynchronizedRead(aMotorT, aHST);
value5[i] = result.result_adc0;
value6[i] = result.result_adc1;
}
testtime = sinceStart; //how long it took to read all 6 pins 16 times.
Serial.print("Full read time was ");
Serial.print(testtime);
Serial.println(" us");
//First ADC array
Serial.print("Pin: "); //Copy and paste hell from here on out...
Serial.print(aThrottle);
Serial.print(", value ADC0: ");
for (i = 0; i < 16; i++) {
Serial.print(value[i]*3.27/adc->getMaxValue(ADC_0), DEC); //using 3.27 as the true voltage value
Serial.print(" ");
}
//Second ADC array
Serial.println(" ");
Serial.print("Pin: "); //Copy and paste hell from here on out...
Serial.print(aCurrent);
Serial.print(", value ADC1: ");
for (i = 0; i < 16; i++) {
Serial.print(value2[i]*3.27/adc->getMaxValue(ADC_1), DEC);
Serial.print(" ");
}
//Third ADC array
Serial.println(" ");
Serial.print("Pin: "); //Copy and paste hell from here on out...
Serial.print(aBusV);
Serial.print(", value ADC0: ");
for (i = 0; i < 16; i++) {
Serial.print(value3[i]*3.27/adc->getMaxValue(ADC_0), DEC);
Serial.print(" ");
}
//Forth ADC array
Serial.println(" ");
Serial.print("Pin: "); //Copy and paste hell from here on out...
Serial.print(aBattV);
Serial.print(", value ADC1: ");
for (i = 0; i < 16; i++) {
Serial.print(value4[i]*3.27/adc->getMaxValue(ADC_1), DEC);
Serial.print(" ");
}
//Fifth ADC array
Serial.println(" ");
Serial.print("Pin: "); //Copy and paste hell from here on out...
Serial.print(aMotorT);
Serial.print(", value ADC0: ");
for (i = 0; i < 16; i++) {
Serial.print(value5[i]*3.27/adc->getMaxValue(ADC_0), DEC);
Serial.print(" ");
}
//Sixth ADC array
Serial.println(" ");
Serial.print("Pin: "); //Copy and paste hell from here on out...
Serial.print(aHST);
Serial.print(", value ADC1: ");
for (i = 0; i < 16; i++) {
Serial.print(value6[i]*3.27/adc->getMaxValue(ADC_1), DEC);
Serial.print(" ");
}
Serial.println(" ");
delay(1000);
}