Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 4 1 2 3 ... LastLast
Results 1 to 25 of 98

Thread: Teensy 4.0 which pins for which ADC

  1. #1
    Junior Member
    Join Date
    Mar 2019
    Posts
    13

    Teensy 4.0 which pins for which ADC

    I have been unable to find a chart that maps out which of the analog read pins is connected to which of the two ADCs on the chip for the Teensy 4.0.
    Could anyone help me find this information?

    Thank you in advance

  2. #2
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    I extracted this from pg3457-3458 of the IMXRT1060 Ref manual and used the pinouts from page 1 of the T4 Beta Thread: Hope it helps:
    Code:
    14/A0	AD_B1_02	ADC1_IN7	Analog channel 1 input 7
    15/A1	AD_B1_03	ADC1_IN8	Analog channel 1 input 8
    16/A2	AD_B1_07	ADC1_IN12	Analog channel 1 input 12
    17/A3	AD_B1_06	ADC1_IN11	Analog channel 1 input 11
    18/A4	AD_B1_01	ADC1_IN6	Analog channel 1 input 6
    19/A5	AD_B1_00	ADC1_IN5	Analog channel 1 input 5
    20/A6	AD_B1_10	ADC1_IN15	Analog channel 1 input 15
    21/A7	AD_B1_11	ADC 2_IN0	Analog channel 2 input 0
    22/A8	AD_B1_08	ADC1_IN13	Analog channel 1 input 13
    23/A9	AD_B1_09	ADC1_IN14	Analog channel 1 input 14
    ---	----		
    24/A10	AD_B0_12	ADC2_IN1	Analog channel 2 input 1
    25/A11	AD_B0_13	ADC2_IN2	Analog channel 2 input 2
    26/A12	AD_B1_14	ADC2_IN3	Analog channel 2 input 3
    27/A13	AD_B1_15	ADC2_IN4	Analog channel 2 input 4
    Last edited by mjs513; 11-14-2019 at 02:15 PM.

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    I might need to double check my spreadsheet, but I have:
    Code:
    Pin	Name		GPIO	Analog
     0	AD_B0_03	1.3	
     1	AD_B0_02	1.2	
     2	EMC_04		4.4	
     3	EMC_05		4.5	
     4	EMC_06		4.6	
    5	EMC_08		4.8	
    6	B0_10		2.10	
    7	B1_01		2.17	
    8	B1_00		2.16	
     9	B0_11		2.11	
    10	B0_00		2.0	
    11	B0_02		2.2	
    12	B0_01		2.1	
    13	B0_03		2.3	
    14/A0	AD_B1_02	1.18	A1:7, A2:7
    15/A1	AD_B1_03	1.19	A1:8, A2:8
    16/A2	AD_B1_07	1.23	A1:12, A2:12
    17/A3	AD_B1_06	1.22	A1:11, A2:11
    18/A4	AD_B1_01	1.17	A1:6, A2:6
    19/A5	AD_B1_00	1.16	A1:5, A2:5
    20/A6	AD_B1_10	1.26	A1:15, A2:15
    21/A7	AD_B1_11	1.27	A1:0, A2:0
    22/A8	AD_B1_08	1.24	A1:13, A2:13
    23/A9	AD_B1_09	1.25	A1:14, A2:14
    ---	----	----	------
    24/A10	AD_B0_12	1.12	A1:1  
    25/A11	AD_B0_13	1.13	A1:2
    26/A12	AD_B1_14	1.30	A2:3  
    27/A13	AD_B1_15	1.31	A2:4  
    28	EMC_32	3.18	
    29	EMC_31	4.31	
    30	EMC_37	3.23	
    31	EMC_36	3.22	
    32	B0_12	2.12	
    33	EMC_07	4.7	
    			
    34	SD_B0_03	2.15	
    35	SD_B0_02	3.14	
    36	SD_B0_01	3.13	
    37	SD_B0_00	3.12	
    38	SD_B0_05	3.17	
    39	SD_B0_04	3.16
    Sorry if things don't align properly...

    Note: As you can see many of these pins can actually connect to either ADC...

    Another side hint is to look at analog.c where it maps pins to channels. Removing the #if 0 stuff... we have:

    Code:
    const uint8_t pin_to_channel[] = { // pg 482
    	7,	// 0/A0  AD_B1_02
    	8,	// 1/A1  AD_B1_03
    	12,	// 2/A2  AD_B1_07
    	11,	// 3/A3  AD_B1_06
    	6,	// 4/A4  AD_B1_01
    	5,	// 5/A5  AD_B1_00
    	15,	// 6/A6  AD_B1_10
    	0,	// 7/A7  AD_B1_11
    	13,	// 8/A8  AD_B1_08
    	14,	// 9/A9  AD_B1_09
    	1,	// 24/A10 AD_B0_12 
    	2,	// 25/A11 AD_B0_13
    	128+3,	// 26/A12 AD_B1_14 - only on ADC2, 3
    	128+4,	// 27/A13 AD_B1_15 - only on ADC2, 4
    	7,	// 14/A0  AD_B1_02
    	8,	// 15/A1  AD_B1_03
    	12,	// 16/A2  AD_B1_07
    	11,	// 17/A3  AD_B1_06
    	6,	// 18/A4  AD_B1_01
    	5,	// 19/A5  AD_B1_00
    	15,	// 20/A6  AD_B1_10
    	0,	// 21/A7  AD_B1_11
    	13,	// 22/A8  AD_B1_08
    	14,	// 23/A9  AD_B1_09
    	1,	// 24/A10 AD_B0_12
    	2,	// 25/A11 AD_B0_13
    	128+3,	// 26/A12 AD_B1_14 - only on ADC2, 3
    	128+4	// 27/A13 AD_B1_15 - only on ADC2, 4
    };
    But this only shows which ones we use, not which ones we could use... Note the 128+ marks those which we map to ADC2.

    Edit: Side note about this above table. It is setup to look like pin 0 is attached as an analog pin, which it is not, instead this is due to the historical way you can call analogRead. That is analogRead(0) is the same thing as analogRead(A0) which in our case is the same as analogRead(14);

  4. #4
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    @KurtE
    Your list is actually better than mine - I missed the second ADC assignment when I went through your list. I must have an outdated spreadsheet -the one I have doesn't have the analog pins.

    Edit: oops - yes it does but is on the beta 1 tab.

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    Good morning @mjs513... Again not sure who might be interested, but I put my Excel documents up on github: https://github.com/KurtE/TeensyDocuments

  6. #6
    Junior Member
    Join Date
    Mar 2019
    Posts
    13
    Great, thank you both very much.

    For the pins that can connect to both ADCs, the decision would be made by choosing an appropriate setting in the code while initializing the pin, correct?

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    I could be wrong, but I believe for those pins which connect to both, it always uses the first one... i.e. the code table in analog.c does not keep mark that it can use either. But since the code for analogRead(pin) does not return until completed, it probably make much difference.

    However hopefully at some point the library ADC will be updated to work on T4. But so far I have not seen anything up on the github project showing any progress toward this.

  8. #8
    Junior Member
    Join Date
    Nov 2019
    Posts
    5
    Quote Originally Posted by KurtE View Post
    I could be wrong, but I believe for those pins which connect to both, it always uses the first one... i.e. the code table in analog.c does not keep mark that it can use either. But since the code for analogRead(pin) does not return until completed, it probably make much difference.

    However hopefully at some point the library ADC will be updated to work on T4. But so far I have not seen anything up on the github project showing any progress toward this.
    Hi KurtE,

    Any idea how to assign pins to a particular ADC, similar to analogRead(XX, ADC_0/ADC_1) in adc.h? I am trying to sample a 15 MHz sine wave using two analog pins and I want them to happen simultaneously. If I understand correctly, analogRead() will be assigned to ADC and it'll take some time to complete before the next analogRead() is performed. I was hoping to use two separate ADCs to do simultaneous measurements.
    Code:
        v1 = analogRead(A2);
        v2 = analogRead(A3);

  9. #9
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    305
    > I am trying to sample a 15 MHz sine wave

    You will need to use an external ADC with parallel output. Or an external track and hold with periodic sampling.

  10. #10
    Junior Member
    Join Date
    Nov 2019
    Posts
    5
    Quote Originally Posted by jonr View Post
    > I am trying to sample a 15 MHz sine wave

    You will need to use an external ADC with parallel output. Or an external track and hold with periodic sampling.
    Thanks. I'm guessing this is because of the sampling rate limitation? How about for much lower frequencies? Is there a way to assign analog pins to specific ADC? I am yet to try Bumbler's T4 ADC Library V0. Maybe I'll give that a shot.

  11. #11
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    @tsaha - As I have mentioned I do most things in digital, so others maybe can help more.

    It would be great if the library ADC was ported over to the T4. But it looks like the owner (pedvide) of it, has not been up on the forum for maybe a year and a half, and the last update to the library was over two years ago...

    So again another useful library that has been semi-orphaned.

    Again as I mentioned, the default call analogRead(pin) will not return until it is done doing the analog conversion. so assigning to the two different ADCs probably would not help you much here..

    Again not sure how hard it would be to setup at least a subset of the ADC library for T4, that allows you to do some of this.
    More details about this library up in the thread: https://forum.pjrc.com/threads/25532...for-Teensy-3-1

    Again I am not sure hard it would be... I might take a quick look to see if at least some of the basics can be ported... But again would be better if someone who really understands and uses Analog stuff would do it!

  12. #12
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    @tasha
    Just to let you know the default settings on initialization is to do a 32 point average using 10bit ADC. You might reduce the time by setting analogReadAveraging. Allowable averages are 4, 8, 16 and 32 point averages.

    Looked at the ADC library a while ago - complicated for me to modify the whole thing but a subset of the library is probably doing for the T4. But as @KurtE haven't looked at it for awhile.

  13. #13
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    @tasha @mjs513 - I hacked up a version of AnalogRead that allowed me to choose a channel 1 or 2 to do conversion.

    Also did a version where I broke it into two parts. First starts conversion, second checks or waits for completion... Parts of it sort of work..

    Not sure how reliable...

    But if you want to take a look:
    Attached Files Attached Files

  14. #14
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    @KurtE
    Thanks. Going to have to update a couple of other functions as well. AnanlogResolution and analogreadaveragering. Just as a note may have to use that other function on reinitialiaztion of changes. Have a couple of other ideas but sick as a dog right now, head in fog argh

  15. #15
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    @KurtE - @Paul

    Was going through analog.c again and was thinking since this is a lite version in order support the second ADC would it be better just to update analog.c to support the second adc?

  16. #16
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    305
    I checked and verified that analogReadAveraging(3) will speed things up. The result with analogRead() was 5 usec per sample.

    With the right code, I'd expect < 1 usec per sample and 2x faster than that when alternating between two ADCs.

    Perhaps others have hard data wrt "how fast is teensy 4 ADC?".

  17. #17
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    @KurtE - @tasha
    Ok tried the other route and adds too much complexity to the situation. So I just added T4AnalogReadRes(pin, adc) as well as T4AnalogReadAveraging(pin, adc) .

    T4_ADC_Lite.zip

  18. #18
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    Quote Originally Posted by mjs513 View Post
    @KurtE - @Paul

    Was going through analog.c again and was thinking since this is a lite version in order support the second ADC would it be better just to update analog.c to support the second adc?
    My quick look through the functions, analogResolution and analogReadAveraging, I thought they were both already handling both ADC1 and ADC2

    Example analogReadRes:
    Code:
    void analogReadRes(unsigned int bits)
    {
      uint32_t tmp32, mode;
    
       if (bits == 8) {
        // 8 bit conversion (17 clocks) plus 8 clocks for input settling
        mode = ADC_CFG_MODE(0) | ADC_CFG_ADSTS(3);
      } else if (bits == 10) {
        // 10 bit conversion (17 clocks) plus 20 clocks for input settling
        mode = ADC_CFG_MODE(1) | ADC_CFG_ADSTS(2) | ADC_CFG_ADLSMP;
      } else {
        // 12 bit conversion (25 clocks) plus 24 clocks for input settling
        mode = ADC_CFG_MODE(2) | ADC_CFG_ADSTS(3) | ADC_CFG_ADLSMP;
      }
    
      tmp32  = (ADC1_CFG & (0xFFFFFC00));
      tmp32 |= (ADC1_CFG & (0x03));  // ADICLK
      tmp32 |= (ADC1_CFG & (0xE0));  // ADIV & ADLPC
    
      tmp32 |= mode; 
      ADC1_CFG = tmp32;
      
      tmp32  = (ADC2_CFG & (0xFFFFFC00));
      tmp32 |= (ADC2_CFG & (0x03));  // ADICLK
      tmp32 |= (ADC2_CFG & (0xE0));  // ADIV & ADLPC
    
      tmp32 |= mode; 
      ADC2_CFG = tmp32;
    }
    Currently analog.c only supports doing one analog operation at a time. So it only bothers to use ADC2 if you asked for one of the few pins that only have support on ADC2.

    And likewise in "lite ADC" code I put in above sketch, there are a few pins that only are on ADC1... Which I marked (actually there are a couple of them I did not mark yet (that is most of the pins are in this table twice (one for the actual pin number and the other for the A number)...

    I am not sure what else to do for a Light version... Could create another simple method like:
    Code:
    bool T4AnalogRead(uint8_t adc1_pin, uint16_t &adc1_val, uint8_t adc2_pin, uint16_t &adc2_val);
    Obviously there is a ton of other stuff that one could try, like DMA support or other form of continuous updates, ...

    But that probably is a very big diversion

  19. #19
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,308
    @KurtE

    Yep it handles them but it setups up the same resolution and averaging for both channels (ADC1 and ADC2). At least I think that is how it is currently working. Changing it this way allows you to change them on a channel basis. Again haven't tested it yet.

    Quote Originally Posted by KurtE
    Obviously there is a ton of other stuff that one could try, like DMA support or other form of continuous updates, ...

    But that probably is a very big diversion
    Oh - big diversion! [EDIT] and I just went back to playing with usbhost

  20. #20
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    @mjs513 I went ahead and hacked in the function I mentioned...
    Also put in loop calls to set the averaging... Although I just used the default one so far..
    T4_ADC_Lite-191202b.zip

    usbHost - Something new and shiny to play with?

  21. #21
    Junior Member
    Join Date
    Nov 2019
    Posts
    5
    Quote Originally Posted by jonr View Post
    I checked and verified that analogReadAveraging(3) will speed things up. The result with analogRead() was 5 usec per sample.

    With the right code, I'd expect < 1 usec per sample and 2x faster than that when alternating between two ADCs.

    Perhaps others have hard data wrt "how fast is teensy 4 ADC?".
    Click image for larger version. 

Name:	IMXRT1060RM_rev1_pdf__page_3_468_of_3_637_.jpg 
Views:	5 
Size:	124.2 KB 
ID:	18323

    Based on the manual, 0.85 us is possible. Also, analogReadAveraging(X), where X<4, should turn off hardware averaging, is that correct?

    Code:
    void analogReadAveraging(unsigned int num)
    {
      uint32_t mode, mode1;
      
      //disable averaging, ADC1 and ADC2
      ADC1_GC &= ~0x20;
      mode = ADC1_CFG & ~0xC000;
      ADC2_GC &= ~0x20;
      mode1 = ADC2_CFG & ~0xC000;
      
        if (num >= 32) {
          mode |= ADC_CFG_AVGS(3);
          mode1 |= ADC_CFG_AVGS(3);
    
        } else if (num >= 16) {
          mode |= ADC_CFG_AVGS(2);
          mode1 |= ADC_CFG_AVGS(2);
    
        } else if (num >= 8) {
          mode |= ADC_CFG_AVGS(1);
          mode1 |= ADC_CFG_AVGS(1);
    
        } else if (num >= 4) {
          mode |= ADC_CFG_AVGS(0);
          mode1 |= ADC_CFG_AVGS(0);
    
        } else {
          mode |= 0;
          mode1 |= 0;
        }
    
      ADC1_CFG |= mode;
      ADC2_CFG |= mode1;
      
      if(num >= 4){
          ADC1_GC |= ADC_GC_AVGE;// turns on averaging
          ADC2_GC |= ADC_GC_AVGE;// turns on averaging
      }
    }

  22. #22
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    305
    Looks like there is some kind of bug. The first time it hits 4 the time is 36. The second time it is 279.


    Quick and dirty T4 Analog Read stuff
    1> 4 2 10 : 2 3 10 : 1 3 5 : 1 2 5
    2> 1 2 10 : 2 0 10 : 0 1 5 : 1 0 5
    4> 5 6 36 : 6 3 36 : 6 4 18 : 6 4 18
    8> 7 6 71 : 7 4 71 : 6 4 35 : 6 4 36
    16> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
    32> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
    64> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
    1> 1 2 10 : 2 0 10 : 1 2 5 : 1 1 5
    2> 0 2 10 : 2 0 10 : 1 5 5 : 0 5 5
    4> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
    8> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
    16> 7 7 279 : 7 4 280 : 7 4 142 : 7 4 141
    32> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141
    64> 7 7 279 : 7 4 281 : 7 4 141 : 7 4 141

  23. #23
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    Yep does sort of look like maybe a bug? Will take a look later

  24. #24
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,733
    Yes it is a bug in the analogReadAveraging

    Code:
    1(000006b7 00000000)> 7 507 10 : 19 507 10 : 1 507 5 : 2 507 5
    2(000006b7 00000000)> 1 507 10 : 19 507 10 : 1 514 5 : 1 507 5
    4(000006b7 00000020)> 8 515 36 : 12 515 36 : 8 517 18 : 8 513 19
    8(000046b7 00000020)> 9 517 71 : 11 517 71 : 9 516 36 : 9 517 35
    16(0000c6b7 00000020)> 10 517 280 : 10 517 281 : 9 517 141 : 9 517 142
    32(0000c6b7 00000020)> 10 517 280 : 10 518 281 : 9 518 141 : 9 517 142
    64(0000c6b7 00000020)> 9 518 280 : 10 517 281 : 9 518 141 : 9 517 142
    1(0000c6b7 00000000)> 1 507 10 : 19 507 10 : 1 507 5 : 1 507 5
    2(0000c6b7 00000000)> 1 507 10 : 19 507 10 : 1 513 5 : 1 507 5
    4(0000c6b7 00000020)> 9 518 280 : 10 517 281 : 9 518 141 : 9 517 142
    8(0000c6b7 00000020)> 10 517 280 : 10 517 281 : 9 518 141 : 9 517 141
    16(0000c6b7 00000020)> 9 518 280 : 10 517 281 : 9 518 141 : 9 518 141
    32(0000c6b7 00000020)> 10 517 280 : 10 517 281 : 9 517 141 : 10 518 141
    64(0000c6b7 00000020)> 9 517 280 : 10 518 281 : 9 518 141 : 9 518 141
    As you can see it is not properly updating the ADC1_CFG field (assume ADC2 as well)
    Code:
      Serial.printf("%u(%08x %08x)> %d %d %u : %d %d %u : %d %d %u : %u %u %u\n",
                    averaging_count,ADC1_CFG, ADC1_GC,
                    a0, a1, t2 - t1,
                    a0_4, a1_4, t3 - t2,
                    a0_4C, a1_4C, t4 - t3,
                    a0_both, a1_both, t5 - t4);
    Looks like: void analogReadAveraging is buggy!

    That is: look at how ADC1_CFG is updated.
    Code:
    void analogReadAveraging(unsigned int num)
    {
      uint32_t mode, mode1;
      
      //disable averaging, ADC1 and ADC2
      ADC1_GC &= ~0x20;
      mode = ADC1_CFG & ~0xC000;
      ADC2_GC &= ~0x20;
      mode1 = ADC2_CFG & ~0xC000;
      
        if (num >= 32) {
          mode |= ADC_CFG_AVGS(3);
          mode1 |= ADC_CFG_AVGS(3);
    
        } else if (num >= 16) {
          mode |= ADC_CFG_AVGS(2);
          mode1 |= ADC_CFG_AVGS(2);
    
        } else if (num >= 8) {
          mode |= ADC_CFG_AVGS(1);
          mode1 |= ADC_CFG_AVGS(1);
    
        } else if (num >= 4) {
          mode |= ADC_CFG_AVGS(0);
          mode1 |= ADC_CFG_AVGS(0);
    
        } else {
          mode |= 0;
          mode1 |= 0;
        }
    
      ADC1_CFG |= mode;
      ADC2_CFG |= mode1;
      
      if(num >= 4){
          ADC1_GC |= ADC_GC_AVGE;// turns on averaging
          ADC2_GC |= ADC_GC_AVGE;// turns on averaging
      }
    }
    If you look at the RED lines. The variable mode is assigned the current value of the ADC1_CFG minus the bits associated with ADC_CFG_AVGS(n)... Which is fine, and then we update the mode variable to have the proper value for those bits, and then we or mode back into ADC1_CFG

    First fix attempt:
    Code:
      ADC1_CFG = mode;
      ADC2_CFG = mode1;
    That appears to work, so I pushed the change up to github cores
    @Paul - if you are looking it is in my currently pending PR in cores: https://github.com/PaulStoffregen/cores/pull/404

    Also updated sketch version as well, and change sketch to use it...T4_ADC_Lite-191202c.zip

  25. #25
    Junior Member
    Join Date
    Nov 2019
    Posts
    5
    Quote Originally Posted by KurtE View Post

    That appears to work, so I pushed the change up to github cores
    @Paul - if you are looking it is in my currently pending PR in cores: https://github.com/PaulStoffregen/cores/pull/404

    Also updated sketch version as well, and change sketch to use it...T4_ADC_Lite-191202c.zip
    Thanks @KurtE. I'll give this a go. For analogRead() statements for two pins with 1 average and 10 bits of resolution, it takes about 10us to complete. Let's see if using separate ADCs makes any difference.

Posting Permissions

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