Coder Social home page Coder Social logo

adc's Introduction

ADC

Teensy 3.0, 3.1, 3.2, LC, 3.5, 3.6, 4, 4.1 ADC implementation library created by Pedro Villanueva.

See examples and documentation.

If you download the library from here, also install the latest Teensyduino version at https://www.pjrc.com/teensy/td_download.html.

This thread in the Teensy forum also has information: http://forum.pjrc.com/threads/25532-ADC-library-update-now-with-support-for-Teensy-3-1

License

Teensy 4.x, 3.x, LC ADC library https://github.com/pedvide/ADC Copyright (c) 2022 Pedro Villanueva

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

adc's People

Contributors

aforren1 avatar drf5n avatar ericfont avatar ivankravets avatar jimparis avatar kurte avatar paulhayes avatar pedvide avatar valeros avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

adc's Issues

ADC speed with Teensy 3.1

This isn't really an issue but more of a question.
I am having a bit of a hard time understanding how fast the sampling speed can go.
"ADC_HIGH_SPEED is guaranteed to be the highest possible speed within specs for resolutions less than 16 bits (lower or eq than 18 MHz)."
So in this setting the Teensy 3.1 can go up tp 18MHz?
Well why does the AnalogContinuousRead example then say:
"At 96 Mhz (bus at 48 MHz), 632 KHz is the fastest we can do within the specs, and only if the sample's impedance is low enough."
I don't get it. :)

