Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: What ADC library to use with Teensy 4.0?

  1. #1

    What ADC library to use with Teensy 4.0?

    Hi all,

    I am trying to use ADC.h from a Teensy 4.0 Arduino sketch and am getting a build error that the library doesn't support T4.

    Any idea what library to use?

    I want to trigger periodically (~20khz) from a timer isr two parallel conversions on ADC1 and ADC2 and get an ADC ISR when the two values are available. I did something similar for T3.2 with ADC but now want to migrate to T4.

    Thanks.

  2. #2
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    677
    There is no ADC library for the T4 yet that I know of. I think what you want to do is relatively straightforward however. By the way, as I understand it, even the T3.2 ADC library did not do strictly simultaneous ADC reads; but rather in the two-channel mode the two ADCs were simply started one right after the other.

  3. #3
    Quote Originally Posted by JBeale View Post
    ... I think what you want to do is relatively straightforward however....
    Thanks JBeale. What do you mean? I can do it without ADC.h support? How? Accessing the hardware directly? Any other useful library?

    Also, anybody knows the ETA of ADC.h support for T4? I am surprised that PJRC are selling the T4 without A/D software support. Am I missing something? Do they provide other libraries that support it?

  4. #4
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    677
    You can use the A/D in the same way as with other Arduino-style boards without a separate library. For example the below program compiles and runs on Teensy 4. Note that T3.2 has a nominally 16-bit ADC although only 12 or 13 bits are real without averaging. Teensy 4 has a nominally 12 bit ADC of which about 10 bits are real without averaging. So for T4 you can set analogReadRes(12), or select 10 or 8 bits for (slightly) faster operation. Also, T4 does not have an external reference input so you are limited to the power supply 3.3V as ADC Vref.

    In this particular example, the code simply reads one ADC channel at 12 bits without extra delays, and it ends up at 174825 samples per second. So two channels at 20 kHz sampling rate should not be a problem.

    Code:
    // Analog input test for Teensy 3/4    Oct 4 2012 - Feb 2019 J.Beale
    
    // Setup: https://picasaweb.google.com/109928236040342205185/Electronics#5795546092126071650
    
    #define VREF (3.292)         // ADC reference voltage (= power supply)
    #define VINPUT (1.328)       // ADC input voltage from NiCd AA battery
    #define ADCMAX (4095)        // maximum possible reading from ADC
    #define EXPECTED (ADCMAX*(VINPUT/VREF))     // expected ADC reading
    #define SAMPLES (100000)      // how many samples to combine for pp, std.dev statistics
    
    const int analogInPin = A0;  // Analog input is AIN0 (Teensy3 pin 14, next to LED)
    const int LED1 = 13;         // output LED connected on Arduino digital pin 13
    
    int sensorValue = 0;        // value read from the ADC input
    long oldT;
    
    void setup() {    // ==============================================================
          pinMode(LED1,OUTPUT);       // enable digital output for turning on LED indicator
          // analogReference(EXTERNAL);  // set analog reference to internal ref
          analogReadRes(12);          // set ADC resolution to this many bits
          analogReadAveraging(1);    // average this many readings
         
          Serial.begin(115200);       // baud rate is ignored with Teensy USB ACM i/o
          digitalWrite(LED1,HIGH);   delay(1000);   // LED on for 1 second
          digitalWrite(LED1,LOW);    delay(3000);   // wait in case serial monitor still opening
         
          Serial.println("# Teensy ADC test start: ");
    } // ==== end setup() ===========
    
    void loop() {  // ================================================================ 
         
          long datSum = 0;  // reset our accumulated sum of input values to zero
          int sMax = 0;
          int sMin = 65535;
          long n;            // count of how many readings so far
          double x,mean,delta,sumsq,m2,variance,stdev;  // to calculate standard deviation
         
          oldT = millis();   // record start time in milliseconds
    
          sumsq = 0; // initialize running squared sum of differences
          n = 0;     // have not made any ADC readings yet
          mean = 0; // start off with running mean at zero
          m2 = 0;
         
          for (int i=0;i<SAMPLES;i++) {
            x = analogRead(analogInPin);
            datSum += x;
            if (x > sMax) sMax = x;
            if (x < sMin) sMin = x;
                  // from http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
            n++;
            delta = x - mean;
            mean += delta/n;
            m2 += (delta * (x - mean));
          } 
          variance = m2/(n-1);  // (n-1):Sample Variance  (n): Population Variance
          stdev = sqrt(variance);  // Calculate standard deviation
    
          Serial.print("# Samples/sec: ");
          long durT = millis() - oldT;
          float datAvg = (1.0*datSum)/n;
          Serial.print((1000.0*n/durT),2);
    
          Serial.print(" Avg: ");     Serial.print(datAvg,2);
          Serial.print(" Offset: ");  Serial.print(datAvg - EXPECTED,2);
          Serial.print(" P-P noise: ");  Serial.print(sMax-sMin);
          Serial.print(" St.Dev: ");  Serial.print(stdev,3);
          Serial.print(" T(deg.C): "); Serial.print(tempmonGetTemp(),1);
          Serial.println();
    } // end main()  =====================================================
    Last edited by JBeale; 09-29-2019 at 07:34 AM.

  5. #5
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,398
    Quote Originally Posted by zapta View Post
    Thanks JBeale. What do you mean? I can do it without ADC.h support? How? Accessing the hardware directly? Any other useful library?

    Also, anybody knows the ETA of ADC.h support for T4? I am surprised that PJRC are selling the T4 without A/D software support. Am I missing something? Do they provide other libraries that support it?
    As you see from JBeale example, direct access to analog ports is part of the Teensy core, so always implemented with ALL Teensies that have build-in ADC

  6. #6
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    677
    If you're curious, here's the implementation of ADC in the Teensy 4 core code: https://github.com/PaulStoffregen/co...ensy4/analog.c
    To (not) answer an earlier question, the adc.h library was done by forum user pedevide (Pedro Villanueva) who AFAIK is a "regular" teensy user like the rest of us here. I do not know if or when he has plans to port it to T4.
    The library code for earlier Teensys is available though if anyone is interested. https://github.com/pedvide/ADC
    Last edited by JBeale; 09-29-2019 at 07:53 AM.

  7. #7
    Thanks JBeale. That example is of ADC with blocking calls, right? Is there an example for a non blocking ADC for T4? For example, something similar to what described here https://www.pjrc.com/teensy/adc.html ?

    I would expect PJRC to clarify for potential buyers that some of the examples they provide with Arduino, for example the ADC | test_pdb which is listed when I select board=t4, where not yet ported to T4.

  8. #8
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    677
    Correct, analogRead() is a blocking call in my example, just as in all other Arduino-alike devices AFAIK. The return value is the ADC reading just made. It is not a terribly long delay on T4; less than 6 microseconds as shown. If that's still too long to wait, then you need to write your own non-blocking implementation, since I'm not aware of one yet for T4. If you look at Paul's core T4 ADC code implementing int analogRead(uint8_t pin) it is not terribly complex, here is the heart of it (omitting the ADC2 code, which is basically a copy of this):

    Code:
    	
    uint8_t ch = pin_to_channel[pin];  // convert Arduino style channel number to Teensy internal numbering
    
    if(!(ch & 0x80)) {
      ADC1_HC0 = ch;                       // set ADC channel number
      while (!(ADC1_HS & ADC_HS_COCO0)) ;  // wait until ADC result ready
      return ADC1_R0;                      // return new ADC result
    }
    Here's a reasonably current list of the status of libraries for T4. Under ADC it just says "pedvide's lib needs work" https://forum.pjrc.com/threads/54711...l=1#post193717
    Last edited by JBeale; 09-29-2019 at 11:08 PM.

  9. #9
    Thanks JBeale, this is very useful! I will look also at the existing ADC.h.

    I can squeeze from T3.2 50k double samplings and shallow processing in the ISR, leaving about 60% CPU time to main but I like to have the larger margins that T4 may provide.

  10. #10
    On a second thought, I don't need two interrupts, one for the timer (which starts the ADC) and one for the ADC result. I can do everything in the timer ISR, reading previous value and then triggering next one. Will try to make it work without ADC.h for T3.2 (based on core/analog.c) and then migrate to T4.

  11. #11
    Junior Member
    Join Date
    Dec 2018
    Location
    PNW
    Posts
    14
    Zapta,

    I did just finish a T4 translation of the ADC library. It's not polished, but it works. I put up a thread about it, I hope you can find it useful

  12. #12
    Thanks a lot Bumbler, I will take a look.

    I have a primitive working version that access the registers directly but it doesn't allow to set thing such as sampling and conversions speeds.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •