Monday, February 9, 2015

Expanding Arduino analogRead() and pinMode() to support the differential inputs on the ATmega32M1 / ATmega64M1

A nice feature of the Atmega32M1 / ATmega64M1 line of uC's is the addition of a differential input amplifier as one of the options for the ADC.  No longer must one take two measurements and subtract them in software, the 'op-amp' can do it for us.  Plus these differential inputs have a selectable gain from 5x to 40x.

On the Solar MPPT controller I use this capability to measure the battery and solar panel currents via a simple low ohm resistor.  Add in a small RC low-pass filter, and that is all that is needed...  (Using the ATmega32M1 uC allowed me to remove several other components typically used in other approaches, current measurement being one of those areas).

There are three differential channels: 0, 1, and 2.  I have extended the Arduino IDE's wiring_analog.c to recognize three new 'virtual ports'**:  AD0, AD1, and AD2.   Reading the value of these differential analog ports one simply uses the oh so familiar analogRead() function, example:

    solarAmpsRaw = analogRead(AD2);       // Read raw value of Solar Amp Shunt.


pinMode() has also been modified to recognize AD0, AD1, and AD2, with a slight change:  the 2nd parameter no longer specifies a 'mode' - as differential reads are always input.  Now the 2nd parameter is used to specific the amplifier gain to be used:  GAIN5, GAIN10, GAIN20, GAIN40

  pinMode(AD2, GAIN40);                 // Enable diff-amp #2, with gain of 40x


** Do take note that when enabling the 'virtual' differential analog inputs, two actual hardware ports are repurposed:


  • AD0 returned results of:  (  D9 - D8)   * gain
  • AD1 returned results of:  (  A3 - A4)   * gain
  • AD2 returned results of:  (D10 - A6)   * gain



Summary of changes:

  1. analogRead() expanded to recognize differential virtual ports AD0, AD1, and AD2
  2. pinMode() expanded to enable AD0, AD1, AD2 and set the gain with: GAIN5, GAIN10, GAIN20 or GAIN40.








An example sketch:

#define SOL_AMPS_CHAN AD2               // ADC channel to read solar amps
                                        //  (Differential channel #2)
#define SOL_AMPS_SCALE (1/(40 * 0.002)) // Channel gain of 40x, 2mOhm shunt


void setup() {
   Serial.begin(9600);                  // open the serial port at 9600 bps:
   pinMode (SOL_AMPS_CHAN, GAIN40);     // Set up the differential channels.
}






void loop() {
  Serial.print(" Solar Amps are now: ");
  Serial.println(analogRead(SOL_AMPS_CHAN)*(int)(SOL_AMPS_SCALE  * 5/1024));
                                       //read and convert Solar Amps
  delay(1000);
}


No comments:

Post a Comment