undefined reference to `AnalogBufferDMA::init(ADC*, signed char)' in PlatformIO Release

The current Teensy_ADC PlatformIO library version (8.0.38) throws an error when compiling the adc_dma example:

undefined reference to AnalogBufferDMA::init(ADC*, signed char)

I noticed that this error is already fixed in the master branch (#ifdef ADC_USE_DMA must be moved below the includes in AnalogBufferDMA.h and AnalogBufferDMA.cpp).
Would it be possible to release a new PlatformIO library with this fix included?

small changes

With the new Teensy3 R19 ide Paul included some of the required definitions inside mk20dx128.h file in Teensy core but I haved to modeify all occourrances of:

ADC0_PGA_PGAEN

to

ADC_PGA_PGAEN

inside ADC_Module.cpp module to get compile without errors.

PS
Really great and useful work, thanks for sharing!

pinMode issue

From a private message:

Change any:

pinMode(A0, INPUT);
to
pinMode(A0, INPUT_DISABLE); // disable digital keeper resistors

The former can interfere with linearity.

More importantly, I think you turn interrupts on, which creates problems for low jitter ADC. If a user has interrupts off, they should remain off.

RingBufferDMA doesn't work with ADC_1

Since ADC_Module.h is not included in RingBufferDMA.h, the ADC_NUM_ADCS is not defined so DMAMUX_SOURCE_ADC does not get set to DMAMUX_SOURCE_ADC1.

//RingBufferDMA.cpp
uint8_t DMAMUX_SOURCE_ADC = DMAMUX_SOURCE_ADC0;
#if ADC_NUM_ADCS>=2
if(ADC_number==1){
    //this block never gets executed if ADC_NUM_ADCS is not defined
    DMAMUX_SOURCE_ADC = DMAMUX_SOURCE_ADC1;
}
    #endif // ADC_NUM_ADCS

Reduce the ADC object API

The ADC object API has many methods, which increases the code to maintain.
Methods like analogRead and similar make sense, but methods like enableDMA or isContinuous always need the ADC number, so probably they should be accessed via adc->adcNUM->method.

Error compiling (VREF_SC_MODE_LV_HIGHPOWERBUF)

Hi,

Trying to use your library (master branch), got this error:

In file included from /home/psc/11h11/electro/arduino-1.8.3/hardware/teensy/avr/libraries/ADC/ADC_Module.cpp:36:0:
/home/psc/11h11/electro/arduino-1.8.3/hardware/teensy/avr/libraries/ADC/VREF.h:23:38: error: 'VREF_SC_MODE_LV_HIGHPOWERBUF' was not declared in this scope
     inline void start(uint8_t mode = VREF_SC_MODE_LV_HIGHPOWERBUF, uint8_t trim = 0x20) {
                                      ^
Error compiling for board Teensy 3.2 / 3.1.

T_4.1 DMA example

forum post : https://forum.pjrc.com/threads/61451-Teensyduino-1-53-Beta-2?p=243846&viewfull=1#post243846

Also note: TD 1.53 is in Beta - is ADC ready to get an update in TeensyDuino? Short time frame with new IDE 1.8.13 release.

The example : \libraries\ADC\examples\ adc_dma
uses unsupported setcommands:

// adc->setAveraging(8, ADC_1); // set number of averages
// adc->setResolution(12, ADC_1); // set bits of resolution
adc->adc1->setAveraging(8);
adc->adc1->setResolution(12);

Differential gain settings not working correctly

I was trying out the differential conversion options with various gain settings and I noticed that x8 and x16 settings seems to not be correct. I did a little sketch to read the same signal at 1,2,4,8,16,32x gain settings and these are the results (Teensy 3.2, A10,A11 inputs, 16-bit resolution)

1088, 2102, 3764, 7278, 9730, 17340
different level
502, 944, 1716, 3118, 4402, 8102

The signal is from a wheatstone bridge with a 3.3V supply so the common mode voltage is about 1.65V

// Differential reads adc->enablePGA(1); value = adc->adc0->analogReadDifferential(A10, A11); // read a new value, will return ADC_ERROR_VALUE if the comparison is false. Serial.print(value); Serial.print(", "); adc->enablePGA(2); value = adc->adc0->analogReadDifferential(A10, A11); // read a new value, will return ADC_ERROR_VALUE if the comparison is false. Serial.print(value); Serial.print(", "); adc->enablePGA(4); value = adc->adc0->analogReadDifferential(A10, A11); // read a new value, will return ADC_ERROR_VALUE if the comparison is false. Serial.print(value); Serial.print(", "); adc->enablePGA(8); value = adc->adc0->analogReadDifferential(A10, A11); // read a new value, will return ADC_ERROR_VALUE if the comparison is false. Serial.print(value); Serial.print(", "); adc->enablePGA(16); value = adc->adc0->analogReadDifferential(A10, A11); // read a new value, will return ADC_ERROR_VALUE if the comparison is false. Serial.print(value); Serial.print(", "); adc->enablePGA(32); value = adc->adc0->analogReadDifferential(A10, A11); // read a new value, will return ADC_ERROR_VALUE if the comparison is false. Serial.print(value); Serial.println();

Bug in void ADC_Module::stopContinuous()?

Hello,
nice work. :-)

Line 1127 ff:
// decrease the counter of measurements (unless it's 0)
if(!num_measurements) {
num_measurements--;
}

I guess, it should read:
if(num_measurements) {

Best wishes, kukks1

Inconsistencies in tables sc1a2channelADC0 and 1 for Teensy 3.1

I think I've found some inconsistencies in file ADD.cpp (the latest version this time) in the table sc1a2channelADC0 for Teensy 3.0 and 3.1:

if defined(ADC_TEENSY_3_0) || defined(ADC_TEENSY_3_1)

const uint8_t ADC::sc1a2channelADC0[]= { // new version, gives directly the pin number
34, 0, 0, 36, 23, 14, 20, 21, 16, 17, 0, 0, 19, 18, // 0-13
15, 22, 23, 0, 0, 35, 0, 37, // 14-21
39, 40, 0, 0, 38, 41, 42, 43, // VREF_OUT, A14, temp. sensor, bandgap, VREFH, VREFL.
0 // 31 means disabled, but just in case
};

Shouldn't the second 23 be a 0 ?
Shouldn't a 0 be inserted between 41 and 42 to have a table with 32 entries ?

And also in the table sc1a2channelADC1 :

const uint8_t ADC::sc1a2channelADC1[]= { // new version, gives directly the pin number
36, 0, 0, 34, 28, 26, 29, 30, 16, 17, 0, 0, 0, 0, // 0-13. 5a=26, 5b=27, 4b=28, 4a=31
0, 0, 0, 0, 39, 37, 0, 0, // 14-21
0, 0, 0, 0, 38, 41, 0, 42, // 22-29. VREF_OUT, A14, temp. sensor, bandgap, VREFH, VREFL.
43
};

Shouldn't a 0 be inserted at the end to have a table with 32 entries ?

Suggestion: adc->ReferenceVoltage

I do the following:

const float ReferenceVoltage = 1.2;
adc->setReference(ADC_REF_ALT);
...
result=adc->analogRead(PinMesswert) * ReferenceVoltage / adc->getMaxValue(ADC_0);

As far as I see I have to declase the referencevoltage. on the other hand the hardware definition prescribs this value if I use ADC_REF_ALT on that platform.

So why not do move that knowledge into the object and make it automatic? Having

adc->setReference(ADC_REF_ALT);
...
result=adc->analogRead(PinMesswert) * adc->ReferenceVoltage / adc->getMaxValue(ADC_0);

would look and feel much nicer to me.

USB Audio

I'm not sure if I have stumbled across a problem or if im just holding my tongue the wrong way.

I was building a device that is destined to bring in audio to a Teensy 3.2 via pin 2, run a filter over it then fire it out the DAC. I wanted to have a play with a few filter settings and as I was lacking some cables decided just to add a USBin and USBout then play some audio in to the USBin and listen to it on the USBout.

The ADC is destined to be used for setting the filters using POT's connected to ADC1,

The problem seems to lay with this part of the code.
ADC *adc = new ADC();
As soon as I add that i get no audio, however if i comment it out i get audio.

'#include <Audio.h>
#include <Wire.h>
#include <ADC.h> //ADCZ to read the POT values
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h> //Button Library

// GUItool: begin automatically generated code
AudioInputAnalog adc1(A2); //xy=55,28
AudioInputUSB usb1; //xy=59,28

AudioOutputUSB usb2; //xy=218,28
AudioOutputI2S i2s1; //xy=365,94
AudioOutputAnalog dac1; //xy=1008,75

AudioConnection patchCord1(usb1, 0, usb2, 0);
AudioConnection patchCord2(usb1, 1, usb2, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=302,184
// GUItool: end automatically generated code

Bounce button0 = Bounce(2, 15);

const int ledPin = 13;
int knob = A17; // Effects Knob

//Problem here!! If i comment it out I get audio, if its active i get no audio out the USB
//ADC *adc = new ADC(); // adc object

int knobval = 0;

void setup() {
Serial.begin(115200);
AudioMemory(24);

pinMode(knob, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(2, INPUT_PULLUP);   //mode select button

delay(500);           //Give us some delay while the system sets itself up

}

void loop() {
float vol = usb1.volume();

delay(100);
}`

About the sample rate

Hello, sorry to bother you but I have a problem now to set the sample rate. I learned from your documentation that I can change the sample rate by adc->setSamplingSpeed(SPEED), and the speed can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED, but I want to know the exact sample rate for the further algorithm, and I don't need a very high sample rate(441000 is enough).

I found that the sample rate is not stable when I use adc->setSamplingSpeed(SPEED), for example I got about 272000 data for two seconds, and got 460650 data for four seconds when I set the same sample rate.

So what should I do if I want an accurate sample rate? How to set it? Sorry to bother you, thanks a lot!

startSynchronizedSingleDifferential() + readSynchronizedSingle() != analogSynchronizedReadDifferential()

In attempting to convert my code from a blocking to non-blocking code sequence, it appears that the code

... = analogSynchronizedReadDifferential(...)

returns a different result to

startSynchronizedSingleDifferential(...)
... do some other work and/or wait for an interrupt ...
... = readSynchronizedSingle()

The result had both glitching and a different voltage level. Eyeballing the code it seems that the code from analogSynchronizedReadDifferential is not fully implemented in the asynchronous equivalent, and I had to modify readSynchronizedSingle() to get it working:

// Reads the analog value of a single conversion.
/*
*   \return the converted value.
*/
ADC::Sync_result ADC::readSynchronizedSingle() {
    Sync_result res = {ADC_ERROR_VALUE, ADC_ERROR_VALUE};;

    uint8_t resolution0 = adc0->getResolution();
    uint8_t resolution1 = adc1->getResolution();

    // ensure both ADCs have finished
    while( (adc0->isConverting()) || (adc1->isConverting()) ) {
        yield();
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
    }
    __disable_irq(); // make sure nothing interrupts this part
    if (adc0->isComplete()) { // conversion succeded
        res.result_adc0 = adc0->readSingle();
        if(resolution0==16) { // 16 bit differential is actually 15 bit + 1 bit sign
            res.result_adc0 *= 2; // multiply by 2 as if it were really 16 bits, so that getMaxValue gives a correct value.
        }
    } else { // comparison was false
        adc0->fail_flag |= ADC_ERROR_COMPARISON;
    }
    if (adc1->isComplete()) { // conversion succeded
        res.result_adc1 = adc1->readSingle();
        if(resolution1==16) { // 16 bit differential is actually 15 bit + 1 bit sign
            res.result_adc1 *= 2; // multiply by 2 as if it were really 16 bits, so that getMaxValue gives a correct value.
        }
    } else { // comparison was false
        adc1->fail_flag |= ADC_ERROR_COMPARISON;
    }
    __enable_irq();

    // if we interrupted a conversion, set it again
    if (adc0->adcWasInUse) {
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        adc0->loadConfig(&adc0->adc_config);
    }
    if (adc1->adcWasInUse) {
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        adc1->loadConfig(&adc1->adc_config);
    }

    //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );

    return res;
}

I haven't looked at other read* functions to see if they suffer from similar problems.

It would be good to see this fixed in the library, or (if the intention of readSynchronizedSingle() is not the above) to better document what readSynchronizedSingle() is intended for, and to provide a function to complete a non-blocking conversion in a way that is equivalent to the blocking version.

DMA ringbuffer fills only half the buffer

Hi,

If you try the DMA ringbuffer with the Teensy 3.1, it does not work as expected : only half the buffer is filled, I think that the correction needs to be done on line 85, you should have 2 * b_size for the second argument which I believe is in bytes, the comment is already pointing to that possible issue

dmaChannel->destinationCircular((uint16_t_)p_elems, 2 * b_size); // 2_b_size is necessary for some reason

There is a side effect if you set this to 2 * b_size, the IsFull function as written now detect the half-full condition .. I am not completely clear on how to use the IsEmpy and IsFull function, it would be more convenient to have a function telling you what is the present level of the buffer.

Anyway, the package is very interesting and usefull some comments could improve its usage

Yours
Vincent

Support for Teensy 4

Currently the codebase doesn't support Teensy 4, and just gives the message:

 #error "Board not supported!"
  ^
Error compiling for board Teensy 4.0.

Thanks,

Matt

Compile error: enum assignment is now an error

Hi! I'm using a newer compiler (https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads/7-2018-q2-update) which now reports this line as an error:

In file included from /home/me/arduino/hardware/teensy/avr/libraries/ADC/ADC.h:45:0,
                 from /home/me/arduinotems/src/pickled/pickled.ino:17:
/home/me/arduino/hardware/teensy/avr/libraries/ADC/ADC_Module.h:130:31: error: could not convert 'REF_DEFAULT' from 'ADC_REF_SOURCE' to 'uint8_t {aka unsigned char}'
     REF_3V3 = ADC_REF_SOURCE::REF_DEFAULT, /*!< 3.3 volts */
                               ^~~~~~~~~~~
/home/me/arduino/hardware/teensy/avr/libraries/ADC/ADC_Module.h:131:31: error: could not convert 'REF_ALT' from 'ADC_REF_SOURCE' to 'uint8_t {aka unsigned char}'
     REF_1V2 = ADC_REF_SOURCE::REF_ALT, /*!< 1.2 volts */
                               ^~~~~~~
/home/me/arduino/hardware/teensy/avr/libraries/ADC/ADC_Module.h:132:31: error: could not convert 'REF_DEFAULT' from 'ADC_REF_SOURCE' to 'uint8_t {aka unsigned char}'
     REF_EXT = ADC_REF_SOURCE::REF_DEFAULT, /*!< External VREF */
                               ^~~~~~~~~~~
/home/me/arduino/hardware/teensy/avr/libraries/ADC/ADC_Module.h:133:28: error: could not convert 'REF_NONE' from 'ADC_REF_SOURCE' to 'uint8_t {aka unsigned char}'
     NONE = ADC_REF_SOURCE::REF_NONE // internal, do not use
                            ^~~~~~~~
Error compiling for board Teensy 3.2 / 3.1.

Code at:

REF_3V3 = ADC_REF_SOURCE::REF_DEFAULT, /*!< 3.3 volts */

Let me know if I can help further... Thanks!

ADC::sc1a2channelADC1 is not correct for T3.5/T3.6

It looks like the table was a simple copy of the T3.2 version of the table. I have not yet also verified if the other table for ADC0 is correct or not, but I believe the correct values for this table is:

#elif defined(ADC_TEENSY_3_5) || defined(ADC_TEENSY_3_6)
const uint8_t ADC::sc1a2channelADC1[]= { // new version, gives directly the pin number
    0, 69, 0, 0, 35, 36, 37, 38, 0, 0, 49, 50, 0, 0, // 0-13.
    31, 32, 0, 39, 71, 65, 0, 0, // 14-21
    0, 67, 0, 0, 0, 0, 0, 0, // 22-29.
    0
};
#endif

Teensy 4.1: Resolution can't be set to 16 bits

I've experienced the problem, that my resolution will max out at 12 bit with the Teensy 4.1.
Shouldn't the Teensy 4.1 be capable of reading analog values with a resolution of 16 bits?

enableInterrupts gives error on teensy 3.2

I'm newbe in programming i try to compile simple TeensyLoadcell by https://github.com/luni64/TeensyLoadcell

it keeps giving me an error can you please help?

void enableInterrupts(void (*isr)(void), uint8_t priority = 255);

  ^

C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\ADC/ADC_Module.h:184:10: note: candidate expects 2 arguments, 0 provided

Error compiling for board Teensy 3.2 / 3.1.

`#include "ADC.h"
#include "TeensyLoadcell.h"
using namespace TeensyLoadcell;

ADC adc;
Loadcell loadcell(adc.adc0);

void setup(){
loadcell.start();
}

void loop(){
Serial.println(loadcell.getValue());
delay(100);
}`

`#include "TeensyLoadcell.h"
#include "ADC.h"

#if ADC_USE_PGA == 0
#error "Board has no PGA"
#endif

namespace TeensyLoadcell
{
static Loadcell *activeLCO[2]; // will point to current Loadcell objects, the pointers are required by the ISR to access the object

// ISR, Read values and calculate exponential average.
template
void Loadcell_ISR()
{
Loadcell *l = activeLCO[n];
float curVal = l->adc->readSingle();
l->average = l->average + l->alpha * (curVal - l->average); //https://en.wikipedia.org/wiki/Exponential_smoothing
}

//----------------------------------------------------------------------------------

Loadcell::Loadcell(ADC_Module *adc, float tau, Gain gain, unsigned sampleFreq)
{
this->adc = adc;
this->sampleFreq = sampleFreq;

  pinP = adc->ADC_num == 0 ? A10 : A12;
  pinN = adc->ADC_num == 0 ? A11 : A13;

  pinMode(pinP, INPUT);
  pinMode(pinN, INPUT);

  adc->setAveraging(32);
  adc->setResolution(13);
  adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED);
  adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED);
  adc->setReference(ADC_REFERENCE::REF_1V2);
  adc->enablePGA(gain);

  c0 = 0.0f;
  c1 = 1.0f;

  setTau(tau);

}

//-----------------------------------------------------------------

Loadcell::~Loadcell()
{
stop();
}

//-----------------------------------------------------------------

void Loadcell::start()
{

  // attach correct ISR depending on ADC module number
  if (adc->ADC_num == 0)
  {
     activeLCO[0] = this;
     attachInterruptVector(IRQ_ADC0, Loadcell_ISR<0>);
  }
  else
  {
     activeLCO[1] = this;
     attachInterruptVector(IRQ_ADC1, Loadcell_ISR<1>);
  }
  average = 0.0f;

  adc->stopPDB();
  adc->startSingleDifferential(pinP, pinN);
  adc->enableInterrupts();
  adc->startPDB(sampleFreq);

}

//-----------------------------------------------------------------

void Loadcell::stop()
{
adc->stopPDB();
adc->disableInterrupts();
activeLCO[adc->ADC_num] = nullptr;
}

//-----------------------------------------------------------------

void Loadcell::setTau(float tau)
{
if (tau <= 0.0f)
{
alpha = 1.0f;
}
else
{
alpha = 1 - expf(-1.0f / (tau * sampleFreq)); //https://en.wikipedia.org/wiki/Exponential_smoothing
}
}

//-----------------------------------------------------------------

void Loadcell::tare()
{
c0 = average;
}

} // namespace TeensyLoadcell

#pragma once

#include "ADC.h"

namespace TeensyLoadcell
{
enum Gain : uint8_t
{
gain_1 = 1,
gain_2 = 2,
gain_4 = 4,
gain_8 = 8,
gain_16 = 16,
gain_32 = 32,
gain_64 = 64
};

class Loadcell
{
public:
// Constructor, tau is the smoothing time constant in seconds.
Loadcell(ADC_Module *adc, float tau = 1.0, Gain gain = gain_64, unsigned sampleFreq = 5000u);
~Loadcell();

  /* Starts continous background conversion.*/
  void start();

  /*Stops background conversions*/
  void stop();

  /* Gets the averaged, calibrated value. Calibration coefficients can be set by setCalib(c0, c1) */
  inline float getValue() { return (average - c0) * c1; }

  // set the smoothing time constant in seconds. Values will be stable after about 5* tau.
  void setTau(float tau);


  // tares the load cell (sets c0 such that getValue() returns 0 )
  void tare();

  // calibration factors. getValue() returns "(average-c0) * c1"
  float c0 = 0.0f, c1 = 1.0f;

  // delete copy constructor
  Loadcell(const Loadcell &) = delete;

protected:
ADC_Module *adc;
volatile float average = 0.0f; // current averaged measurement value
uint8_t pinP, pinN; // used input pin pair

  float alpha;                     // smoothing factor
  unsigned sampleFreq;             // used sample frequency for the PDB


  template<unsigned n> friend void Loadcell_ISR(); // let the ADC ISR update the measurement value (average)

};

} // namespace TeensyLoadcell`

Protect from irq?

Hola Pedro. Great work. I have a suggestion.
Could it be helpful to protect read() against IRQ? I think the case when write() is called from inside an irq is very popular. This may corrupt some variables if colliding with read().
Regards. Eduardo

Simultaneous DAC?

Hi, is there a way to run the DAC simultaneously with two ADC inputs? I would like to generate a waveform and measure the response in my experiment. After running the DMA for some length of data, how do I regain access for single read calls?
Thank you

