1

So I am trying to use this thermistor to measure temperature and with this code below it always puts the same value (2147483647). I used this tutorial to do the wiring and coding. I don't think the wiring is the problem but think the problem is somewhere in my code or perhaps I am using a wrong type of thermistor? Am I missing something? Any help is greatly appreciated.

I am only using a 1k resistor in series with the thermistor but don't think that would be a problem, right?

Edit: I should have mentioned I'm using the adafruit huzzah esp8266 so there are a few pins.

#include <DHT.h>
#include <ESP8266WiFi.h>
#include <Phant.h>
#include <ESP.h>


#define DHTPIN 2
#define DHTTYPE DHT22
#define THERMISTORPIN 4


DHT dht(DHTPIN, DHTTYPE);

const char* ssid = "xxxx";
const char* password = "yyyyyy";
const char* host = "data.sparkfun.com";
const String publickey = "uuuuuu";
const String privatekey = "ttttttt";
const byte NUM_FIELDS = 5;
const String fieldNames[NUM_FIELDS] = {"ghumidity", "gtemp", "light", "otemp", "wtemp"};
String fieldData[NUM_FIELDS];

//thermistor variables
const int thermresistor = 987; //value of resistor in series with thermistor
int thermtemp = 0;
uint8_t i;
uint8_t numsamples = 5;
uint8_t To = 25;
const int B = 3950;



void setup(){
    Serial.begin(115200);
    delay(10);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
  delay(500);
}

    fieldData[0] = 1; //humidity
    fieldData[1] = 2; //garden temp
    fieldData[2] = 3; //light
    fieldData[3] = 4; //outside temp
    fieldData[4] = 8; //water temp


//turnpumpon();
posttophant();
//turnpumpoff();
ESP.deepSleep(1200000000, WAKE_RF_DEFAULT);

}


void posttophant()
{
    fieldData[0] = dht.readHumidity();
    fieldData[1] = dht.readTemperature(true);


    //read outside temp (otemp) data and convert to a temp
    for (i=0; i<numsamples; i++){
      thermtemp = analogRead(THERMISTORPIN);
      thermtemp += thermtemp;
      delay(10);
    }

    //take the sum of all the readings and divide by # of samples to get avg.
    thermtemp = thermtemp / numsamples;

    #voltage divider equation
    thermtemp = thermresistor / (1023 / thermtemp - 1);


    //Steinhart eqn.
    thermtemp = 1 / (log(thermtemp / thermresistor) / B + (1 / (To + 273))) - 273;
    fieldData[3] = String(thermtemp);

    WiFiClient client;

    const int httpPort = 80;
if (!client.connect (host, httpPort)){
  return;
}

    client.print("POST /input/");
    client.print(publickey);
    client.print("?private_key=");
    client.print(privatekey);
    for (int i=0; i<NUM_FIELDS; i++)
    {
      client.print("&");
      client.print(fieldNames[i]);
      client.print("=");
      client.print(fieldData[i]);
    }
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(host);
    client.println("Connection: close");
    client.println();
}
  • i would consider using the thermistor as an RC's R, allowing more precise measurement than 10bits. – dandavis Mar 31 '17 at 4:01
  • A 10 kΩ series resistor should give you significantly better resolution. – Edgar Bonet Apr 1 '17 at 8:11
  • Can you please give a hint how can I deal with a following issue ? Because of space limitations, I've to share ADC and one of GPIO's, meaning that in one case, controlled by software GPIO should be used for it's original value (digital IO), ignoring ADC, and on another occasion, ADC should be used without being overloaded by GPIO current. Is it theoretically possible to use one terminal for both pins ? Thank you. – Sergiy Sep 7 '18 at 15:00
2

Considerations about the ESP8266 analog pin

