5

I'm using Arduino Nano to measure temperature with a 10 kohm thermistor and a voltage divider. My problem is I'm getting only 4.2V on the 5V pin. The power is supplied via a USB cable from a desktop PC.

enter image description here

I measured the output voltage of a USB port on the PC and it was around 4.5V. It doesn't look normal. So I suspect the power supply unit of the PC is not strong enough.

But it still makes sense to measure the voltage at the 5V pin since there is no guarantee it's exactly 5V. Its error will affect the calculated resistance of the thermistor. So I got it by connecting the pin directly to the A1 pin.

On the other hand, it seems to me Arduino internally and digitally knows the value of the supply voltage. So it would be faster and easier to get it rather than using the A1 pin. But I don't know how to do it.

After searching on the Internet, I could find only these things which didn't help me much.

I also considered using an external power supply, say 9V to the VIN pin but I don't feel like doing that much.

How can I measure the supply voltage of Arduino without using an analog pin?

8
  • 2
    The analog inputs measure a voltage ratio: input/reference. Thus the calculated resistance of the thermistor is not affected by variations in the supply voltage. Commented Mar 15, 2018 at 14:30
  • Okay, so the integer returned by analogRead() is input/reference(1.1V)/5V*1023?
    – dixhom
    Commented Mar 15, 2018 at 14:53
  • 3
    In the case of your voltage divider, analogRead() returns Rthermistor÷(Rthermistor+Rpullup)×1024, irrespective of the supply voltage. Commented Mar 15, 2018 at 15:28
  • 2
    Yes, it's 1024. The ADC saturates at 1 step below Vref. C.f. the datasheet of the microcontroller, which is the only authoritative document for that matter. Commented Mar 17, 2018 at 9:30
  • 2
    Actually it's 1022÷1024×Vref, because when you read 1023 you don't know whether the input voltage is 1023÷1024×Vref or anything higher. Actually, any voltage above 1022.5÷1024×Vref is expected to give a reading of 1023. Commented Mar 17, 2018 at 10:01

2 Answers 2

6

Yes, you can do it.

You can measure the voltage of the internal (approximately) 1.1V reference voltage using the ADC and use the results of that to calculate what the reference voltage you used (VCC) must have been to get the results you did.

This is a function I commonly use:

long readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1125300L / result; // Back-calculate AVcc in mV
  return result;
}

Depending on how close to 1.1V your internal reference voltage is, you may need to adjust the value 1125300L in the code above. Measure the actual VCC voltage and adjust that value until it results in the same voltage being returned (multiplied by 1000 since that function returns millivolts).

However, as Edgar Bonet mentions, you don't need to care about the supply voltage in your situation, since your thermistor readings are just a ratio that input voltage, whatever it is. Change the input voltage and you will get the same results, since the ADC returns a value between 0 and Vcc in 1024 steps. With different supply voltages you still get 1024 steps.

9
  • How did you get 1125300L? And why is it 1125300L / result? It seems to me ADCL | ADCH << 8 is a 10 bit ADC value so something like result = 1125300L * result / 1024 would make sense. But for this one result is the denominator.
    – dixhom
    Commented Mar 24, 2018 at 11:18
  • 2
    1125300 is 1100 (1.1v as mv) times 1023 (ADC max value).
    – Majenko
    Commented Mar 24, 2018 at 11:40
  • In this page, it is 1126400L = 1.1*1024*1000. I'm wondering which I should believe.
    – dixhom
    Commented Mar 24, 2018 at 12:18
  • There are massive arguments around the net regarding if you should use 1023 or 1024. I say 1023. The max value of the ADC is not equal to VREF, but is VREF "minus one LSB" (as stated by the datasheet). 1024 would be VREF but you can't get 1024 out of the ADC.
    – Majenko
    Commented Mar 24, 2018 at 12:22
  • IMHO it's 1024. Edgar Bonet's comments sound reasonable. For the denominator thing, I was wrong. the equation is Vin(1.1V) = ADC/1024*AVcc(5V) since it reads "1.1V reference against AVcc". That's equivalent to AVcc = 1.1*1024/ADC = 1126.4/ADC.
    – dixhom
    Commented Mar 24, 2018 at 13:16
0

The Nano has an ATMega328P MCU, which has an internal 1.1V reference voltage.

You use analogReference() to change the reference voltage that analogRead() compares the analog inputs against.

You will need to use a voltage divider to ensure that your maximum possible supplied voltage ends up being no higher than the 1.1V reference.

You'll still need to use an analogInput pin.

4
  • 1
    If you do this, you will make the resistance reading dependent on the supply voltage, which is what the OP wanted to avoid in the first place. Commented Mar 15, 2018 at 14:46
  • I see. You are correct; I was only solving the problem of how to compute the supply voltage, but with the supply voltage known, the resistance reading for the thermistor can be calibrated in software. Commented Mar 15, 2018 at 14:57
  • 1
    What Edgar was saying is that the thermistor measure is ratiometric, so using a ratiometric way of measuring the thermistor voltage the supply voltage perfectly cancel out. If you use the 1.1V reference you will have to make more calculations and will have a less precise measurement
    – frarugi87
    Commented Mar 16, 2018 at 8:20
  • Hi, my intention was to know the supply voltage without making the system complicated. I think the value of the voltage doesn't matter as @frarugi87 suggested the two voltages cancel out. If it were not so high it generates tremendous heat and break parts or so low it can't be measured, it's fine.
    – dixhom
    Commented Mar 17, 2018 at 7:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.