ADC not working with Teensyduino 4.0

When I try to include ADC.h and compile with Teensyduino 4.0, I get the following errors below:
If I compile with Teensyduino 3.6, there are no errors generated.
I am running Teensyduino verion 1.53, the newest version, and I have ADC verion 8.0.0 installed..
I am running the Arduino IDE on a Linux machine, IDE verion 1.8.5

/home/rj/Downloads/arduino-1.8.5/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In constructor 'RingBufferDMA::RingBufferDMA(volatile int16_t*, uint32_t, uint8_t)':
/home/rj/Downloads/arduino-1.8.5/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:33:19: error: 'ADC0_RA' was not declared in this scope
, ADC_RA(&ADC0_RA + (uint32_t)0x20000ADC_number)
^
/home/rj/Downloads/arduino-1.8.5/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In member function 'void RingBufferDMA::start(void (
)())':
/home/rj/Downloads/arduino-1.8.5/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:64:30: error: 'DMAMUX_SOURCE_ADC0' was not declared in this scope
uint8_t DMAMUX_SOURCE_ADC = DMAMUX_SOURCE_ADC0;
^
Multiple libraries were found for "ADC.h"
Used: /home/rj/Downloads/arduino-1.8.5/hardware/teensy/avr/libraries/ADC
Not used: /home/rj/Arduino/libraries/ADC-master
Error compiling for board Teensy 4.0.

Spontaneous ADC failure

Has anyone ever experienced a spontaneous permanent failure of the ADC on the K60 line of MCUs? There is a thread on the NXP forum (https://community.nxp.com/thread/381051) , and I have recently encountered this same very strange problem with the Teensy 3.6 using this ADC library. I apologize that my question is not directly related to this library, but I'm hoping someone has heard of this or has an idea of what could possibly cause it.

enableInterrupts API changed: adc->enableInterrupts(adc0_isr, ADC_0);

Many of the examples still have in them calls like:

adc->enableInterrupts(adc0_isr, ADC_0);
adc->enableInterrupts(adc1_isr, ADC_1);

Which does not work properly as you now have another parameter for Interrupt priority.
So for example the second call below still sets interrupts on ADC_0 at priority 1.

ADC library sampling rate on Teensy 3.2

Hi,
I'm working on Teensy 3.2, and using ADC lib to sample A2 pin input (ADC1).
I read the samples and pass them (collected in array of 2048 samples) to arm_cfft_radix4_f32 function in order to perform fft.
I need to know the frequency step of the 1024 samples of FFT and the frequency of the 1024-th fft element.

My ADC setup code is:
adc->setReference(ADC_REFERENCE::REF_1V2, ADC_1); adc->setAveraging(16); adc->setResolution(16); adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_LOW_SPEED);

Thanks in advance.
Best Regards

enablePGA doesn't work on second adc

When using continuous differencial reading on adc1 I get the error
Error ADC1: Wrong pin
But only if I try to enable the PGA. If I omit the call to enablePGA it works, and it works if using adc0. Is this expected?

  adc->adc1->enablePGA(1);
  adc->adc1->setAveraging(32); // set number of averages
  adc->adc1->setResolution(16); // set bits of resolution
  adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::LOW_SPEED); // change the conversion speed
  adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED); // change the sampling speed
  
  adc->adc1->enableInterrupts(adc1_isr);
  adc->startContinuousDifferential(A10,A11,ADC_1);

Compile error

I can't get the examples to compile with arduino studio 1.6.1. I get this error messages for the following examples:

analogContinuousDifferentialRead

analogContinuousDifferentialRead.ino: In function 'void setup()':
analogContinuousDifferentialRead:18: error: 'A13' was not declared in this scope
'A13' was not declared in this scope

analogRead:

Arduino: 1.6.1 (Linux), TD: 1.23, Board: "Teensy LC, Serial, 48 MHz, US English"

/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In constructor 'RingBufferDMA::RingBufferDMA(uint8_t, uint8_t)':
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:57:20: error: 'DMA_TCD0_CSR' was not declared in this scope
DMA_TCD_CSR = &DMA_TCD0_CSR + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:59:22: error: 'DMA_TCD0_SADDR' was not declared in this scope
DMA_TCD_SADDR = &DMA_TCD0_SADDR + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:60:21: error: 'DMA_TCD0_SOFF' was not declared in this scope
DMA_TCD_SOFF = &DMA_TCD0_SOFF + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:61:22: error: 'DMA_TCD0_SLAST' was not declared in this scope
DMA_TCD_SLAST = &DMA_TCD0_SLAST + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:63:22: error: 'DMA_TCD0_DADDR' was not declared in this scope
DMA_TCD_DADDR = &DMA_TCD0_DADDR + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:64:21: error: 'DMA_TCD0_DOFF' was not declared in this scope
DMA_TCD_DOFF = &DMA_TCD0_DOFF + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:65:25: error: 'DMA_TCD0_DLASTSGA' was not declared in this scope
DMA_TCD_DLASTSGA = &DMA_TCD0_DLASTSGA + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:67:21: error: 'DMA_TCD0_ATTR' was not declared in this scope
DMA_TCD_ATTR = &DMA_TCD0_ATTR + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:68:28: error: 'DMA_TCD0_NBYTES_MLNO' was not declared in this scope
DMA_TCD_NBYTES_MLNO = &DMA_TCD0_NBYTES_MLNO + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:70:30: error: 'DMA_TCD0_CITER_ELINKNO' was not declared in this scope
DMA_TCD_CITER_ELINKNO = &DMA_TCD0_CITER_ELINKNO + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:71:30: error: 'DMA_TCD0_BITER_ELINKNO' was not declared in this scope
DMA_TCD_BITER_ELINKNO = &DMA_TCD0_BITER_ELINKNO + dma_offset_16*DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In member function 'void RingBufferDMA::start()':
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:86:5: error: 'DMA_CR' was not declared in this scope
DMA_CR = 0; // normal mode of operation
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:90:40: error: 'DMA_TCD_ATTR_SIZE_16BIT' was not declared in this scope
*DMA_TCD_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:90:63: error: 'DMA_TCD_ATTR_SSIZE' was not declared in this scope
*DMA_TCD_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:91:61: error: 'DMA_TCD_ATTR_DSIZE' was not declared in this scope
DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:92:38: error: 'DMA_TCD_ATTR_DMOD' was not declared in this scope
DMA_TCD_ATTR_DMOD(4); // src and dst data is 16 bit (2 bytes), buffer size 2^^4 bytes = 8 values
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:106:20: error: 'DMA_TCD_CSR_INTMAJOR' was not declared in this scope
*DMA_TCD_CSR = DMA_TCD_CSR_INTMAJOR; // Control and status: interrupt when major counter is complete
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:108:5: error: 'DMA_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // clear all past request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:108:41: error: 'DMA_CERQ_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // clear all past request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:109:5: error: 'DMA_CINT' was not declared in this scope
DMA_CINT = DMA_channel; // clear interrupts
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:117:5: error: 'DMA_SERQ' was not declared in this scope
DMA_SERQ = DMA_SERQ_SERQ(DMA_channel); // enable DMA request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:117:41: error: 'DMA_SERQ_SERQ' was not declared in this scope
DMA_SERQ = DMA_SERQ_SERQ(DMA_channel); // enable DMA request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In destructor 'RingBufferDMA::~RingBufferDMA()':
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:127:5: error: 'DMA_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // stop channel 3
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:127:41: error: 'DMA_CERQ_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // stop channel 3
^
Error compiling.

analogContinuousRead:

Arduino: 1.6.1 (Linux), TD: 1.23, Board: "Teensy LC, Serial, 48 MHz, US English"

Build options changed, rebuilding all
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In constructor 'RingBufferDMA::RingBufferDMA(uint8_t, uint8_t)':
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:57:20: error: 'DMA_TCD0_CSR' was not declared in this scope
DMA_TCD_CSR = &DMA_TCD0_CSR + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:59:22: error: 'DMA_TCD0_SADDR' was not declared in this scope
DMA_TCD_SADDR = &DMA_TCD0_SADDR + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:60:21: error: 'DMA_TCD0_SOFF' was not declared in this scope
DMA_TCD_SOFF = &DMA_TCD0_SOFF + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:61:22: error: 'DMA_TCD0_SLAST' was not declared in this scope
DMA_TCD_SLAST = &DMA_TCD0_SLAST + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:63:22: error: 'DMA_TCD0_DADDR' was not declared in this scope
DMA_TCD_DADDR = &DMA_TCD0_DADDR + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:64:21: error: 'DMA_TCD0_DOFF' was not declared in this scope
DMA_TCD_DOFF = &DMA_TCD0_DOFF + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:65:25: error: 'DMA_TCD0_DLASTSGA' was not declared in this scope
DMA_TCD_DLASTSGA = &DMA_TCD0_DLASTSGA + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:67:21: error: 'DMA_TCD0_ATTR' was not declared in this scope
DMA_TCD_ATTR = &DMA_TCD0_ATTR + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:68:28: error: 'DMA_TCD0_NBYTES_MLNO' was not declared in this scope
DMA_TCD_NBYTES_MLNO = &DMA_TCD0_NBYTES_MLNO + dma_offset_32_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:70:30: error: 'DMA_TCD0_CITER_ELINKNO' was not declared in this scope
DMA_TCD_CITER_ELINKNO = &DMA_TCD0_CITER_ELINKNO + dma_offset_16_DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:71:30: error: 'DMA_TCD0_BITER_ELINKNO' was not declared in this scope
DMA_TCD_BITER_ELINKNO = &DMA_TCD0_BITER_ELINKNO + dma_offset_16*DMA_channel;
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In member function 'void RingBufferDMA::start()':
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:86:5: error: 'DMA_CR' was not declared in this scope
DMA_CR = 0; // normal mode of operation
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:90:40: error: 'DMA_TCD_ATTR_SIZE_16BIT' was not declared in this scope
*DMA_TCD_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:90:63: error: 'DMA_TCD_ATTR_SSIZE' was not declared in this scope
*DMA_TCD_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:91:61: error: 'DMA_TCD_ATTR_DSIZE' was not declared in this scope
DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:92:38: error: 'DMA_TCD_ATTR_DMOD' was not declared in this scope
DMA_TCD_ATTR_DMOD(4); // src and dst data is 16 bit (2 bytes), buffer size 2^^4 bytes = 8 values
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:106:20: error: 'DMA_TCD_CSR_INTMAJOR' was not declared in this scope
*DMA_TCD_CSR = DMA_TCD_CSR_INTMAJOR; // Control and status: interrupt when major counter is complete
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:108:5: error: 'DMA_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // clear all past request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:108:41: error: 'DMA_CERQ_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // clear all past request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:109:5: error: 'DMA_CINT' was not declared in this scope
DMA_CINT = DMA_channel; // clear interrupts
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:117:5: error: 'DMA_SERQ' was not declared in this scope
DMA_SERQ = DMA_SERQ_SERQ(DMA_channel); // enable DMA request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:117:41: error: 'DMA_SERQ_SERQ' was not declared in this scope
DMA_SERQ = DMA_SERQ_SERQ(DMA_channel); // enable DMA request
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp: In destructor 'RingBufferDMA::~RingBufferDMA()':
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:127:5: error: 'DMA_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // stop channel 3
^
/arduino-1.6.1/hardware/teensy/avr/libraries/ADC/RingBufferDMA.cpp:127:41: error: 'DMA_CERQ_CERQ' was not declared in this scope
DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // stop channel 3
^
Error compiling.

