Atmega328 internal temperature sensor (yes it exists!)


  • Mod

    I few days ago I learned something new about the atmega328: it has an internal temperature sensor.

    The specs are awful: +-10 degrees C! This is uncompensated though.

    Also, the internal temperature sensor will (of course) read a higher temperature when the mcu is running. But many MySensors nodes sleep almost all the time, and will not generate heat because if it did it would drain the battery pretty quickly.

    I decided to put the sensor to test, comparing it with a BME280.

    I first ran it with the "default" compensation using the code at http://www.netquote.it/nqmain/2011/04/arduino-nano-v3-internal-temperature-sensor/
    The BME280 said 23 degrees, the Atmega328 internal sensor said -9.6 degrees C. That's 73 vs 15F for our friends dominated by the imperialists.

    I added the (linear) compensation to bring it back to 23 and let it log data for almost 40 hours. This was the result:
    0_1535915778309_4a02e06b-2a5c-4219-aead-66c81038eb16-image.png

    The difference:
    0_1535915802088_0157ce8d-0180-4327-b66d-b9074f08b6fa-image.png

    After adjusting the compensation (not sure why the original compensation was so off):
    0_1535915973056_48c177ae-60f9-4e84-abad-f8b6469b5a6f-image.png

    Difference:
    0_1535916472461_aabc9c4d-def5-4f8b-8fa8-81f998588a98-image.png

    So for normal indoor temperatures, it seems like the internal temperature sensor can be quite OK, as long as it is compensated. I think I'll add this temperature reading to my plant monitor nodes. It is free, and it probably has the same level of accuracy as the DHT22.

    It would be interesting to see the difference over a larger temperature span, but that will have to wait for another day.

    Sketch:

    // Based on http://www.avdweb.nl/arduino/hardware-interfacing/temperature-measurement.html
    #include <avr/pgmspace.h>
    
    #include "ChipTemp.h"
    #define MY_DEBUG
    #define MY_GATEWAY_SERIAL
    
    #include <MySensors.h>
    #define CALIBRATION_TEMP 23
    
    ChipTemp chipTemp;
    
    void setup()
    {
      Serial.begin(115200);
    }
    
    void loop()
    {
      Serial.print(chipTemp.deciCelsius() / 10.0, 1); Serial.println(" ");
      Serial.print("New offset at CALIBRATION_TEMP degrees: "); Serial.println(chipTemp.deciCelsius() * gain / 10 + offset - gain * CALIBRATION_TEMP);
      sleep(60000);
    }
    

    Read more: https://playground.arduino.cc/Main/InternalTemperatureSensor (especially the links at the end)


  • Hardware Contributor

    I wish I had a home that fresh 😄

    Thank you for the time taken to test and report, I knew about didn't think you could keep that close to a temperature sensor even after individual calibration.

    Question is, is it worth the time to calibrate each atmega compared to adding a cheap i2c sensor ?


  • Hero Member

    Does the difference remain small over a wide temperature range? I doubt it.


  • Mod

    @nca78 if a single calibration at room temperature is enough, I’d say it is. Quick and simple. But if i need to put the node in the freezer to get a second calibration point, it would take too much time.

    My guess is that one calibration point is insufficient, since my tests show increased drifting both at ~24C (-0.4C) and ~21.5C (+0.3C). So as soon as we get away from the 23C calibration point the accuracy becomes bad.


  • Hero Member

    It would be an interesting experiment to gather data at every point over a wide temperature range. That chip would then be perfectly calibrated. The question would then be: how well do other chips follow the same curve? Maybe they follow it reasonably closely. Or, maybe they don't. I suppose it depends on manufacturing tolerances.

    As far as I know, no one has done that experiment.


  • Mod

    @neverdie from what I have read, there will be large differences between different chips. Similar to the pullups not being exactly same, and the internal band gap reference being different.


  • Mod

    @mfalkvidd This appnote contains a conclusion on accuracy:

    • One-point calibration. Offset removal using room temperature as reference gives +/-5°C accuracy from -30°C to 100°C and +/-3°C accuracy between 0°C and 85°C.
    • Two-point calibration. Here, +/-1°C accuracy from 5°C to 95°C can be achieved.


  • Interesting to know that atmega328 has a temperature sensor!
    I'm thinking the calibration doesn't need to be completely manual and shouldn't be requiring us to flash the µC again just to recalibrate. we could connect an I2C sensor just during calibration and disconnect it after calibration is done. the firmware could get data from both internal and external sensors and store the calibration data in eeprom. This data can then be read back to measure properly using internal sensor after deploying.
    It is even possible to remove the need to flash the µC after the calibration, if the calibration logic is part of the production firmware itself.


  • Mod

    While browsing the MySensors source code, I stumbled on this code that shows that support for the internal temperature sensor is already included in the MySensors library, including offset and gain calibration.

    Just call hwCPUTemperature()


  • Plugin Developer



  • @mfalkvidd that is pretty nifty. I need to figure out how I can use this. Thanks for keeping this discussion active. Little things like that have the possibility of saving even more power.



  • @mfalkvidd said in Atmega328 internal temperature sensor (yes it exists!):

    hwCPUTemperature()

    sorry, stupid question maybe, but with my 328p based sensors hwCPUTemperature() is not automatically callable using just
    #include <MySensors.h> --> neither with 2.2.0 nor with 2.3.0

    Do I have to include /hal/architecture/AVR/MyHwAVR.h ?
    Cannot compile it, what path should I use in the #include statement? ☹


Log in to reply
 

Suggested Topics

10
Online

11.4k
Users

11.1k
Topics

112.7k
Posts