Save the Earth One Resistor at a Time – External pull-up resistor no longer needed for DS18B20 temp sensor


Using the updated Arduino 1-Wire library code presented here, you can eliminate the need for an external pull-up resistor for typical small networks of DS18B20 temperature sensors.  This should also work with any AVR processor and other types of 1-Wire devices as well. You can download the updated 1-Wire library here…

The mythical “required” external pull-up

From the DS18B20 Data Sheet

From the DS18B20 Data Sheet

If you’ve ever used the ubiquitous (and amazingly useful!)  DS18B20 family of 1-Wire temperature sensors, you’ve almost certainly used a 4.7K ohm pull-up resistor as well. Every one of the seemingly endless Arduino DS18B20  tutorials on the web starts with some version of the line “You will not be able to do anything with this senor until you go out and procure yourself a 4.7K ohm resistor”. AdaFruit is even generous enough to include one of these resistors with every DS18B20-based temperature sensor they sell (be it bare, waterproof, or hi-temp) because they know you are going to need it.

I am here to tell you that everything is about to change. If you were banking on your stockpiles of 4.7K ohm resistors to be the one reliable store of value in these uncertain times, you need to rethink your long-term asset preservation strategy because the decade-long run of stable demand for this part is about to plummet. Yes – it is now possible to connect DS18B20 sensors without any external pull-up resistor at all!

Outrageous claims demand outrageous proof, so let’s start with a brief demo that proves beyond a shadow of a doubt that this is not just a cockamamie theory, but cold hard fact…

Understanding the pull-up

In the time-tested tradition, the 4.7K ohm pull-up resistor is always connected between the power and the bus and holds the bus high unless either the master or one of the salves is actively pulling it down. This is handy because multiple devices can pull the bus low at the same time and nothing bad happens. There is a neat protocol that everyone follows that lets them carry on orderly communication on this shared wire.

It turns out that the processor in the Arduino has built-in internal pull-ups on the I/O pins that can be enabled via software. These pull-ups can be very handily because they let you, say, connect a switch between a pin and ground. The pull-up will hold the pin at high unless the switch connects it to ground. These internal pull-ups are specified in the Data Sheet as 20K-50K ohms…

Pull Up Capture

While this is a lot more resistance than the 4.7K ohms specified for the 1-Wire pull-ups, we can still make it work for many cases. There real limiting factor here is time – the time it takes for the bus to come back up to a high level after one of the devices is finished pulling it to low.

Without going into too much detail, here is what it looks like when a 1-Wire master reads a bit from a slave (also from the DS18B20 data sheet)…

Rad 1-wire bit Capture

The master will pull the bus low to tell the slave it is ready to read a bit, and then it will let go of the bus to see what happens. If the slave wants to send a 0, it will signal so by pulling the bus low. If the master sees that the bus is STILL low even after it has let go of it, then it knows that the slave is sending a 0 bit. If the slave wants to send a 1 bit, then it does nothing and just lets the bus get pulled back up to high when the master lets go. The master looks at the bus after it has let go, and if it has returned to high then it knows that the slave sent a 1. Cool, right?

In the case of the slave sending a 0 bit, the pull-up has no effect during the actual bit transmission. We go from the state of the master actively pulling low, to the state of both the master and the slave actively pulling low, to the state of just the slave pulling low. The bus is actively low throughout the entire bit and would be so even with no pull-up at all.

In the case of the 1 bit, we need the pull-up to pull the bus high after the master lets go. This is the moment that the red arrow is pointing to above. The stripped area underneath the arrow is time period where the bus is being pulled from low to high by the pull-up. This does not happen instantly because the pull-up resistor, the devices on the bus, and the wires connecting them all form an RC circuit.  The bigger the resistance and the capacitance, the longer it will take for the line to get back up to a high level.

The spec says that in the case of a 0 bit, the slave will pull the bus low within 1us of the master pulling it low, and will hold the bus low for at least 15us after. To be able to tell if the slave was sending a 1 or 0 bit, the master looks at the bus during this time to see if it stayed low (the slave was pulling it low to send a 0 bit), or it returned to high (the slave sent a 1 bit by not doing anything and just letting the bus get pulled back up to high after the master let go).

These protocol constraints limit the size of the pull-up resistor and the capacitance of the system. If it takes the bus longer than 15us to return to high after the beginning of this sequence, then the master will see the bus as low and falsely think that the slave was sending a 0 bit. Since the spec also says that the master must hold the bus low for at least 1us to start the whole process, so we are left with 14us for the pull-up to pull the bus up from low to high.

Reading a

“1” bit with an external pull-up

The yellow trace at the bottom is a trigger I setup to to show when things happen. The trigger goes high when the master lets go of the bus, and then goes low when the master reads the bus to see if a “0” or “1” bit is present. The blue trace is the bus and you can see a nice steep RC curve where the bus rises after the master lets go. It just makes it back up to 5 volts by the time the master reads it.

So, can the internal  50K Ohm (worst case) internal pull-up do the job? Well, it all depends on the resistance and capacitance of the devices on the bus and the wires connecting them. It turns out that this is also a limiting factor when using an external 4.7K pull-up, it is just that the smaller pull-up resistor will give you more headroom for higher resistance and capacitance in the network.

There are very helpful documents that give heuristics to determine how many devices, how much wire, and what configurations will work on normal 1-wire networks with external resistors. All these same hints apply to networks driven by internal 50K Ohm pull-ups, you just get less of everything.

Aim low

For everything to work, our pull-up must be able to pull the bus back up to a “1” within 14us. But what is the minim voltage for the master to see a “1” bit?

Since we are using a digital input pin of our AVR to sense the bus, and since we are running with a supply voltage (Vcc) of 5 volts, the datasheet gives the answer here…


Minimum input voltage level for a 1 bit when running at 5 volts

We need at least about 2.6 volts on the I/O pin for it to be seen as a “1”.

Can it work?

It turns out that this is just a classic RC circuit that looks like this….


The larger C1 is, the longer it will take to charge though the 50K ohm pull-up resistor. We need to find the largest value of C1 that will get the bus up to 2.6 volts in less than 14us.

We can use the formula..

Vc = V * (1- e^(-t / R*C))

…to figure out that we can just make it under the wire if C1 is 400pF. Any larger and the bus might be lower than our 2.6 volt threshold at the end of the 14us (you can check my work here).

400pF is not a lot of capacitance. Can it possibly work?

There are 3 main sources of capacitance in 1-wire networks – the nodes (our DS18B20’s), the wires, and the input pin on the master.

The data sheet for the DS18B20 tells us that the data pin has a maximum capacitance of 25pF…


A typical capacitance for twisted pair wire is on the order of 1pF per inch.

The capacitance of an input pin of a microcontroller like our AVR is typically on the order of 20pF.

Because all of these capacitances are in parallel, we can just add them together to find the total capacitance.

So, as long as stay within the parameters of this formula…

( sensor_count * 25pF ) + ( total_length_of_wire * 1pF/inch ) + 20 pF < 400pF

…then it might just work!

But does it actually work in real life?

It really works. 1 meter of wire with 4 sensors works. 10 meters of wire with 1 sensor works. 3 meters of wire with 2 sensors works. Try it.

Practical usefulness

My hunch is that the internal pull-up will be good enough for the vast majority of people using the DS18B20 sensors. The new library is looks the same as the old one to the programmer and will work with or without an external pull-up, so you can use it for all your projects and hopefully save the resistor most of the time.

If you need dozens of sensors dangling from dozens of meters of wires to monitor the core of your breeder reactor for partial melt, then you can splurge the extra $0.02 for a potentially superfluous external pull-up without hurting my feelings.

Note that in cases where the internal pull-up is not strong enough, you will know it because you will not be able to communicate with the sensors, at which point you can simply add an external resistor and it automatically start working (assuming that the external pull-up is strong enough for your network).

Software Implementation

It turns out to be almost trivially easy to enable the internal pull-up in on an AVR digital I/O pin in software. It is also very easy to add the required code to the existing 1-wire library. You can see the changes needed to the original 1-Wire code here…

The changes are slight – 2 lines added and 2 removed.

The basic idea is to turn on the internal pull-ups anytime the bus is not being actively driven (either high or low) by the master. This even saves a bit of power (about 10 trillion electron-volts per reset pulse!) in the case when the master is actively driving the bus low because it is no longer fighting against the external pull-up.

The resulting new code is backwards compatible with the old code, and will work with or without external pull-up resistors.

While I had the code open, I also added a new function that lets you tell the difference between a shorted bus and a bus that just has no slaves on it. The function is called busFail() and could be useful in debugging failed networks.

You can find the latest Version of the library here…

Installation Step-By-Step

  1. Download, install, and run version 1.6.4 or higher of the Arduino IDE.
  2. Download the DallasTempurature library as a ZIP and install it by choosing “Sketch->Include Library->Add .ZIP Library…”
  3. Download the OneWireNoResistor library as a ZIP and install it by choosing “Sketch->Include Library->Add .ZIP Library…”
  4. Open the example program by choosing “File->Examples->OneWire No Resistor->NoPullupTester”.
  5. Connect a temperature sensor(s) to your Arduino as shown above.
  6. Run!


Q: How can there be enough current going though the 50K Ohm internal pull-up to power parasite devices on the bus?
A: The DS18B20 chips are spec-ed to pull 5uA when idle (IDQ) . This means a voltage drop of only 0.25 volts per slave device. Since we are starting at 5 volts, and the DS18B20 chip is spec-ed to run down to 3 volts (VDD), then we should wost case be able to get up to 8 salves on the bus before the voltage drop across the internal pull-up is the limiting factor.

Q: How about the 1.5mA per slave needed during a temperature conversion or EEPROM write?
A: Despite the dire admonishment on the wiki, the 1-Wire library actively drives the bus high during these power hungry events if there are devices are running on parasite power. This means that the pull-up resistors (internal or external) are irrelevant in these cases. A digital I/O pin is spec-ed to be able to drive 20mA, so you should be able to do a simultaneous temperature conversion with up to a dozen parasite-powered sensors on the bus. In practice, I’ve done even more and it worked fine so the sensors are probably drawing less than the spec-ed 1.5mA maximum current.

Q: Help! I need to add more slaves/wire to my network and I am just not willing to fork over my hard earned money to buy that external resistor unless it is 100% necessary!
A: We still have some tricks up our sleeves to get even more headroom out of our networks. Our limiting factor above was that the “1” bit did not have time to rise all the way up the level where it could be register as a “1” on the digital input pin (about 2.6 volts). Even though there is not enough voltage for a digital I/O pin to see it as a “1” we can clearly see it is rising just by looking at it. If we were to switch over to an analog input pin, well then we could detect rises as small as micro-volts! This would give us much, much more headroom on both internally and externally pulled-up networks. And, it just turns out that the way our AVR chip samples analog pins works out perfectly for this task. There is way too much info to shove in this FAQ answer- but maybe I’ll write a follow-up article with working code if there is enough interest.

Q: Wait, I understand everything about the internal pull-up, but how did you get the the sensor to work directly plugged into the Arduino header?
A: Easy – I just added the following lines of code to the setup() function…

  // This lines just make it so you can plug a DS18B20 directly into 
  // digitial pins 8-10. 
  digitalWrite( 8 , LOW );
  pinMode( 8  , OUTPUT );
  digitalWrite( 10 , LOW );  
  pinMode( 10 , OUTPUT );

These two pins are now driven low and effectively ground, so both the Vcc and the ground of the sensor are now connected to ground even if you plug it in upside down (remember that Vcc can go to ground and not power because we are using parasitic power off the data pin in the middle).

Q: Why the frick don’t you just buy a frickin’  $0.02 resistor you frickin’ cheapskate!
A: I actually have boxes of 4.7K resistors sitting on my shelf. That is not what this is about. I ended up working on this because I was writing instructions for a DS18B20 temperature logger and got stuck on the part about hooking up the pull-up. I looked around the web, and everyone said the external resistor was “required” with no explanation.I bet there are lots and lots of people who have excitedly sat down to build a project with a brand new DS18B20 sensor that they picked up on the way home, only to loose all their momentum when they found out that they need an extra part that they didn’t have. Hopefully now future generations of DS18B20 builders will avoid this frustration.

I am also obsessed with eliminating hardware with clever software wherever possible. Hardware is mater and is therefore you have to manufacture, move, and dispose of each and every hardware part used.  None of these these problems apply to software – write it once and and it can be efficiently used infinitely many times in infinitely many places by infinitely many people. And when you dispose of an old piece of code, you have more room than when you started rather than less. We will never run out of room for code landfills. I’d guess that clever software could eliminate about 20% if the matter in most technological objects. Think about a world where every phone, computer, and car was 20% less stuff. Think about the effort required to manufacture all that needless mass, and to transport it around the world, and then to dump it. I am happy to trade some of my time to get rid of the need for a widely used $0.02 resistor!


  1. AndrewN41

    If you have a spare digital IO pin you can tie two of them together providing two internal pull up resistors (once configured). You still only read and write through one pin, but you will be able to handle more devices without the external resistor. Nice article.

    • bigjosh2

      Absolutely! You could even tie 8 pins together and just about match the 5kohms spec’ed for an external resistor.

      As long as all the pins were on the same PORT, then there would not even be any performance cost and only a very slight code modification (changing the bit mask).



  2. anon

    After receiving 2 DS18B20 in the mail today, I was disappointed I didn’t have a pull up resistor. I stumbled across this and it worked beautifully for me. Thank you!

  3. Fredrik

    Hmm, I get the value 85.00 from my sensor?

    I’ve connected them to port 8,9,10, downloaded you version of the OneWire library and the normal dallas one, and done the digital writing in the beginning, my code:

    float temperature1;
    float temperature2;
    OneWire oneWire(9);
    DallasTemperature sensors(&oneWire);

    void setup() {
    digitalWrite( 8 , LOW );
    pinMode( 8 , OUTPUT );
    digitalWrite( 10 , LOW );
    pinMode( 10 , OUTPUT );


    void loop() {
    temperature1 = sensors.getTempCByIndex(0);
    // Serial.println(a);
    // temp++;
    // delay(5000);


  4. Trev

    I did a quick experiment with this today, using a Leonardo. and an 18B20.

    With this code, I was able to use the device without the pullup only by attaching the third pin of the 18B20 to 5V. It worked in that mode with this library, but not with the stock OneWire. When I removed the 5V from the 18B20 it didn’t respond with either library.

    I didn’t scope it as I had a 2K resistor sitting around that worked as a pullup.

    In my application I have a few other passives so I will keep the 4.7K, but this is an interesting take.

    • bigjosh2

      On the standard part, the Vdd pin (pin #3) must be connected to ground when operating from parasite power. There is also a version of the part called the DS18B20-PAR that has the Vdd connected to ground internally, so pin #3 is not connected to anything.

      • Trev

        Ah! RTFM!

        I’ve always been using them with all three pins dutifully connected. This was my first attempt at reducing the connections. Very cool.

        Now for your next trick, figure out how to reduce the passives count when using a split core current sensor….

  5. Trev

    For further data, the Sparkfun waterproof sensor ( has been working for me for a few days with the third wire unconnected but using a pullup on the data line. I’m not sure if internally it uses the -PAR part, but I’m guessing not or the third wire would be omitted.

    I did notice though that over time it reverted to a higher precision than I originally set. So I suspect it self-reset once, but it returned and continued to report. I’ll hazard a guess that this configuration is not recommended.

    I will build another prototype shortly and see if it will work using your code and no pullup.

  6. regionalistecz

    I have errors with the NoPullupTester during compilation of the code:
    NoPullupTester.ino: In function ‘void loop()’:
    NoPullupTester.ino:50:17: error: ‘class DallasTemperature’ has no member named ‘reset’
    NoPullupTester.ino:56:19: error: ‘class DallasTemperature’ has no member named ‘busFail’
    ‘class DallasTemperature’ has no member named ‘reset’

    I have latest IDE 1.6.4, DallasTemperature (3.7.2) and your OneWire libraries via GitHub.
    Where is the problem?

    • bigjosh2

      Ok, I just updated the package to be compatible with the new Arduino library manager stuff. It should now be very easy to get the example program up and running. Check out the new step-by-step instructions at the bottom of the post and let me know if you run into any problems. It might make sense to delete any old installs of either the DallasTempurature or OneWireNoResistor folders in your Arduino libraries directory first to avoid any conflicts.

  7. Ralph Doncaster (Nerd Ralph)

    Just tested out your fork; it works fine.
    I made a small change to setup so the pin above and below the onewire bus pin is grounded instead of pins 8 & 10:
    digitalWrite( ONE_WIRE_BUS-1 , LOW );
    pinMode( ONE_WIRE_BUS-1 , OUTPUT );
    digitalWrite( ONE_WIRE_BUS+1 , LOW );
    pinMode( ONE_WIRE_BUS+1 , OUTPUT );

    Technically you don’t even need the digitalWrite lines, since the reset state of all port pins is 0 (low).

  8. Kajetan Schuler

    really cool tutorial. Helped me to set up my DS18b20 without having the 4.7k resistor. I get data but my room is definetely not 80 fahrenheit…is my sensor broken?

      • Kajetan Schuler

        Yes, that works without a problem. I tried it with longer and shorter cables, with parasite power and without. lowest i can get is about 76.5 fahrenheit. After starting, the data shows decreasing values (e.g. it starts at 78.0 and goes down to 76.5 in about 5 minutes) then it stays at 76.5…

        Any idea?

        Best regards!

  9. bigjosh2

    What temp is your room? Is it possible that the reading is correct? Maybe try putting the sensor into a glass of ice water and seeing what reading that produces?

  10. Ainsy


    I’m a total novice to electronics, so most of the detail was well over my head. However, I did know about the concept of internal pull-ups. I got a bunch of temp sensors today and dutifully started to solder on the pins. Then I started to look into how to wire them up. Like I said, I’m a novice … :-) Oh, I was very unimpressed to find I needed an additional resistor. After some rummaging I found said resistor, wired it in, and life was good. Temp sensor stuffed under armpit and voila, 37 degrees. Happy days.

    Then I thought, “hang on, what about the internal pull-up – surely I don’t need that bloody resistor messing up my wiring?” (Mmm, for an explanation of ‘novice’, think deeply about the comment I just made) Anyway I Googled “DS18B20 wiring input_pullup”, and guess who was the first on the list.

    Everything works beautifully. Plus the wiring (for a simple sensor application) is far, far, far, more elegant.

    It has been a pleasure – Well done you!!

  11. Chaz

    Noob question…When using the water-proof probe version, which color wires (black, red, yellow) go to which pins (8, 9, 10)? Since I’m not using the power and ground spots on the board I’m a little lost. Thanks!

    • bigjosh2

      Typically red and black would go to ground, and yellow (or sometimes it is white) to data.

      If you are suing the NoPullupTester sketch on an Arduino Uno, that would translate to white and black wires to Arduino digital pins 8 and 10, and the yellow wire to digital pin 9. Note that the red and white wires could just as easily be attached to any of the Arduino’s “GND” pins as well.

  12. Don Perry Andal

    I really appreciate your work! Exactly what I need!
    These words really hit me:
    “excitedly sat down to build a project with a brand new DS18B20 sensor that they picked up on the way home, only to loose all their momentum when they found out that they need an extra part that they didn’t have”
    Thank you for your time!

  13. Lars

    Can you comment on using 3.3V GPIOs, please? I tried your code with the ESP8266 and it worked on some boards and not on others. And strangely I encountered the situation when the temperatue readings were continously 5 degrees too high.

    • bigjosh2

      The DS18B20 can run off of 3 volts, so as long as the wires are not too long then that should not be a problem. The code in this article, however, is very specific to the AVR processor on Arduino boards, and I would not expect it to work on ESP8266 which uses a completely different processor with different IO pin characteristics. While it would probably be possible to use this technique to have an ESP8266 to drive a DS18B20 with internal pullups, you would likely have to start over and write code specifically for that processor.

    • Michael Ratcliffe

      If your using a NodeMCU [ESP-board], then digital pin D3 already has a pull up on the board that works with the temperature probe. Other breakout boards may have one on a digital pin.

    • bigjosh2

      Did you using the example code and attaching your DS18B20 directly to the Arduino without any wires first to test? If that works, then we can walk though small changes towards your ending setup and see which step makes things break.

      • Elliott

        I am having the same issue. The Serial Monitor is only printing “Parasite:OFF Count:0”. I only have the wired waterproof sensors, so I can’t plug in the sensor directly.

  14. mrkale

    According to my experiments, without external resistor in parasite power mode the bus (library) does not select sensors with activated alarms. In that case I had to use an external pullup resistor to detect the alarms. What about your experience?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s