Teensy 4 not supported by ADC examples

Status
Not open for further replies.

Deane

Well-known member
I am starting to work with the ADC so I went to Files > Examples > Teensy 4.0 examples > ADC > (pick any example file)
None of these will compile. I only tried 3 but they all give an error that says #error Board not supported.
So what is the best way to use the AD converter? Will the Arduino command analogRead(pin number) work OK?
Thanks.
 
I don't see how to determine that.The menu items in the small Teensyduino box are grayed out.
I just downloaded it on December 30 and the install file is 65,080K bytes.
 
TD 1.50 was release after that. It would be the one to test against.

In the Main IDE window - selecting 'Help /About Arduino' will show the IDE version and a tag in the upper right corner is added to indicate the version of TeensyDuino
 
Also if you are not using the version of ADC that is installed by Teensyduino, but instead installed from github, you should either sync up to the latest stuff or remove it and use the version with Teensyduino.
 
I get different errors than you, and a bunch of warnings, but I can confirm this: Does not compile with 1.50 .

Example:
Code:
ringBufferDMA: In function 'void setup()':
ringBufferDMA:41: error: 'class ADC' has no member named 'setAveraging'
   41 |     adc->setAveraging(8); // set number of averages
      |          ^~~~~~~~~~~~
ringBufferDMA:42: error: 'class ADC' has no member named 'setResolution'
   42 |     adc->setResolution(12); // set bits of resolution
      |          ^~~~~~~~~~~~~
ringBufferDMA:50: error: 'class ADC' has no member named 'enableDMA'
   50 |     adc->enableDMA(ADC_0);
      |          ^~~~~~~~~
ringBufferDMA:53: error: 'class ADC' has no member named 'enableInterrupts'
   53 |     adc->enableInterrupts(adc0_isr, ADC_0);
      |          ^~~~~~~~~~~~~~~~
Bibliothek ADC in Version 8.0 im Ordner: C:\Arduino\hardware\teensy\avr\libraries\ADC  wird verwendet

or, warnings:
Code:
C:\Arduino\hardware\teensy\avr\cores\teensy4/imxrt.h:999:38: warning: '<<' in boolean context, did you mean '<' ? [-Wint-in-bool-context]
  999 | #define ADC_GC_DMAEN    ((uint32_t)(1<<1))
      |                                    ~~^~~~