Sample rate

It would be really nice with a way to set the sample rate or at least get the current rate. This is vital for DSP work.

Teensy 3.6 wrong ADC1_IRQ

The ADC1_IRQ is set to 40 but it should be 73 for Teensy 3.5/3.6.
I fixed it in file "ADC_Module.cpp" by:

ADC_Module::ADC_Module(uint8_t ADC_number, const uint8_t* const a_channel2sc1a, const ADC_NLIST* const a_diff_table) :
ADC_num(ADC_number)
, channel2sc1a(a_channel2sc1a)

.......

, PDB0_CHnC1(&PDB0_CH0C1 + ADC_num0xA)
#if ADC_NUM_ADCS==2
, IRQ_ADC(IRQ_ADC0 + ADC_num
(IRQ_ADC1 - IRQ_ADC0)) // fix by SB (Teensy 3.6)
#else
, IRQ_ADC(IRQ_ADC0 + ADC_num*1)
#endif

Frequency controlled conversions

It is possible to trigger ADC conversions at a fixed frequency.
Teensy 3.x have the PDB, Teensy 4 has something like that.

The goal is to have frequency controlled conversions for all boards. DMA functionality is discussed in a different issue (#42 ), but it may be related to this at some point.

DMA functionality

DMA can be used to trigger and transfer conversions from/to the ADC.
The current DMA and RingBuffer code does not work very well.
@KurtE has some working code we need to review and incorporate.

The goal is to have support for DMA transfers from/to the ADC for all boards.

Recent interface format changes

The version of the library has broken some of my code. Most of the issue has been traced to the interface changes mentioned here:
https://forum.pjrc.com/threads/59874-Teensyduino-1-51-errors-on-compile-1-48-does-not-ADC-class-implicated

However, this doesn't solve all the recent problems. I'm presently seeing issues getting measurements to complete. Questions:

This the line I'm using to start conversions. I never calls the interrupt and if I manually read the output after conversions should have been complete the result is always zero.
ADC_ERROR =adc->startSynchronizedContinuous(ANA_PIN0,ANA_PIN1);

I tried this line for a single channel, and it did the same. Interrupt is never called.
//ADC_ERROR =adc->adc0->startContinuous(ANA_PIN0);

I tried this and the output was -70000.
adc0=adc->adc0->analogRead(ANA_PIN0);
Serial.println(adc0);

Obviously something else changed, but I can't tell what.
Is this the correct format to implement the enable interrupts command:
adc-> adc0-> enableInterrupts(adc0_isr);

Return type does not match documentation ADC.h

/////////////// NON-BLOCKING CONVERSION METHODS //////////////

    //! Starts an analog measurement on the pin and enables interrupts.
    /** It returns inmediately, get value with readSingle().
    *   If the pin is incorrect it returns ADC_ERROR_VALUE
    *   If this function interrupts a measurement, it stores the settings in adc_config
    */
    bool startSingleRead(uint8_t pin, int8_t adc_num = -1);

    //! Start a differential conversion between two pins (pinP - pinN) and enables interrupts.
    /** It returns inmediately, get value with readSingle().
    *   \param pinP must be A10 or A12.
    *   \param pinN must be A11 (if pinP=A10) or A13 (if pinP=A12).
    *
    *   Other pins will return ADC_ERROR_DIFF_VALUE.
    *   If this function interrupts a measurement, it stores the settings in adc_config
    */
    bool startSingleDifferential(uint8_t pinP, uint8_t pinN, int8_t adc_num = -1);

Assigning pinMode(pin, INPUT) causes slightly wrong readings?

I have a voltage divider here to read the voltage of a lithium ion cell:
Vbatt ->33k -> pin -> 100k -> GND
(100µF cap via pin -> cap -> GND, high impedance is not the issue)
Ohms law says that Vbatt = (33k + 100k) / 100k * Vpin
However, the pin is reading high. Both in the µC as well as when using a multimeter on pin<->GND compared to the correct Vbatt<->GND.
Not much, but the reading is about 5% high.
It took me way too long to find out that said pinMode causes this problem.
Removing the pinMode declaration removed the issue, the ready is now <1% off the multimeter.

While trying to figure out what is going on I also found that I was unable to have ADC_0 at 16bit resolution and ADC_1 at 10bit. They were always both at 16bit.
And what does the compare mean... I tryed to turn that on and off for both ADCs and it didnt change a thing. So why "always call it"?
// always call the compare functions after changing the resolution! //adc->enableCompare(1.0/3.3*adc->getMaxValue(ADC_0), 0, ADC_0); // measurement will be ready if value < 1.0V //adc->enableCompareRange(1.0*adc->getMaxValue(ADC_0)/3.3, 2.0*adc->getMaxValue(ADC_0)/3.3, 0, 1, ADC_0); // ready if value lies out of [1.0,2.0] V

Analog Buffer cannot be dynamically allocated on Teensy 4

I am trying to use dynamically allocated buffers and AnalogBufferDMA, and found the following:

An instantiation of AnalogBufferDMA must be global if two buffers are used for continuous operation, is this correct.

An instantiation of AnalogBufferDMA can be dynamic if one buffer is used for IntervalTimer operation.

The buffers must be global. I tried malloc and new the buffer(s), and they will fill up the first time by the DMA, but will never be filled up again with new data.

I tried using double buffer for IntervalTimer operation, by setting stopOnCompletion(true) after init. But this does not work. I looked through the code and during init some other methods are called other then just setting _stop_on_completion.

setAveraging 8 and 16 exchanged

ADC is a fantastic piece of code !
During my tests on my small domotic solution, I found that the behaviour of 8 and 16 averaging are exchanged.
The problem comes from the ADC_Module::setAveraging method where the comments are OK but not the code :

  } else if (num <= 8) {
       num = 8;
       // *ADC_SC3_avgs0 = 1;
       // *ADC_SC3_avgs1 = 0;
       setBit(ADC_SC3, ADC_SC3_AVGS1_BIT); // should be clearBit
       clearBit(ADC_SC3, ADC_SC3_AVGS0_BIT); // should be setBit
   } else if (num <= 16) {
       num = 16;
       // *ADC_SC3_avgs0 = 0;
       // *ADC_SC3_avgs1 = 1;
       clearBit(ADC_SC3, ADC_SC3_AVGS1_BIT); // should be setBit
       setBit(ADC_SC3, ADC_SC3_AVGS0_BIT); // should be clearBit

ADC sample event triggered by flexpwm Teensy 4

I have tried everything but i absolutely cannot get an adc sample to occur when the flexpwm event triggered, perhaps an issue of hardware sync or can anyone guide me how i would implement this properly :(

RingBufferDMA Channel 2 on ADC_0 Fails to Update Second Half

Just want to mention that this library has been super useful so far, but I am running into a weird issue with trying to use DMA on the Teensy 3.1 with code that is very similar to your example but uses startSynchronizedSingleRead for pins A9 and A3. It appears that the last 4 samples in the size 8 ring buffer do not get updated on only ADC_0, whereas ADC_1 seems to work correctly. I will post some code below that hopefully will recreate the error for you.

ADC1 interrupts?

Hi, I am attempting to override the ADC interrupt behavior. This works swimmingly when I work with ADC0, however, it does not work with ADC1. Is this known? Expected?

Example with ADC0:
ADC adc;

void attribute((weak)) adc0_isr(void) {
digitalWrite(13, HIGH);
}

void setup() {
adc.enableInterrupts(0);
pinMode(13, OUTPUT);
adc.startSingleRead(A0,0);
digitalWrite(13, LOW);
}
void loop() { }

The LED turns on.

However, with
ADC adc;

void attribute((weak)) adc1_isr(void) {
digitalWrite(13, HIGH);
}
void setup() {
adc.enableInterrupts(1);
pinMode(13, OUTPUT);
adc.startSingleRead(A2,1);
digitalWrite(13, LOW);
}
void loop() { }

The LED does not.

Should I be doing anything differently?

reading several channels with multiplexed ADC

First, thank you for a very nice repo!

I am using some code on Arduino Due to:

  • 1 set up a timer
  • 2 set up the ADC to trigger at rising edge of the timer, and read on several multiplexed channels one after the other
  • 3 raise the ADC ISR once all conversions are done.

The code looks like this:

constexpr int adc_sample_rate = 1000;
constexpr uint8_t adc_channels[] = {7, 6, 5, 4, 3};
constexpr int nbr_adc_channels = sizeof(adc_channels);

void adc_setup()
{
  PMC->PMC_PCER1 |= PMC_PCER1_PID37;      // ADC power on
  ADC->ADC_CR = ADC_CR_SWRST;             // Reset ADC
  ADC->ADC_MR |= ADC_MR_TRGEN_EN |        // Hardware trigger select
                 ADC_MR_PRESCAL(200) | // pre-scaler
                 ADC_MR_TRGSEL_ADC_TRIG3; // Trigger by TIOA2 Rising edge

  ADC->ADC_IDR = ~(0ul);
  ADC->ADC_CHDR = ~(0ul);
  for (int i = 0; i < nbr_adc_channels; i++)
  {
    ADC->ADC_CHER |= ADC_CHER_CH0 << adc_channels[i];
  }
  ADC->ADC_IER |= ADC_IER_EOC0 << adc_channels[nbr_adc_channels - 1];
  ADC->ADC_PTCR |= ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS; // Disable PDC DMA
  NVIC_EnableIRQ(ADC_IRQn);                           // Enable ADC interrupt
}

void tc_setup()
{
  PMC->PMC_PCER0 |= PMC_PCER0_PID29;                     // TC2 power ON : Timer Counter 0 channel 2 IS TC2
  TC0->TC_CHANNEL[2].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK2 // clock 2 has frequency MCK/8, clk on rising edge
                              | TC_CMR_WAVE              // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC      // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR        // Clear TIOA2 on RA compare match
                              | TC_CMR_ACPC_SET;         // Set TIOA2 on RC compare match

  constexpr int ticks_per_sample = F_CPU / 8 / adc_sample_rate; // F_CPU / 8 is the timer clock frequency, see MCK/8 setup
  constexpr int ticks_duty_cycle = ticks_per_sample / 2;        // duty rate up vs down ticks over timer cycle; use 50%
  TC0->TC_CHANNEL[2].TC_RC = ticks_per_sample;
  TC0->TC_CHANNEL[2].TC_RA = ticks_duty_cycle;

  TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC2 counter and enable
}

void ADC_Handler(){
  // putting inside buffer
}

Is there a way to set up a similar timer + triggering + multiplexed ADC conversion with your library, or does this require doing some register operations as done here?

I looked at the examples:

  • this one was very interesting about timers etc, but it looks like there is a bit more complexity than needed / the previous example, and also, the ADC is not really triggered by the timer, rather, the timer raises an interrupt in which ISR the ADC conversion is started. Not sure if this is less accurate that the method above?

https://github.com/pedvide/ADC/blob/master/examples/analogReadIntervalTimer/analogReadIntervalTimer.ino

  • in this example, not sure what effective sampling frequency is obtained in the end:

https://github.com/pedvide/ADC/blob/master/examples/analogContinuousRead/analogContinuousRead.ino

  • I am also not sure if this library lets one set the multiplexing through register setup?

ADC library on 3.6 + DAC

Hello:

Is possible to use this lib with the Audio lib?

ADC *adc = new ADC(); // this makes audio to not work :)

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.