The ESP8266 has only one pin that allows analog read. This pin is call A0 on the NodeMCU module or A on the ESP8266 Huzzah (some other ESP module don't expose that pad - for example ESP8266-01) or might label it differently - check the documentation of your ESP module. Following your edit: make sure that you connect your thermistor to the A pin of the Huzzah ESP8266 module.

You should keep in mind that this analog pin is a 10bit ADC with in principle limited input voltage range.

To read an external voltage applied to the ADC pin, use analogRead(A0). Unless you are using a board specially design to increase its range, the input voltage range is 0 — 1.0V. As @dandavis pointed out some boards (Node MCU e.g.) include a voltage divider on board to give you a full 0 - 3.3V input range.

Thermistor equations

The datasheet of your thermistor states that the TCR coefficient is 3000ppm/%C and has a 10K value [note that the manufacturer doesn't provide you with the temperature at which R = 10K]. The equation of the resistance variation ∆R with temperature variation ∆T is given by:

∆R = ∆T*10k*3000ppm = 30*∆T

So if T_0 is the temperature where R = 10k, the equation of the resistance value is given by:

R = 10k + (T-T_0)*30

I am assuming that you are using the 3.3V supply of your ESP and creating a voltage divider using the 1K resistor and the thermistor. There are two ways to do this divider:

1. Voltage divider option 1

schematic

simulate this circuit – Schematic created using CircuitLab

[Note that the thermistor needs to be connected to the A pin of your ESP8266.]

2. Voltage divider option 2

schematic

simulate this circuit

Equation of voltage at node A

For both case here is the voltage V_A seen at node A:

1. Voltage divider option 1

V_A = R_series *3.3 / (R_th + R_series)

2. Voltage divider option 2

V_A = R_th *3.3 / (R_th + R_series)

Analysis of the variations of V_A with temperature

Lets look at the difference between the 2 formulas above:

1. Voltage divider option 1

The numerator is a constant with temperature while the denominator changes with T. You will get a strong variation.

2. Voltage divider option 2

Both the numerator and denominator increase with temperature. You won't get a lot of variation on V_A with temperature. You should avoid this configuration.

Analysis of the maximum allowed value of R_series

The important consideration is that for your ESP module V_A cannot be higher than 1V.

1. Voltage divider option 1

Increasing R_series will increase V_A so we compute a maximum value: 1V = 3.3V*R_series_max/(R_series_max+10K)

That gives you: R_series_max = 4300Ohms

2. Voltage divider option 2

Increasing R_series will decrease V_A so we compute a minimum value: 1V = 3.3V*10k/(R_series_min+10K)

That gives you: R_series_min = 23kOhms

This is the reason why it was suggested to you using a 30k resistor in that case.

Considerations about temperature measurement precision

The voltage variation ∆V on the node A of the ESP between temperature T1 and T2 can be computed as follow: ∆V = 3.3 *1K/(1k + 10k + 30*T1) - 3.3 *1K/(1k +10k+ 30*T2)

If we assume that the thermistor is 10K for ambient temperatures the baseline voltage measured on the A pin is: 3.3V*1K/11k = 0.3V

For a 0 to 1V 10bit DAC of the ESP8266 that is around: 2^10*0.3 = 307

A change of 10C would lead to a variation of voltage of: ∆V = 0.3 - 3.3 *1K/(11k + 300) = 8mV ~8ADC code

The equation of ∆T vs ∆V is not linear but for small variation of temperature with your current setup you get ~1ADC code per degree.

Depending of your application this might not be enough for you. As suggested in several comment you could:

  • Add more thermistors in parallel
  • Increase the 1K series resistor (but not too much or you will saturate the ADC).
  • Change the architecture of the measuring circuit (RC oscillator using the thermistor and interrupt counter in the ESP, 555 timer circuit loaded with the thermistor and interrupt counter, ...)
  • Or since you want to do humidity and temperature measurement why don't you get the BME280 module. It can be read over I2C and libraries are readily available to read it with the ESP8266.
  • 2
    1.0 nodeMCU boards accept 0-3.3v. the ones that fit on a bread board and have cp2102s – dandavis Mar 31 '17 at 3:31
  • @dandavis wasn't aware of this interesting feature (so far I have only be using the ESP-01 myself). – vrleboss Mar 31 '17 at 3:55
  • @dandavis thinking about it, this integrated on-board voltage divider can be dangerous if the source impedance is very high. Although not the case here. – vrleboss Mar 31 '17 at 4:02
  • 1
    might consider two thermos in parallel for a lower R and averaged errors (they are cheap anyway) – dandavis Mar 31 '17 at 4:08
  • 1
    vrleboss, denominator (11k + 0.003*10), which is 11000.03, should instead be 1KΩ + (1 + 0.003*10)*10KΩ, which is 11300. That is, 3000 ppm of 10KΩ is 10000 * 3000/1000000 Ω, or 30 Ω per degree – James Waldby - jwpat7 Mar 31 '17 at 5:06
1

Re “the problem is somewhere in my code”, lots of places in the code have problems.

• The following loop does not add up readings; it takes a bunch of readings and throws them away, then doubles the last one. For example, if the five readings in a row are 300, 400, 500, 600, and 100, thermtemp is 200 after the loop. To see this, try it out – mentally simulate what the code does, writing down the value of thermtemp after each step.

for (i=0; i<numsamples; i++) {
   thermtemp = analogRead(THERMISTORPIN);
   thermtemp += thermtemp;
   delay(10);
}

• Your “voltage divider equation” (below) has a form like that shown in the Adafruit tutorial, but because your thermtemp is declared as an int (vs Adafruit's float), integer division with truncation will be used, producing inaccuracy.

thermtemp = thermresistor / (1023 / thermtemp - 1);

• Your Steinhart-Hart equation is miscoded. At that step, the fixed resistor's value, thermresistor, is no longer relevant. The relevant value is the ADC reading as converted to thermistor resistance.

• In your Steinhart-Hart misimplementation, log(thermtemp / thermresistor) takes log of zero because in integer arithmetic, thermtemp / thermresistor is zero.

• The expression 1 / (To + 273) is zero in integer arithmetic.

  • As for the for loop I thought saying... thermtemp += thermtemp; would add the just read value to the previous total and store that new value into the variable? I see what you are saying about the integers, haha, still learning and was trying to save storage space. I'll make those changes. – willocks1718 Mar 31 '17 at 2:37
  • @willocks1718, yes, thermtemp += thermtemp adds thermtemp to thermtemp, which doubles it. Go through it manually, writing down the value after each step: 300, 600, 400, 800, 500, 1000, 600, 1200, 100, 200. – James Waldby - jwpat7 Mar 31 '17 at 3:04
  • sorry I meant if the first reading was 300 that gets stored into thermtemp. With the next reading being 350 or so it would add it to the previous value and store it to get 650. Basically it would sum the next x readings. So that is incorrect thinking? – willocks1718 Mar 31 '17 at 14:01
1

There are a few possible issues you're having:

First off, from what I understand, the ESP8266 ADC only reads up to 1V. If wired per the Arduino example you cited, and using 1K, you'll have VCC->1K->THERMISTOR->GND. At room temp the thermistor is 10K, so the voltage at the ADC will be 3.3*(10K/(1K+10K)), so pretty close to 3.3V. I don't know the behavior of the ADC when overrange, but I'd assume you'd just get 0xFFFF. You'll probably want >30K in series with the thermistor to get it into a usable range.

I also see a subtle error(I think) in your code:

//read outside temp (otemp) data and convert to a temp
for (i=0; i<numsamples; i++){
  thermtemp = analogRead(THERMISTORPIN);
  thermtemp += thermtemp;
  delay(10);
}

Should be:

//read outside temp (otemp) data and convert to a temp
thermtemp = 0
for (i=0; i<numsamples; i++){
  thermtemp += analogRead(THERMISTORPIN);
  delay(10);
}

Otherwise thermtemp is just the last reading added to itself.

Lastly, I would probably make the part of the code that posts the result to a function and call it throughout your calculations of the temp, to see if anything weird happening.

Hope this helps.

  • I didn't realize that about the pin only reading 0-1V, thanks. I have some resistors coming, and will figure out what value I need. As for the for loop I was trying to add the new value to the previous value and re-store the sum to the variable again, apparently the way I tried to do it doesn't work though so I'll fix the loop – willocks1718 Mar 31 '17 at 2:46
  • 1
    fwiw, on the cp2102-based NODEMCU boards, there's already two high-ohm resistors on A0 to allow a 0-Vcc range, which i find very useful. – dandavis Mar 31 '17 at 3:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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