C:\Arduino\hardware\teensy\avr\libraries\ADC\ADC_Module.cpp:1522:28: note: in expansion of macro 'ADC_GC_DMAEN'
 1522 |         if (adc_regs.GC && ADC_GC_DMAEN) {
      |                            ^~~~~~~~~~~~
C:\Arduino\hardware\teensy\avr\cores\teensy4/imxrt.h:999:38: warning: '<<' in boolean context, did you mean '<' ? [-Wint-in-bool-context]
  999 | #define ADC_GC_DMAEN    ((uint32_t)(1<<1))
      |                                    ~~^~~~
C:\Arduino\hardware\teensy\avr\libraries\ADC\ADC_Module.cpp:1535:28: note: in expansion of macro 'ADC_GC_DMAEN'
 1535 |         if (adc_regs.GC && ADC_GC_DMAEN) {
      |                            ^~~~~~~~~~~~
Note, I'm using a different compiler-version (but this is not the reason)
Note, the lines above are ERRORS - don't take them as warnings. Remove a "&"
 
Last edited:
So no one proofed this example?

Possibly/apparently not :( It was done by forum members starting from T4 specific examples merging with the original github author of the T_3.x ADC code - and testing done against other sketches for new T4 hardware.

In the process - at least final testing as integrated skipped those prior examples. The WIP on github may have alternate examples to show function on Teensy 4.
 
In an effort to read any analog signal I tried the Arduino example for simple analogRead. (Examples>Basics>AnalogReadSerial) It compiled and loaded but nothing happened.
It was supposed to print the voltage on the screen but it does nothing.
So I reloaded the last program that I had been running (attached). Strangely it still outputs the 100 ns pulse every cycle but the orange LED stays on for about 8 seconds then goes off for 8 seconds.
What is going on? Did I change something by loading the Arduino example? How can I fix this?View attachment LED_8_second_delay.ino
 
@Frank B - Yep bugs... I just put in PR to fix the && to & https://github.com/pedvide/ADC/pull/50

As for not building on Teensyduino 1.50. It builds for me...
BUT - I am thinking he may have deleted the file: Arduino\hardware\teensy\avr\libraries\ADC\RingBufferDMA.cpp: from the library.

The Ring Buffer DMA code had two minor issues. The DMA code did not work, never really filled above the half way mark of the buffer and sometimes would crash things, and the none of the other methods were implemented to actually do anything with the data...

Yes I verified this was part of the commit: https://github.com/pedvide/ADC/commit/c1e9f42971d98910aa375dcf1a77484c00d8c929
Looks like he deleted all of the files that start with ringBuffer...

Note the non-dma one I believe worked.

@all try deleting these files ...

@Paul - another case of how to handle non-clean installs (updates over previous installs) where some files have been deleted.
 
I attempted to find a way to delete the old TeensyDuino program first but it is not listed as a program in the Windows control panel. When I installed the new version it never asked me if I wanted to overwrite the old version but I guess that is what it did.
Kurt E -- I can see that the ADC_TEST example is large because it checks for which Teensy is used and which A/D and lots of other stuff that I don't need. Could you please just pair it down to the simplest program possible (without the ring buffer) that will read an analog pin (A1) on AD0 as fast as it can and put the value in RAM? My goal is to read the pin and write the value in less than 200 ns. I don't know if this is possible but I wanted to test it. I realize that this will probably require a small number of samples, maybe only one. THANKS!
 
@Deane - please note, I am not the owner of this library or use it much, I am simply a PJRC user who wanted to help out to get one more thing working on the T4... So started working on it and then the library owner @pedvide integrated it.

To get the stuff to hopefully be able to compile, simply open up a command prompt or folder window to the location where ADC is installed on your machine, which I believe is:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\ADC\

Then delete all files that start with the name ringBuffer...

Note: In my case I have different directories for different Arduino releases and in this case this was the first release of Teensyduino that supported the current release 1.8.11 so it was fresh install...

As for quickest and ... You need to look at the different options, like how many bits of data, and sample speed and ... And choose what works for you.

I should also note, that the owner of the library changed a lot of things in the current release so some things may not compile...

Example adc_dma may not compile. Someone should go through and fix them...

Example, he removed a lot of methods from the top level ADC object and you need to instead use the actual module... (adc0 or adc1).

So for example:
Code:
adc->setAveraging(8); // set number of averages
adc->setResolution(12); // set bits of resolution
should now be:
Code:
adc->adc0->setAveraging(8); // set number of averages
adc->adc0->setResolution(12); // set bits of resolution

And likewise:
Code:
   adc->setAveraging(8, ADC_1); // set number of averages
    adc->setResolution(12, ADC_1); // set bits of resolution
Need to be converted...

Note: I made these changes to this specific example and added it to my Pull Request back to the owner... Other examples probably have similar problems.

I mention this example as this one should read in a full buffer of ADC examples as fast as it can. Actually it does two different pins one on each of the hardware ADCs... The speed probably depends on what options you choose.
 
Thanks Kurt E. I deleted the 4 Ring Buffer files in the ADC folder and now it compiles and seems to run the simple readAnalog example as modified by me to remove all the ADC1 stuff that I don't intend to use.
The program is attached. The LED blinks rapidly as I see the code for that but nothing is printed on the screen. What am I missing to make the Serial.Print work? View attachment Mod_Analog_Read for T4.txt
 
Short code like that is easy to Ctrl+T format in the IDE and post for faster review in #/Hashtag code block.

Setup() enters on Teensy before PC will have establlished connection by a couple hundred milliseconds. Adding this in setup() will assure SerMon is online before printing goes to the bitbucket to be missed:

>> while( !Serial && millis()<2000 );

Code:
/* Example for analogRead ----> Simplifed by Deane  Feb 7 2020
   You can change the number of averages, bits of resolution and also the comparison value or range.
*/


#include <ADC.h>
#include <ADC_util.h>

const int readPin = A1; // ADC0


ADC *adc = new ADC(); // adc object;

void setup() {

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(readPin, INPUT);

  Serial.begin(9600);
  [B][COLOR="#FF0000"]while( !Serial && millis()<5000 );[/COLOR][/B]
  Serial.println("Begin setup");

  ///// ADC0 ////
  // reference can be ADC_REFERENCE::REF_3V3, ADC_REFERENCE::REF_1V2 (not for Teensy LC) or ADC_REFERENCE::REF_EXT.
  //adc->adc0->setReference(ADC_REFERENCE::REF_1V2); // change all 3.3 to 1.2 if you change the reference to 1V2

  adc->adc0->setAveraging(4); // set number of averages
  adc->adc0->setResolution(12); // set bits of resolution

  //  Choose one of the following Conversion speeds:
  //  ADC_CONVERSION_SPEED enum: VERY_LOW_SPEED, LOW_SPEED, MED_SPEED, HIGH_SPEED_16BITS,
  //  HIGH_SPEED or 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 of the
  //  bus speed.

  adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); // change conversion speed

  // Choose sampling speed: ADC_MED_SPEED enum: VERY_LOW_SPEED, LOW_SPEED, MED_SPEED,
  //  HIGH_SPEED or VERY_HIGH_SPEED

  adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // change sampling speed

  // always call the compare functions after changing the resolution!
  //adc->adc0->enableCompare(1.0/3.3*adc->adc0->getMaxValue(), 0); // measurement will be ready
  //  if value < 1.0V
  //adc->adc0->enableCompareRange(1.0*adc->adc0->getMaxValue()/3.3, 2.0*adc->adc0->getMaxValue()/3.3, 0, 1); // 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)
  //adc->adc0->enableInterrupts(adc0_isr);

  Serial.println("End setup");

}

int value;


void loop() {

  // Single reads

  value = adc->adc0->analogRead(readPin); // read a new value, will return ADC_ERROR_VALUE if
  //  the comparison is false.

  Serial.print("Pin: ");
  Serial.print(readPin);
  Serial.print(", value ADC0: ");
  Serial.println(value * 3.3 / adc->adc0->getMaxValue(), DEC);


  // Print errors, if any.
  if (adc->adc0->fail_flag != ADC_ERROR::CLEAR) {
    Serial.print("ADC0: "); Serial.println(getStringADCError(adc->adc0->fail_flag));
  }


  digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));

  delay(50);
}

