Here's a simple example that I got from nick gammon's forum.
This is to get internal voltage through 1.1v bandgap
void setup(void)
{
Serial.begin(115200);
}
void loop(void)
{
Serial.println (getBandgap ());
delay(1000);
}
[b]const long[/b] InternalReferenceVoltage = 1062; // Adjust this value to your board's specific internal BG voltage
// Code courtesy of "Coding Badly" and "Retrolefty" from the Arduino forum
// results are Vcc * 100
// So for example, 5V would be 500.
int getBandgap ()
{
// REFS0 : Selects AVcc external reference
// MUX3 MUX2 MUX1 : Selects 1.1V (VBG)
ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
ADCSRA |= bit( ADSC ); // start conversion
while (ADCSRA & bit (ADSC))
{ } // wait for conversion to complete
[b]int results = (((InternalReferenceVoltage* 1024) / ADC) + 5) / 10;[/b]
return results;
} // end of getBandgap
Results=467 (Fine)
but if i just leave out
const long InternalReferenceVoltage = 1062;
and just put 1062 directly into the equation as such..
If you set the "Compiler warnings:" preference to "All" you will see:
sketch_jul13a.ino: In function 'int getBandgap()':
sketch_jul13a.ino:27:25: warning: integer overflow in expression [-Woverflow]
int results = (((1062 * 1024) / ADC) + 5) / 10;
^
Sketch uses 1898 bytes (5%) of program storage space. Maximum is 32256 bytes.
Global variables use 188 bytes (9%) of dynamic memory, leaving 1860 bytes for local variables. Maximum is 2048 bytes.
const long InternalReferenceVoltage = 1062; // Adjust this value to your board's specific internal BG voltage
// Code courtesy of "Coding Badly" and "Retrolefty" from the Arduino forum
// results are Vcc * 100
// So for example, 5V would be 500.
int getBandgap ()
{
// REFS0 : Selects AVcc external reference
// MUX3 MUX2 MUX1 : Selects 1.1V (VBG)
ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
ADCSRA |= bit( ADSC ); // start conversion
while (ADCSRA & bit (ADSC))
{ } // wait for conversion to complete // int results = (((1062* 1024) / ADC) + 5) / 10; byte results = 1023*5-5000;
return results;
} // end of getBandgap
1023 * 5 =5115....-5000=115
And that's exactly what prints.
So if what you are saying holds true, then why does it "overflow" when I say
int results = (((1062* 1024) / ADC) + 5) / 10;
and not when I say
byte results = 10235-5000;
or
intresults = 10235-5000;
1062 * 1024 is 1,087,488 (0x109800) which won't fit in a 16-bit 'int' (32,767 max). It gets truncated to 16 bits (0x9800) to fit. That also makes it a negative number since the 16th bit is set: -26624
1023 * 5 = 5115 That DOES fit in an integer. Subtracting 5000 gets you a value that fits in a byte or integer.
const long InternalReferenceVoltage = 1062; // Adjust this value to your board's specific internal BG voltage
// Code courtesy of "Coding Badly" and "Retrolefty" from the Arduino forum
// results are Vcc * 100
// So for example, 5V would be 500.
int getBandgap ()
{
// REFS0 : Selects AVcc external reference
// MUX3 MUX2 MUX1 : Selects 1.1V (VBG)
ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
ADCSRA |= bit( ADSC ); // start conversion
while (ADCSRA & bit (ADSC))
{ } // wait for conversion to complete
// int results = (((InternalReferenceVoltage * 1024) / ADC) + 5) / 10; byte results = 32767*5-163800;
return results;
} // end of getBandgap
32767*5=163,835....-163800=35 so the result should be 35
even that prints correctly EVEN if it is only a byte
My point is that from what we see here is that you can use large number even larger than the capacity of the declared variable and it wont overflow AS LONG as the end result is less than the space of that given variable.
void loop() {
byte result=1062*1024-1087400;//result will be 1,087,488-1,087,400=88
Serial.println(result);//I GOT 88 EVEN IF THIS IS JUST A byte
delay(100);
}
That ahaah moment!!
So you are saying that if the "written" values are within the..say byte range but somewhere along the calculation the value exceeded the overflow limit of byte the result will be wrong even if the true result fits into .. say byte?
But in my example I had a written value more than int so the equation space was automatically bumped up to long by the compiler. Is that correct?
P.s. I had trouble using "bold" in the code tags. I guess I'm not supposed to hit the bold button while writing in code tags. Will use from now on. Sorry.
int results = (((InternalReferenceVoltage* 1024) / ADC) + 5) / 10;
return results;
} // end of getBandgap
The ADC part of the equation is not given and therefore not predictable. This is why the compiler does not bump it up to a long And that is the reason you have to declare
Integer constants (nnnnnnn) are 'int' unless outside the allowed range for 'int', then promoted to 'long'.
Unsigned integer constants (nnnnnnnU) are unsigned int unless outside the range for unsigned int, then promoted to unsigned long.
Even if you cast both sides of an operator to 'byte' the operation will be done in 'int'.
Serial.println(100 * 10); // 1000 Promoted to 'int'
Serial.println((byte)100 * (byte)10); // 1000 Promoted to 'int' despite casting
Serial.println(10000 * 10); // -31702 Integer overflow
Serial.println(32767 * 10); // -10 Integer overflow
Serial.println(32768 * 10); // 327680 Promoted to 'long'
Serial.println(32768U * 10); // 0 unsigned int overflow WITH NO WARNING
Serial.println(65535U * 10); // 65526 unsigned int overflow WITH NO WARNING
Serial.println(65536U * 10); // 655360 Promoted to 'unsigned long'
Serial.println(100000 * 10); // 1000000 Promoted to 'long'
Turning up warnings will get you the appropriate warning messages for int, but not for unsigned int:
sketch_jul13a.ino: In function 'void setup()':
sketch_jul13a.ino:7:24: warning: integer overflow in expression [-Woverflow]
Serial.println(10000 * 10); // Integer overflow
^
sketch_jul13a.ino:8:24: warning: integer overflow in expression [-Woverflow]
Serial.println(32767 * 10); // Integer overflow
^