ADC library, with support for Teensy 4, 3.x, and LC

golden2620,

I suggest you use a independent source for the source. You are using interrupts to generate the source and to read it; this can fail when other higher priority interrupts happen. Also writing to Serial inside an interrupt is not recommended, it is much better to save the values to a buffer and print them in the loop() when it's full.
 
Hi Pedvide,

Just starting to explore the use of your ADC lib.
Great lib, thanks for the fantastic contribution!

How to use ADC lib and Audio lib together in a sketch to mix audio and adc
(using Audio lib mixer: "AudioMixer4 A2A3Mix; ) from ADC0 and ADC1?

What I can figure out -> inputs from A2 and A3,
A2 would use "AudioInputAnalog adc0(A2);",
how about A3 :
int value = adc->analogRead(A3, ADC_1);
ADC::Sync_result result = adc->analogSyncRead(A2, A3);

Then:
AudioConnection patchCord0(adc0,0,A2A3Mix, 0);
AudioConnection patchCord1(adc->(analogRead(A3,ADC_1), 0, A2A3Mix, 0));

Is the above (psudo-)code or something similar even possible ? The above code is illustrative only as I have not actually coded it in a sketch. Just thought I'd run it by you before I go down a path that may not even have a glimmer of hope of working :)

Please, any advice is helpful.
 
You can't do that, unfortunately.
I'm actually working on a "AudioInputAnalog1" object that can be used exactly the same way. However in the future having a AudioInputAnalog object that simply gets the ADCX number as parameter would be ideal.
 
Thank you Pedvide for your information.

Alternately, while you are working on AudioInputAnalog1, I figure I can always use your "Example for synchonized measurements using both ADC present in Teensy 3.1" and implement a basic mixer that is in Paul's Audiolib.

Can you pl. share approximately when your AudioInputAnalog1 may be ready?

Best Regards
 
Is anyone else having issues loading the doc? It gives me an error that appears the file is looking for an E: drive in my file path that isn't there. Somehow I had it working from an older version of the library but the update will not let me move around in the HTML doxygen doc
 
There's something strange with the link, open doxygen/html/index.html directly, that should work.
I'm preparing a update that will break some things, so I wanna test it before committing it to github.
 
Has the library been updated for the 3.6 ? I'm just testing to see how fast it samples, and I'm seeing about 5kHz regardless of the speed that I set:

ADC* adc;

void setup()
{
pinMode(LEDpin, OUTPUT);
adc = new ADC();
adc->setSamplingSpeed(ADC_HIGH_SPEED);
}

void loop()
{
digitalWrite(LEDpin, HIGH);
for (int i = 0; i < 10000; ++i)
ADC::Sync_result result = adc->analogSyncRead(16, 17);
digitalWrite(LEDpin, LOW);
for (int i = 0; i < 10000; ++i)
ADC::Sync_result result = adc->analogSyncRead(16, 17);
}

thanks!
 
Forgive the classic blunder of replying to one's own question, but I cleared up a little of this. Looking through hardware/teensy/avr/libraries/ADC/*, it looks like the 3.6 is actually the 3_5 ?

#elif defined(__MK64FX512__) // Teensy 3.4
#define ADC_TEENSY_3_4
#elif defined(__MK66FX1M0__) // Teensy 3.5
#define ADC_TEENSY_3_5
#else
#error "Board not supported!"
#endif

No biggee, just surprising. Anyways, then I figured out that ::setSamplingSpeed() has to be called for each ADC (assuming you're asking for a "sync" conversion from each.) Again, surprising, but no biggee.

Hope this helps someone. Cheers.
 
The correct names are updated in the github repository!

keraba,
You're only changing the sampling speed, not the conversion speed. The sampling part of a measurement takes a few ADC clock cycles, so it doesn't affect the total measurement time too much. The conversion part usually takes much more time.
Change the conversion speed and you should see the difference.

Also, you need to change both ADC's speeds, now you're only changing ADC0, not ADC1.
 
I used this library with the T32 and found that only certain pairs of pins could be used with the dual synced function. Is this true for the T36 and if so, what pairs are allowed.
 
Thanks for the link. The card that comes with the T36 does not distinguish between ADC0 and ADC1 so this photo will be helpful.

On the T32, I used A2 and A3 and got it to run at 60Ksps when triggered by a timer generated interrupt.
 
Ran a quick test on the T36 using dual synchronized readings and got a little over 2.14Msps. Used the example from the library. This is quite impressive and opens many new possibilities.
 
@Donziboy2
Where did you get the ADC0/ADC1 data for your T36 card addition? I would like to do the same thing for the T32.

PS
I found your T30/31 map but do you have one for the T32?
 
Last edited:
I'm trying to make sense of what I'm seeing from the ADC library. I have a 10k pot across analog GND and 3.3V with the sweeper connected to pin 16(A2). This is on a Teensy 3.6. My set-up looks like:

adc = new ADC();
for (int n = 0; n <= 1; ++n)
{
adc->setConversionSpeed(ADC_MED_SPEED, n);
adc->setResolution(16, n);
}

I'm making "synced" reads. What I'm seeing is roughly:

0V-1.65V: 1 to 32k
1.65V-3.3V: -32k to -1

Is this expected? It kind of looks like a math error, but maybe the chip actually provides values like this?

What I'm doing to correct it is:

if (level < 0)
level += 64k;

If it's a known issue, does anyone know if the above should be this?

if (level <= 0)

Finally, if there's some way to get contiguous values, I'd love to know how.

thanks!
 
I'm trying to make sense of what I'm seeing from the ADC library. I have a 10k pot across analog GND and 3.3V with the sweeper connected to pin 16(A2). This is on a Teensy 3.6. My set-up looks like:

adc = new ADC();
for (int n = 0; n <= 1; ++n)
{
adc->setConversionSpeed(ADC_MED_SPEED, n);
adc->setResolution(16, n);
}

I'm making "synced" reads. What I'm seeing is roughly:

0V-1.65V: 1 to 32k
1.65V-3.3V: -32k to -1

Is this expected? It kind of looks like a math error, but maybe the chip actually provides values like this?

What I'm doing to correct it is:

if (level < 0)
level += 64k;

If it's a known issue, does anyone know if the above should be this?

if (level <= 0)

Finally, if there's some way to get contiguous values, I'd love to know how.

thanks!


Hello Keraba, you need to post the entire code your using.
Please use the code wrapper tags.

edit..
Just took another look. I think its ok, its being treated as a signed value. Also your never going to get 16 bit resolution from the ADC's on the Teensy. 13 bit is about the most you can reliably get.
 
Last edited:
So when you say, "treating it as a signed value", you mean that if the library reads the value like a signed 16 bit number (instead of the unsigned number it's supposed to be), once the "high" bit (bit 15) gets set, the number pops out as negative. That's unfortunate. I'll report the bug. Thanks for the theory.

Anyways, here's the code, including a couple fixes.

Code:
#include <ADC_Module.h>
#include <RingBuffer.h>
#include <ADC.h>
#include <RingBufferDMA.h>

int LEDpin = 13;
int ADC1 = 16;
int ADC2 = 17;

ADC* adc;

void setup()
{
  Serial.begin(38400);
  pinMode(LEDpin, OUTPUT);
  adc = new ADC();
  for (int n = 0; n <= 1; ++n)
  {
    adc->setConversionSpeed(ADC_MED_SPEED, n);
    adc->setResolution(16, n);
  }
}


void loop()
{
  digitalWrite(LEDpin, HIGH);
  int max_level = -100000, min_level = 100000;
  for (int i = 0; i < 30000; ++i)
  {
    ADC::Sync_result result;
    result = adc->analogSyncRead(ADC1, ADC2);
#if 0
    int level = result.result_adc0;

    if (level < 0)
      level += 65536;
#else
    int level = (unsigned short)result.result_adc0;
#endif
    if (level > max_level)
      max_level = level;
    if (level < min_level)
      min_level = level;
  }
  Serial.print(min_level);
  Serial.print(" min ");
  Serial.print(max_level);
  Serial.println(" max");
  digitalWrite(LEDpin, LOW);
  for (int i = 0; i < 30000; ++i)
    adc->analogSyncRead(ADC1, ADC2);
}
 
I may be wrong but I believe its how your calling the value from serial print, you may need to specify the type. dec, hex etc.....
 
But my two changes (in the #if block) fix it. I know that it's difficult to believe that there's a bug in the library, but there's no other explanation. I suspect people are avoiding it by only sampling at 13 bits.
 
But my two changes (in the #if block) fix it. I know that it's difficult to believe that there's a bug in the library, but there's no other explanation. I suspect people are avoiding it by only sampling at 13 bits.

Edit, ok I need to wake up before I post. I need to look at the library a little.
 
Last edited:
I am in the field until Tuesday so I don't have a Teensy to test anything on.

First I would get rid of the for loop below and use the examples of how to setup the ADC's.
Code:
  for (int n = 0; n <= 1; ++n)
  {
    adc->setConversionSpeed(ADC_MED_SPEED, n);
    adc->setResolution(16, n);
  }

I would also switch from ints which are signed to uint32_t or uint16_t if your not doing any addition/subtraction.

Im also not sure if calling RingBuffer.h and RingBufferDMA.h at the same time could cause issues.
 
Back
Top