Go Down

Topic: Can a pin handle a voltage greater than Vcc if it is just sinking to ground? (Read 851 times) previous topic - next topic

Coding Badly

You can measure the internal 1.1V analog reference relative to AVcc (which will be your battery voltage).


Would that violate the specifications (AVcc = 4.2 V, Vcc = 3.3 V)?

Personal opinion: I suspect that it would work.  Especially if the digital pin driver is disabled.

retrolefty



From the ATmega328P datasheet:

28.1 Absolute Maximum Ratings
Voltage on any Pin except RESET with respect to Ground ................................-0.5V to VCC+0.5V


So it won't work.  Any other ideas on how to read the battery voltage without constantly draining the battery through a voltage divider?


Well if you would return to your first idea of powering the 328P directly from the battery below is a proof of concept sketch that Coding Badly and I worked on a couple of years ago that allows a sketch to directly determine the actual value of the voltage applied to it's Vcc/Avcc pins. It uses the known internal band-gap reference as a way to 'back calculate' what the applied Vcc must be at any given time.
Of course that still leaves you with a means of how you are going to disconnect the battery once you have performed all the orderly shutdown tasks.

Code: [Select]

// Function created to obtain chip's actual Vcc voltage value, using internal bandgap reference
// This demonstrates ability to read processors Vcc voltage and the ability to maintain A/D calibration with changing Vcc
// Now works for 168/328 and mega boards.
// Thanks to "Coding Badly" for direct register control for A/D mux
// 1/9/10 "retrolefty"

int battVolts;   // made global for wider avaliblity throughout a sketch if needed, example a low voltage alarm, etc

void setup(void)
   {
    Serial.begin(38400);
    Serial.print("volts X 100");
    Serial.println( "\r\n\r\n" );
    delay(100);
   }
   
void loop(void)
   {
    battVolts=getBandgap();  //Determins what actual Vcc is, (X 100), based on known bandgap voltage
    Serial.print("Battery Vcc volts =  ");
    Serial.println(battVolts);
    Serial.print("Analog pin 0 voltage = ");
    Serial.println(map(analogRead(0), 0, 1023, 0, battVolts));
    Serial.println();    
    delay(1000);
   }

int getBandgap(void) // Returns actual value of Vcc (x 100)
   {
       
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    // For mega boards
    const long InternalReferenceVoltage = 1115L;  // Adjust this value to your boards specific internal BG voltage x1000
       // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc reference
       // MUX4 MUX3 MUX2 MUX1 MUX0  --> 11110 1.1V (VBG)         -Selects channel 30, bandgap voltage, to measure
    ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR)| (0<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
 
#else
    // For 168/328 boards
    const long InternalReferenceVoltage = 1056L;  // Adjust this value to your boards specific internal BG voltage x1000
       // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
       // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
    ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
     
#endif
    delay(50);  // Let mux settle a little to get a more stable A/D conversion
       // Start a conversion  
    ADCSRA |= _BV( ADSC );
       // Wait for it to complete
    while( ( (ADCSRA & (1<<ADSC)) != 0 ) );
       // Scale the value
    int results = (((InternalReferenceVoltage * 1024L) / ADC) + 5L) / 10L; // calculates for straight line value
    return results;

   }



Lefty

jerseyguy1996




You can measure the internal 1.1V analog reference relative to AVcc (which will be your battery voltage).  By working backward you can calculate the battery voltage.  You have to set the analog multiplexer register directly to set the analog input to the reference.  Note that the reference is only accurate to 10% (1.0V to 1.2V) so to get accurate results you need to measure the internal reference.  Write a sketch to enable the internal analog reference and do an analogRead(). Then measure the voltage at the Aref pin.  It should be your 1.0 to 1.2V.


But AVcc won't be my battery voltage.  It will be the voltage coming out of the boost converter which will be 3.3V even when the battery is well below 3.3V.
Arduino Uno;
Mega328

jerseyguy1996




Well if you would return to your first idea of powering the 328P directly from the battery below is a proof of concept sketch that Coding Badly and I worked on a couple of years ago that allows a sketch to directly determine the actual value of the voltage applied to it's Vcc/Avcc pins. It uses the known internal band-gap reference as a way to 'back calculate' what the applied Vcc must be at any given time.
Of course that still leaves you with a means of how you are going to disconnect the battery once you have performed all the orderly shutdown tasks.



But I'm not running it directly from the battery.  The mega328 will get a regulated 3.3V from a step-down/boost converter. I've shown this on the schematic above on my original post. That means I can't just read the internal band gap voltage to get the voltage at Vcc because Vcc (assuming the boost converter is working properly) will be regulated to 3.3V regardless of the battery voltage.
Arduino Uno;
Mega328

retrolefty


You can measure the internal 1.1V analog reference relative to AVcc (which will be your battery voltage).


Would that violate the specifications (AVcc = 4.2 V, Vcc = 3.3 V)?

Personal opinion: I suspect that it would work.  Especially if the digital pin driver is disabled.


I believe bad currents start flowing when Vcc and AVcc are not the same, and creates a black hole that sucks us all in.
Datasheet says:
Quote
The ADC has a separate analog supply voltage pin, AVCC. AVCC must not differ more than ±0.3V
from VCC. See the paragraph "ADC Noise Canceler" on page 258 on how to connect this pin.


Lefty

Go Up