// If you enable interrupts make sure to call readSingle() to clear the interrupt.
void adc0_isr() {
  //  adc->adc0->readSingle();
}

//   ***** END *****
 
Code:
/* Example for analogRead ----> Simplifed by Deane  Feb 7 2020
*  You can change the number of averages, bits of resolution and also the comparison value or range.
*/


#include <ADC.h>
#include <ADC_util.h>

const int readPin = A1; // ADC0


ADC *adc = new ADC(); // adc object;

void setup() {

    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(readPin, INPUT);
    
[COLOR="#B22222"]    while (!Serial && (millis() < 5000)) ;[/COLOR]
       Serial.begin(9600);

    Serial.println("Begin setup");

    ///// ADC0 ////
    // reference can be ADC_REFERENCE::REF_3V3, ADC_REFERENCE::REF_1V2 (not for Teensy LC) or ADC_REFERENCE::REF_EXT.
    //adc->adc0->setReference(ADC_REFERENCE::REF_1V2); // change all 3.3 to 1.2 if you change the reference to 1V2

    adc->adc0->setAveraging(4); // set number of averages
    adc->adc0->setResolution(12); // set bits of resolution
    
    //  Choose one of the following Conversion speeds:
    //  ADC_CONVERSION_SPEED enum: VERY_LOW_SPEED, LOW_SPEED, MED_SPEED, HIGH_SPEED_16BITS, 
    //	HIGH_SPEED or 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 of the 
    //	bus speed.
    
    adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); // change conversion speed
    
   // Choose sampling speed: ADC_MED_SPEED enum: VERY_LOW_SPEED, LOW_SPEED, MED_SPEED, 
  //	HIGH_SPEED or VERY_HIGH_SPEED
  
    adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // change sampling speed

    // always call the compare functions after changing the resolution!
    //adc->adc0->enableCompare(1.0/3.3*adc->adc0->getMaxValue(), 0); // measurement will be ready 
    //  if value < 1.0V
    //adc->adc0->enableCompareRange(1.0*adc->adc0->getMaxValue()/3.3, 2.0*adc->adc0->getMaxValue()/3.3, 0, 1); // 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)
    //adc->adc0->enableInterrupts(adc0_isr);

    Serial.println("End setup");

}

