Atlas Scientific ENV-TMP


Im hoping I can find some guidance adapting the Atlas ENV-TMP code to the Core and at the same time learn more about microcontrollers. My understanding with the below code is that you take the volts and divide it by the resolution of the analog to digital converter. Beyond that I dont think I understand what the resolution would be :grin: or if there is a better way to go about this.

v_out*=.0048;            //convert ADC points to volts (we are using .0048 because this device is running at 5 volts)

Original Sample Code


@canada7764, more specifically, the voltage equivalent of an Analog input pin on the Core is:

V = analogRead(analogPin) * (3.3 / 4095);
  = analogRead(analogPin) * 0.00081;

where: analogPin is any analog input pin (A0 - A7)
       3.3 represents the maximum input voltage on any analog input pin
       4095 is the maximum decimal value of a 12-bit analog-to-digital (ADC) converter

In the case of the Arduino, the maximum voltage on an analog pin is 5v and it uses a 10-bit ADC, so:

V = analogRead(analogPin) * (5 / 1024);
  = analogRead(analogPin) * 0.0048;

The most important thing to remember is that the maximum voltage you can put on an analog pin of the Core is 3.3v or you will damage the Core. :smile:


This sample code is quite well documented.

But since the Core has some slight differences to the Arduino I’ll just convert the main function into Spark-Speak for you :wink:

void setup() 
  pinMode(D2, OUTPUT);        // we don't really like anonymous numbers ;-)
  pinMode(A0, INPUT_PULLUP);  // do this only once in setup 
                              // and INPUT_PULLUP is a bit clearer than the 
                              // Arduino way with digitalWrite() on an INPUT to
                              // attach/detach an internal pull-up resistor
float read_temp(void){
  float v_out;
  float temp;
  //pinMode(A0, INPUT_PULLUP);  // this got moved to setup()
  digitalWrite(D2, HIGH);       // power up the sensor (but only 3.3V on the Core)
  v_out = analogRead(A0);       // get the voltage reading
  digitalWrite(D2, LOW);        // power off again
  // here comes the maths Paul has already expained ;-)
  v_out *= 3300.0 / 4095.0;     // only in mV already
  temp= 0.0512 * v_out - 20.5128;
  // but there might a way that does incorporate less loss of precision ;-)
  // or fewer calculations
  // e.g. given 0.0512 * 1000 = 51,2 which is the 80th part of 4096
  // temp = analogRead(A0) * 3.3 / 80.0 - 20.5128;
  return temp;

Darn, @peekay123 got to it before me - grrr … :wink:


Thank you @ScruffR & @peekay123.

@peekay123 your explanation was exactly what i needed to get that light bulb moment.


Being the fast reading, instant gratification type I didnt notice you final //comment until after noticing accurate temp range but wild swings. Care to explain?

I’ve just added some more to this comment :wink:

Given the original value of 0.0048 as a “shorthand” for 5.0 / 1023.0 which is more like 0,00488759 as well as the “arbitrary” 20.5128 and the fact that your actual voltage might not be exactly 3.3V, precision should not be the prime concern :wink:

For my part I often limp between very verbose maths in programs, to remember why and how a value needs to be calculated a certain way, or the other extreme to make my code as short, fast and most direct.
So it’s mainly up to you, which of these extremes or anywhere in between you want your code to be. But as you’ve seen with the original - too short doesn’t always help :wink:

But if you say “wild swings” of what kind of magnitude are we talking here?

There are factors that do influence your measurement:

  • time between measurement (faster is often less precise)
  • self heating of your sensor (should be no issue with power on/off and little current flowing)
  • human perception (digital numbers seem to change a lot, while the value actually only changes in a minor decimal place)

To counter act these things, slow down your repetitions, maybe incorporate some averaging (e.g. moving average), draw a graph rather than look at digital numbers.

In this forum there are some threads that do deal with ADC precision, have a look there for more hints.

I’ve just had a look at the datasheet of the sensor and given this

• Wide temperature range: -20 Celsius to 133 Celsius
• Accuracy: ± 1°C
• Fast reading time: <1 ms
• Ultra low operating current: 6 μA
• Wide operating voltage range: 3.1V to 5.5V
• Maximum Vout = 3V

you shoulnd’t need to worry too much about precision :wink:

Along with what @ScruffR said, you may want to add a 0.01uF capacitor between the ADC input pin and GND as was done with other voltage-based sensors. :smile: