DS18B20 reads -127C on Nano ESP32 - reads properly on NodeMCU/ESP8266

The issue is not pin numbering. There is a 4.7K pullup resistor on the data line.
I have tried higher resistor values. Same thing.
The DS18B20 is hooked up to D2 on the board or GPIO5 for ESP32.
I have tried using D2 with Arduino pin numbering and 5 with legacy GPIO numbering.
Nothing works so far.
I'm using IDE 2.3.6.

I have used many DS18B20s with NodeMCU/ESP8266 for years with no problem. I'm thinking of starting to use Nano ESP32 for new projects but not reading the temp properly is a show stopper.

Below is simple demo code from newbiely that uses Arduino pin numbering but it doesn't work for me. The same DS18B20 works fine with NodeMCU/ESP8266.
I have spent days trying everything I can think of. Any suggestions?

/*This Arduino Nano ESP32 code was developed by newbiely.com

  • This Arduino Nano ESP32 code is made available for public use without any restriction

/*

#include <OneWire.h>
#include <DallasTemperature.h>

#define SENSOR_PIN D2 // The Arduino Nano ESP32 pin D2 connected to DS18B20 sensor's DATA pin

OneWire oneWire(SENSOR_PIN);
DallasTemperature DS18B20(&oneWire);

float temperature_C; // temperature in Celsius
float temperature_F; // temperature in Fahrenheit

void setup() {
Serial.begin(9600); // Initialize the Serial to communicate with the Serial Monitor.
DS18B20.begin(); // initialize the DS18B20 sensor
}

void loop() {
DS18B20.requestTemperatures(); // send the command to get temperatures
temperature_C = DS18B20.getTempCByIndex(0); // read temperature in °C
temperature_F = temperature_C * 9 / 5 + 32; // convert °C to °F

Serial.print("Temperature: ");
Serial.print(temperature_C); // print the temperature in °C
Serial.print("°C");
Serial.print(" ~ "); // separator between °C and °F
Serial.print(temperature_F); // print the temperature in °F
Serial.println("°F");

delay(500);
}

I found that it would work if I chose '5' for the pin number, and 'By Arduino pin (default)' as the pin numbering.

1 Like

I still get -127C with '5' for the pin number, and 'By Arduino pin (default)' as the pin numbering. Many people with my issue found it had to do with pin numbering.

I did find a solution that works for me after days of trying.
Use OneWireNg library instead of OneWire and it works with the DallasTemperature example provided in the OneWireNg library. 195 lines of code but it works with multiple DS18B20s. It prints the HEX address of each one and then the temp.

Don't need to: #include <DallasTemperature.h> as OneWireNG does everything.

With the OneWireNG example you can use '5' for the pin number, and 'By Arduino pin (default)' as the pin numbering. So the rest of the program can use board pin numbers like D4.

I had searched "onewire timing issue with nano esp32" as I heard there could be an issue.
And I got:
"Onewire timing issues on the ESP32, particularly with the Nano ESP32 and the Arduino framework, are very common."

" Solutions

  1. Use a robust, ESP32-compatible onewire library
    Replace the standard library with one specifically designed for the ESP32's architecture.
  • OneWireNg: This is a highly recommended, modern alternative to the standard OneWire library. It was designed from the ground up to be more robust for modern microcontrollers and is better suited for the ESP32's environment."

I’ve used many DS18B20 sensors with ESP8266 and ESP32 processors, with the usual OneWire and Dallas libraries: no problems. The ESP32 are mostly from Adafruit, but I’ve also used NodeMCU and, most recently, the XIOA ESP32S3.

The typical guidance for using the DS18B20 with 3.3v processors is to use lower value resistors, like 3.3k or even 2.2k.

I tried lower values as well. NodeMCU/ESP8266 always worked OK with a 4.7K resistor and 3.3V even with 3 sensors and wire length up to 40 ft.
The only thing that worked for me was OneWireNG.
I've had no issues previously with ESP8266 and OneWire.
Apparently OneWire may or may not work with ESP32.
It looks like it works for most people but not me.
OneWireNG is specifically for, and is better suited for, ESP32 apparently.

That depends also on the wire length.
I have build several clocks with DS18B20 sensors attached to ESP32 boards directly (1" wires). There was no need for a pull up resistor at all, just internal pullup on the pin was enough.

Just the standard OneWire library worked fine.
Leo..

What you are seeing (-127°C on ESP32 but not on ESP8266) is a very typical 1-Wire timing sensitivity issue.

The fact that the same hardware works on the ESP8266 but not on the Nano ESP32 strongly suggests that this is not a wiring or sensor problem, but a software/timing-related difference between the platforms. The ESP32 (especially with RTOS, interrupts, etc.) is much more sensitive to timing deviations in bit-banged protocols like 1-Wire.

Switching from OneWire to OneWireNg “fixes” the issue because the implementation is more robust with respect to timing – but it doesn’t really change the underlying nature of the system: communication errors can still occur under real-world conditions.

The important point is that readings like -127°C (and also 85°C) should not be treated as rare anomalies or purely hardware faults. They are normal indicators of temporary communication failures.

In practice, a robust system should therefore not rely on perfect communication, but explicitly handle these cases in software:

  • detect invalid readings (-127°C, 85°C, etc.)
  • retry reads where appropriate
  • validate results before using them
  • use a fail-safe output strategy

In my own measurements, I observed nearly 1000 read errors within ~27 days on a single sensor, while still maintaining completely valid output values by applying recovery and validation logic.

So while choosing a better library helps, the real solution is to design the system in a way that tolerates and handles these errors.

I documented this in more detail here (including measurements and practical strategies):

The issue wasn't occasional read errors. It was reading incorrectly, -127C all the time with Onewire. OnewireNG made it read correctly all the time in my case. I always check if the value is in a correct range before using it.

I’m not clear what you ultimately do with it? I’d be interested …

The sensor can output directly in F
Change this
temperature_C = DS18B20.getTempCByIndex(0); // read temperature in °C
to
temperature_F = DS18B20.getTempFByIndex(0); // read temperature in °F

Note the F in the middle of getTempFByIndex

Leo..

Strictly speaking, no. The sensor only outputs a temperature in °C.

The library call to getTempFByIndex reads the °C temperature from the ds18b20 and converts it to Fahrenheit.

Pete

1 Like

Many of the following projects use DS18B20s to measure temperature to control heaters. Also used to modify the thermostat for my gas furnace to save many dollars.

Previously I used Nodemcu/esp8266 but I'm thinking of using an Arduino Nano ESP32 from now on so was testing the many functions I use with it. Temperature was an issue until I found OneWireNG. I also found with Nodemcu it's best to use the sensor address with multiple sensors or the values can be mixed up.

I understand, but it makes the user code a bit more transparent if you let the library calculate it. High time that the US and it's territories switch to what most of the world uses: Celcius.
Leo..

Maybe off-topic, but about that Celcius-switch thing...

For the same reason there is no such thing as the centigree, where a circle has 100 degrees, and stepper motors step at 1.8 degrees. Functionality.

Fahrenheit divided the liquid phase of water into 180 degrees. Half a circle. Perfect for a dial on a scale in his time. And why not 180? The circle has 360 degrees, and no worldwide protest. Why does the circle have 360 degrees? Because an ancient culture "thought" there were 360 days in the year... so the Degree is one, big, joke, but Water and Circles are what makes the world go "round." Yes, there is a pun in this truth.

Why Centigrade? Why does the world not stop using the arbitrary Celcius scale and move to Kelvin? Kelvin is an absolute scale, in which water begins its liquid phase at 273.15K (Celcius... is not perfect). Almost looks like the "Fahrenheit" values... perhaps that is why the change to Kelvin won't happen... admitting the centigrade scale is arbitrary.

Picking yet another arbitrary scale for the liquid phase of water, and saying Fahrenheit is not a valid scale, is just mob mentality.

And about that "meter." Not only is the meter arbitrary (first it was one ten-millionth of the distance from the equator to the North Pole, and recently the distance traveled by light in vacuum in 1/299792458⁠ of a second), but the physical meter metric was fake, because one explorer fudged his records (too lazy to get it right), and even better than this lie-turned-defacto, the fudging was known while the meter-standard was established. Now, "the world" (minus a few outliers) abide by an extremely accurate fake measurement "ruling" the world, and mocking the King's Foot.

Personally, I like more than two or three degrees to decide "jacket and hat" or "t-shirt and shorts"

So... that's why.

Nice to see someone working on projects in a similar direction as I am!

I don’t want to impose, but since the hardware side seems to be sorted out, I’d like to share a practical suggestion:

In real-world applications, it’s not a question of if but when you won’t get a valid temperature reading from one or more sensors — but I’m sure you’ve already experienced that yourself.

That’s why I recommend using the sanitizeTemp() function in the critical if statement where you control outputs, to ensure logical safety:

Also, since some actuators don’t tolerate being switched off and on again within the next loop — or certain situations simply can’t handle that behavior — I’d additionally suggest this approach:

Wishing you success with your projects, and I’d be glad to hear whether this input turns out to be useful for you.

1 Like

nope, 360 was chosen as it has many dividers, in fact it is a multiple of 60 which has 12 factors , which was the chosen math system of the Babylonians and Sumerians. Their choice was made for such a (highly composite) number as it allows them to divide it easily without decimals for several numbers.

60 = 2 x 2 x 3 x 5
360 = 2 x 2 x 2 x 3 x 3 x 5
60 has 12 factors {1,2,3,4,5,6,10,12,15,20,30, 60}
360 has 24 factors { 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 18, 20, 24, 30, 36, 40, 45, 60, 72, 90, 120, 180, 360 }

Wrt temperature scales, there are many that are far more fun than Celsius or Fahrenheit
See - Online temperature conversions for 73 different scales, a world’s record

I think that forces factual data.

If I were in a primative (not advanced, as with Babylon, Aztec, et c.) civilization, I would try solving "when the sun would return" (days, seasons, yearly cycle) before factoring numbers... but that's using "shelter, fire, food" as a guide, rather than what the philosopher might be solving to explain the cycles. It is amazing, the knowledge they had, and lost.

It is these lost volumes of knowledge that underline how Fahrenheit is no worse than the metric system's flawed response.

"Factoring" in all countinng systems are the same, regardless of base 2, 5,10, 12,16, 18. Consider a counting system that is a physical item, and remove parts/factors from it. You still get parts of the whole, and each part then becomes its own "whole" counting system. So, never a fraction, just a new, smaller, counting system.

I would put the importace of having a calendar far before ethereal number systems.

1 Like