int value;


void loop() {

    // Single reads

    value = adc->adc0->analogRead(readPin); // read a new value, will return ADC_ERROR_VALUE if 
					//	the comparison is false.

    Serial.print("Pin: ");
    Serial.print(readPin);
    Serial.print(", value ADC0: ");
    Serial.println(value*3.3/adc->adc0->getMaxValue(), DEC);

   
       // Print errors, if any.
    if(adc->adc0->fail_flag != ADC_ERROR::CLEAR) {
      Serial.print("ADC0: "); Serial.println(getStringADCError(adc->adc0->fail_flag));
    }
    

    digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));

    delay(50);
}

// If you enable interrupts make sure to call readSingle() to clear the interrupt.
void adc0_isr() {
      //  adc->adc0->readSingle();
}

//   ***** END *****

It looks like it should print. I added the one line in RED (typed on fly so always potential I mistyped) That waits up to 5 seconds for the serial port to be ready...
Obviously you need to have something like the Serial Monitor open to the correct Serial port...
 
Still nothing printed on the screen. What do you mean by opening a serial monitor. How do I do that?
 
Running Arduino, there is a button near the upper right hand side of window (on windows below the area for min/max/close windows, which if you hover over it says Serial Monitor... Click on it.
Or choose it from the Arduino Tools menu or ...
 
Kurt, thanks! Easy and now everything works. A/D is reading accurately and reporting. Sorry for bothering you with basic beginner stuff. I have not played with the IDE much.
Thanks to all. Now I can move on to testing the speed and accuracy (at speed) of the Teensy 4.0 A/D.
 
FYI -- It looks like the fastest the Teensy 4.0 can get is about 1.1 microseconds for reading the A/D. This is using the 600 MHz clock speed, Averaging set to 1, Resolution to 10 bits, Conversion set to VERY_HIGH_SPEED and Sampling set to VERY_HIGH_SPEED. This is disappointing for my project. I had hoped to get below 200 ns. Now I have to learn all about external A/D converters and high speed FIFO memory.
 
Kurt, Yes I did read a lot of that a couple of days ago. I did not understand some of it. For example "There are two ways to do periodic conversions: using an IntervalTimer or using the PDB."
What is PDB?
It also sounds like the "Continuous mode" might be useful if can go faster than a single reading but I found nothing that said that that might be true. I should try that if I can find an example of it.

The way I timed my single reading was to turn on a digital pin just before the analogRead line and turn it off right after that line. I looked at the duration of the resulting pulse on my scope.Knowing that the (fastRead or fastWrite)commands only take about 22 nanoseconds allows one to get a very good idea of the time it takes to do the analog read.
 
Hello Deane,

The example conversionSpeed runs over all possible configurations of the board and prints out the conversion speed for both the single-shot analogRead and the continuous mode. You can then check what configuration need to set to get the speed that you need.
Indeed the continuous mode is faster than the single-shot one.
 
Hi Pedvide,
Thanks for pointing this example out. I have been running this example a few times now but it always fails to show a Time and Voltage near the end of the Continuous Mode. It also shows 0.0000 Volts at the end. Can you please take a look at the results below? Also, what is the meaning of Conversion Speed: ADACK_10 and ADACK_20 ? Also, why are some times showing Time: inf us. OR nan us. I had to put a 200 ms. delay after printing the titles because they were not showing up on the serial monitor.
I see no numbers less that the ~1us. that I found with a single read so far. Thanks .
View attachment AD Speed test output.txt
 
Status
Not open for further replies.
Back
Top