Changes to PGA1 also change PGA0 on Teensy3.1

Status
Not open for further replies.

saintc

New member
I modified the analogDifferentialRead example to test setting the gain values of the programmable gain amplifiers (PGAs) for ADC0 and ADC1. Changing the gain to ADC0 works as I expected but whenever I change the gain to ADC1 the ADC0 gain changes also. Here's the test case:
Code:
/* Test for analogReadDifferentialGain as modified from analogReadDifferential
*  You can interactively change PGA gain values from the Serial Monitor:
*     Enter two characters: cg 
*         where c selects the ADC number and can be 0 or 1
*         and where g sets the gain and can be 0, 1, 2, 3, 4, 5, or 6 
*         for a gain value of 1, 2, 4, 8, 16, 32, or 64 respectively
*  You can enter strings of commands. For example 000102 will set ADC0's gain to 
*  1, 2, and 4 on successive iterations. 1302 will set AGC1's gain to 8 and 
*  AGC0's gain to 4.
*
*  ADC0 and the corresponding PGA0 are connected to pins A10/A11 (+/-)
*  ADC1 and the corresponding PGA1 are connected to pins A12/A13 (+/-)  
*  On the breadboard A11 and A13 are tied to ground. A10 and A12 are tied to
*  the same pot and that is adjusted to about 0.1 volts.
*/

#include <ADC.h>
ADC *adc = new ADC(); // adc object

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(A10, INPUT); //Diff Channel 0 Positive
    pinMode(A11, INPUT); //Diff Channel 0 Negative
    pinMode(A12, INPUT); //Diff Channel 3 Positive
    pinMode(A13, INPUT); //Diff Channel 3 Negative

    Serial.begin(9600);

    ///// ADC0 ////
    adc->setAveraging(8); // set number of averages
    adc->setResolution(9); // set bits of resolution

    // these can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED,
    //              ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
    adc->setConversionSpeed(ADC_MED_SPEED); // change the conversion speed
    adc->setSamplingSpeed(ADC_MED_SPEED); // change the sampling speed
    // always call the compare functions after changing the resolution!
    adc->disableCompare(ADC_0);

    ////// ADC1 /////
    adc->setAveraging(8, ADC_1); // set number of averages
    adc->setResolution(9, ADC_1); // set bits of resolution
    adc->setConversionSpeed(ADC_MED_SPEED, ADC_1); // change the conversion speed
    adc->setSamplingSpeed(ADC_MED_SPEED, ADC_1); // change the sampling speed
    // always call the compare functions after changing the resolution!
    adc->disableCompare(ADC_1);
    
    adc->enablePGA(1, ADC_0);  // gain can be 1,2,4,8,16,32,64
    adc->enablePGA(1, ADC_1);

    delay(500);
}

int value[2];
int c = 0, g = 0;
float k[] = {0, 0};

void loop() {
    if (Serial.available()) {
        c = Serial.read() - '0';   // get DAC number
        g = Serial.read() - '0';   // get gain value
        Serial.println("");
        Serial.print("Cmd: "); Serial.print(c); Serial.print(g);
        Serial.print(" (adc->enablePGA(1<<"); Serial.print(g); Serial.print(", "); 
        Serial.print(c); Serial.println(");)");
        adc->enablePGA(1<<g, c);   // set gain
        for (c=0; c<2; c++) {
          Serial.print("  ADC"); Serial.print(c);
          Serial.print(" MaxVal: "); Serial.print(adc->getMaxValue(c));
          Serial.print(" PGA: "); Serial.print(adc->getPGA(c));
          k[c] = 3.3/adc->getPGA(c)/adc->getMaxValue(c);
          Serial.print(" k: "); Serial.println(k[c], 6);
        }
    }
    value[0] = adc->analogReadDifferential(A10, A11, ADC_0);
    value[1] = adc->analogReadDifferential(A12, A13, ADC_1);
    for (c=0; c<2; c++) {
      Serial.print("ADC"); Serial.print(c);
      Serial.print(" Value: (0x"); Serial.print(value[c], HEX);
      Serial.print(", Voltage: "); Serial.print(k[c]*value[c], 3);
      Serial.print(") ");
    }
    Serial.println("");

    if(adc->adc0->fail_flag) {
        Serial.print("ADC0 error flags: 0x");
        Serial.println(adc->adc0->fail_flag, HEX);
    }
    if(adc->adc1->fail_flag) {
        Serial.print("ADC1 error flags: 0x");
        Serial.println(adc->adc1->fail_flag, HEX);
    }
    digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
    delay(1000);
}
Here is a sample output with annotations:

Cmd: 01 (adc->enablePGA(1<<1, 0);)
ADC0 MaxVal: 255 PGA: 2 k: 0.006471
ADC1 MaxVal: 255 PGA: 1 k: 0.012941
ADC0 Value: (0x10, Voltage: 0.104) ADC1 Value: (0x8, Voltage: 0.104)
This is as expected. PGA0 is set to 2x gain. PGA1 is unchanged.

Cmd: 02 (adc->enablePGA(1<<2, 0);)
ADC0 MaxVal: 255 PGA: 4 k: 0.003235
ADC1 MaxVal: 255 PGA: 1 k: 0.012941
ADC0 Value: (0x1F, Voltage: 0.100) ADC1 Value: (0x8, Voltage: 0.104)
This is as expected. PGA0 is set to 4x gain. PGA1 is unchanged.

Cmd: 00 (adc->enablePGA(1<<0, 0);)
ADC0 MaxVal: 255 PGA: 1 k: 0.012941
ADC1 MaxVal: 255 PGA: 1 k: 0.012941
ADC0 Value: (0x8, Voltage: 0.104) ADC1 Value: (0x8, Voltage: 0.104)
This is as expected. PGA0 is set to 1x gain.

Cmd: 14 (adc->enablePGA(1<<4, 1);)
ADC0 MaxVal: 255 PGA: 16 k: 0.000809
ADC1 MaxVal: 255 PGA: 16 k: 0.000809
ADC0 Value: (0x76, Voltage: 0.095) ADC1 Value: (0x75, Voltage: 0.095)
This is wrong. PGA1 is set to 16x gain and PGA0 changes also.

Cmd: 15 (adc->enablePGA(1<<5, 1);)
ADC0 MaxVal: 255 PGA: 32 k: 0.000404
ADC1 MaxVal: 255 PGA: 32 k: 0.000404
ADC0 Value: (0xDD, Voltage: 0.089) ADC1 Value: (0xDC, Voltage: 0.089)
This is wrong. PGA1 is set to 32x gain and PGA0 changes also.

Cmd: 10 (adc->enablePGA(1<<0, 1);)
ADC0 MaxVal: 255 PGA: 1 k: 0.012941
ADC1 MaxVal: 255 PGA: 1 k: 0.012941
ADC0 Value: (0x8, Voltage: 0.104) ADC1 Value: (0x8, Voltage: 0.104)
This is wrong. PGA1 is set to 1x gain and PGA0 changes also.

Any thoughts on what's going on here?
 
My guess is that there is a simple and straight forward problem with the ADC driver. But, I'm not familiar enough with C++ to really track that down.
 
I looked at the ADC library code and found the problem (in the function enablePGA(...) ). I'll post an update today.
Thanks for the well documented bug report!
 
Status
Not open for further replies.
Back
Top