Bug in Pedivide ADC library function

CrazyDog

Member
I'm using the adc .h library in an application requiring high speed 12 bit a/d conversion by interleaving the two A/Ds on a T4 or T4.1 running at 600MHz. The interrupt service is called every 2 microseconds by the timer in the Timer.lib. The bug is that the converted values from each conversion cannot be assigned to two separate variables. If both converted values are assigned to the same variable everything works properly. I've attached code wherein both are assigned to value1 using a pointer p1 to value1 a 16 bit unsigned integer. that works but if I change the code to assign each converted value to a different variable, e.g. value 1 for adc0 and value2 for Adc1 one of the conversion results is always 0 while the other is correct.



```cpp
#include <ADC.h>
#include <TimeLib.h>
ADC *adc = new ADC(); // adc object
IntervalTimer ADCTimer;
short unsigned int value1 = 0;
short unsigned int value2 = 0;
uint32_t RMSAVG = 0;
bool error = 0;
volatile uint32_t deltacountcopy;
short unsigned int *p1 = &value1;
short unsigned int *p2 = &value2;
//*******************************************************
// INTERRUPT SERVICE FOR A/D TRIGGERED BY TIMER
//******************************************************
void ADCService(void) // interrupt service interleaving A/Ds
{
volatile uint32_t dwt;
uint32_t deltacount = 0;
volatile uint32_t dwtlast = 0;
static unsigned flipflop = 0;
error = 0; // clear error flag on entry
dwt = ARM_DWT_CYCCNT; // used to time interrupt service
if (flipflop++ % 1) {
if (adc->adc0->isConverting()) // CHECK FOR READ ERRORS
error = 1; // WILL SERIAL PRINT "error" IF ERROR
adc->adc0->startSingleRead(A0); // start a single conversion
*p1 = adc->adc0->readSingle(); // get converted value
} else {
if (adc->adc1->isConverting()) // CHECK FOR READ ERRORS
error = 1; // WILL SERIAL PRINT "9999" IF ERROR
adc->adc1->startSingleRead(A0); // start a single conversion
*p1 = adc->adc1->readSingle(); // get converted value
}
dwtlast = ARM_DWT_CYCCNT;
deltacount = dwtlast - dwt;
noInterrupts();
deltacountcopy = deltacount; // avg 223 CPU cycles per interrupt/600Mhz= 371nsec
interrupts();
} // end of ADCService()


void setup() {
// put your setup code here, to run once:
Serial.begin(9600);

adc->adc0->setAveraging(0); // no averaging
adc->adc0->setResolution(12); // 12 bit
adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED);
adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
adc->adc1->setAveraging(0); // no averaging
adc->adc1->setResolution(12); // 12 bit
adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED);
adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
pinMode(A0, INPUT_DISABLE); //DISABLE KEEPER RESISTORSS ON THE INPUT
pinMode(A1, INPUT_DISABLE);
ADCTimer.begin(ADCService, 2.0); // start timer to interrupt every 2.0 microseconds
// this is 500kHz sampling, 12 bit resolution
NVIC_SET_PRIORITY(IRQ_ADC1, 55); // Very high priority for A/D1
NVIC_SET_PRIORITY(IRQ_ADC2, 55); // Very high priority for A/D2
}
//********************************************************************************
// FIRST ORDER DIGITAL IIR FILTER TO COMPUTE RMSAVG
//********************************************************************************
float filteredADC() // first order recursive digital filter
{
const float alpha = 0.0005; // alpha = (Ts/Tau), valid for tau>(10/fsampling)
// tau is filter time constant ***ALPHA MUST BE < 1.0 ***
static float foutput = 0.0f; // static
float input = value1; // input is the A/D conversion result from interrupt service
foutput += alpha * (input - foutput);

return (unsigned int)foutput; // returns filter output
}

void loop() {

if (error) Serial.println("9999"); // if tried to start A/D conversion while busy
Serial.println(value1);

}

```



``
 
Back
Top