DS18b20 addressing at runtime

I have found several posts asking this question but did not see any answers.

How do I change out a DS18B20 sensor without having to reprogramming the Arduino Uno with the new device serial number (address)?

Basically I want to be able to scan the network and detect the new sensor and fill in the missing sensor. If more than one sensor is missing, then the lcd and buttons will be used to assign the sensor to the location or purpose. All of the example programs I have found have a global declaration of the location and the address. Such as:

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

#define ONE_WIRE_BUS 3 // Data wire is plugged into pin X on the Arduino

DeviceAddress Temp1 = { 0x28, 0x2A, 0x3A, 0x59, 0x04, 0x00, 0x00, 0x8B };

Does anyone have an example of assigning the address based on a bus scan?

P.S. I do realize that sensors would have to be plugged in one at a time and that's fine.

adwsystems:
P.S. I do realize that sensors would have to be plugged in one at a time and that's fine.

If you have to mess about like that, why not simply adjust the programme.

You don't have to work with addresses.
This also works.

temp1 = sensors.getTempCByIndex(0);
temp2 = sensors.getTempCByIndex(1);
etc.

I think the library is sorting the sensors by address/serial number, so you might have to re-allocate all of them when you insert/add a new one.
Leo..

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

OneWire oneWire(6); // pin D6
DallasTemperature sensors(&oneWire);
float temp1, temp2;

void setup() {
  Serial.begin(115200);
  Serial.println("DS18B20 thermometer");
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures();
  temp1 = sensors.getTempCByIndex(0);
  temp2 = sensors.getTempCByIndex(1);
  
  Serial.print("Temp1 is ");
  Serial.print(temp1, 1); // one decimal places
//Serial.print(temp1, 4); // four decimal places
  Serial.println(" C");
  Serial.print("Temp2 is ");
  Serial.print(temp2, 1);
  Serial.println(" C\n");
}

Wawa:
I think the library is sorting the sensors by address/serial number, so you might have to re-allocate all of them when you insert/add a new one.

Indeed........

Hi,

If you have a table or list of device addresses you could add 1 or 2 "SpareSensor1" entries to your usual list similar to this:

// Assign the addresses of our 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20#Read%20individual

DeviceAddress TemperatureCellarProbe = { 0x28, 0xFF, 0x11, 0x8A, 0x60, 0x14, 0x02, 0xF5 };        // Probe markings C1
DeviceAddress TemperaturePoolProbe = { 0x28, 0xFF, 0x3C, 0x6E, 0x2D, 0x04, 0x00, 0xD7 };          // P1
DeviceAddress TemperatureOutdoorsProbe = { 0x28, 0xFF, 0x87, 0x34, 0x2E, 0x04, 0x00, 0xCF };      // O1  
DeviceAddress TemperatureSoilProbe = { 0x28, 0x05, 0x37, 0x3C, 0x05, 0x00, 0x00, 0x4F };          // NOT ADDRESSED YET
DeviceAddress TemperaturePoolHeaterInProbe = { 0x28, 0xFF, 0x54, 0x88, 0x2C, 0x04, 0x00, 0x13 };  // P2
DeviceAddress TemperaturePoolHeaterOutProbe = { 0x28, 0xFF, 0x9E, 0x34, 0x2E, 0x04, 0x00, 0x40 }; // P3
DeviceAddress TemperatureUpstairsProbe = { 0x28, 0x87, 0xF4, 0xEF, 0x04, 0x00, 0x00, 0x85 };      //  NOT ADDRESSED YET

Then at runtime when you detect a failed sensor you can read SpareSensor1 etc. And of course alert the operator that there is a persistent error.

This may be a solution for "Field Maintenance without coding".

The other classic approach is to have a data structure that is read in at startup time, that is retrieved from EEPROM or over a network, so that reconfiguration is data driven not code driven. That would allow you to replace the sensor with an arbitrary one, not a pre-positioned one.

Let us know what you end up doing...

I think you are are understanding what I'm after. I'm not sure we have a final solution.

terryking228:

// Assign the addresses of our 1-Wire temp sensors.

// See the tutorial on how to obtain these addresses:
// http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20#Read%20individual

DeviceAddress TemperatureCellarProbe = { 0x28, 0xFF, 0x11, 0x8A, 0x60, 0x14, 0x02, 0xF5 };        // Probe markings C1
DeviceAddress TemperaturePoolProbe = { 0x28, 0xFF, 0x3C, 0x6E, 0x2D, 0x04, 0x00, 0xD7 };          // P1
DeviceAddress TemperatureOutdoorsProbe = { 0x28, 0xFF, 0x87, 0x34, 0x2E, 0x04, 0x00, 0xCF };      // O1 
DeviceAddress TemperatureSoilProbe = { 0x28, 0x05, 0x37, 0x3C, 0x05, 0x00, 0x00, 0x4F };          // NOT ADDRESSED YET
DeviceAddress TemperaturePoolHeaterInProbe = { 0x28, 0xFF, 0x54, 0x88, 0x2C, 0x04, 0x00, 0x13 };  // P2
DeviceAddress TemperaturePoolHeaterOutProbe = { 0x28, 0xFF, 0x9E, 0x34, 0x2E, 0x04, 0x00, 0x40 }; // P3
DeviceAddress TemperatureUpstairsProbe = { 0x28, 0x87, 0xF4, 0xEF, 0x04, 0x00, 0x00, 0x85 };      //  NOT ADDRESSED YET





Then at runtime when you detect a failed sensor you can read SpareSensor1 etc. And of course alert the operator that there is a persistent error.

This may be a solution for "Field Maintenance without coding". 

The other classic approach is to have a data structure that is read in at startup time, that is retrieved from EEPROM or over a network, so that reconfiguration is data driven not code driven. That would allow you to replace the sensor with an arbitrary one, not a pre-positioned one.

Why mix pre-assigned addressing with SpareSensor? Someone still has to make the assignment of spare sensor to location. Seems like double work.

Nick_Pyner:
If you have to mess about like that, why not simply adjust the programme.

I am anticipating a few dozen Arduino boards but each only with 3-6 sensors. I think it would be easier to manage one general program and assign the sensors in the field than manage dozens of programs (more than dozens of sensor adresses).

Wawa:
You don't have to work with addresses.
This also works.

temp1 = sensors.getTempCByIndex(0);
temp2 = sensors.getTempCByIndex(1);
etc.

I think the library is sorting the sensors by address/serial number, so you might have to re-allocate all of them when you insert/add a new one.
Leo..

#include <DallasTemperature.h>

#include <OneWire.h>

OneWire oneWire(6); // pin D6
DallasTemperature sensors(&oneWire);
float temp1, temp2;

void setup() {
  Serial.begin(115200);
  Serial.println("DS18B20 thermometer");
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures();
  temp1 = sensors.getTempCByIndex(0);
  temp2 = sensors.getTempCByIndex(1);
 
  Serial.print("Temp1 is ");
  Serial.print(temp1, 1); // one decimal places
//Serial.print(temp1, 4); // four decimal places
  Serial.println(" C");
  Serial.print("Temp2 is ");
  Serial.print(temp2, 1);
  Serial.println(" C\n");
}

I will have to look into this method. Thanks for the warning.

I had a related question and was about to start a new thread, but I think it might have been answered here.

From what I read above, the OneWire address search function returns the serial numbers of devices it finds in a simple alphanumeric order? And from there, if you address Device 0, it will be the first serial in the alphanumeric list, Device 1 will be the second serial in the list, etc.?

I'd been hoping beyond hope that the one-wire protocol provided some magical means of identifying devices by physical location on the bus (or similar). :confused:

See my message #3 in The best way to get multiple DS18B20 Data - Sensors - Arduino Forum and follow the links.
It explains how the software identifies multiple DS18B20 on a bus.

Pete

pamies:
I'd been hoping beyond hope that the one-wire protocol provided some magical means of identifying devices by physical location on the bus (or similar).

No magic. I think the real answer is that, if you don't want to worry about addresses and location, use a different sensor - one that doesn't use the One-wire system. In the meantime, the DS18B20 is very reliable and I bet the main reason for replacing them is as a result of actual abuse, and the obvious way of using them is with the code in the original post.

QUOTE:

I think it would be easier to manage one general program and assign the sensors in the field than manage dozens of programs (more than dozens of sensor addresses).

You could have sensor addresses in EEPROM, and copy them in to the standard sketch at initialization time.

Every application sketch could be the same.

To reassign addresses (or replace a sensor) you can run a separate sketch that loads the EEPROM in an individual station with it's sensor addresses. Then reload the Standard Sketch every station uses.

A little more complex is adding function to the standard station sketch to communicate over Serial and accept a message that updates the EEPROM sensor addresses.

You should be able to solve this using the library functions and the EEPROM. Keep an array of DS18B20 addresses in RAM which you populate from EEPROM. Decide which function each element of the array is dedicated to e.g. address[2] is the BoilerSensor. When your sketch needs the boiler temperature, use getTempC to get it, passing address[2] as the parameter.

At startup, or on user request, Enumerate the addresses on the bus. For each one, look for it in your array. If it is not there, ask the user which array element it should overwrite. When you're done, if you made any changes, write to EEPROM.

The beauty of this is that you can bootstrap a new device simply by plugging sensors in one at a time and running the detection routine for each one.

Be careful that you don't mix up the array indexes with the index used in GetTempCByIndex - they are most unlikely to be the same.

As I am working through this, the first thing that occurred to be is the global DeviceAddress declaration is nothing more than assigning eight values into a uint_8 array. Skipping the assignment in the global declaration and doing this at startup provides the first step in becoming dynamic. Finding the address(es) and making the assignment(s) will be the next step. Final step will be storing and loading the assigned address(es).

Step 1, done. On to step 2.

This shouldn't be complicated conceptually:

In EEPROM you have a list of sensor ids.

At startup read the bus. Compare the list for differences. If there is no difference, fine
If there is one id missing and one new id, replace the old one in the list (in EEPROM), continue.

Any other kind of difference, giveup and flash an LED or something to say "I've got a problem"

So you need code to compare lists for differences, as if they are sets (ie order doesn't matter).

There might even be a library for that.

Hello All,

TL;DR
You can use a separate GPIO's to switch a transistor that will switch the GND pin of the DS18B20 effectively turning each sensor on one at a time and reading its address. then assign it to a physical location in software. This should be a part of your setup method. This would prevent you from adding time to your loop reading from individual bus's. This eats up a lot of GPIO's so you can simply use a GPIO expansion such as the MCP23017 to accomplish the same.

This is a hardware/software hybrid solution. It requires a mixture of both in order to achieve desired results.

Parts Required:

  • Arduino of choice (mine was not an arduino but an esp8266)
  • Multiple DS18B20's
  • A MCP23017 GPIO expansion chip
  • Same number of transistors as sensors (2n 2222a)
  • Same number of resistors as transistors (43k)

With the popularity of the DS18B20's still growing, I wanted to offer an answer that may better answer this question. The software methods above are decent and should be considered if it can solve your needs. You could just use separate GPIO pins for each sensor which would take forever to read causing your loop to be extremely inefficient, IF you have enough pins available. I battled this issue for a couple of days and read through Stack posts as well as Arduino forum posts and all affirmed the same things:

  • You cannot get physical location of any 1wire device because, electrically they are not in a different location.
  • The enumeration process in the Dallas Sensor library orders by value.
  • There are software ways to handle this with intervention by manually (or with an output) changing the temp of the probe.
  • Multiplexing is an option, but possibly overkill and could lead to more complex code.
  • GPIO expansions such as the MCP23017 or similar cannot reliably read the sensors and reading requires heavy software modification.
  • Other sensors (such as DS28EA00) are able to be chained and a sequence detection function used to get physical location in the chain. But, if a member of the chain fails the following members will be unreachable (like xmas lights).

The last of the above seemed like a winner, but the fact that the links depended on preceding links (without bypassing) was not acceptable for my application. Furthermore, there are not many readily available probes on the market with this chip.

I started mauling it over and insisted using the MCP23017 when it hit me... I don't need to read the sensor through it.. I just need to switch power to the sensors individually, effectively turning them on one by one and assigning them a physical location in software. A simple loop can take care of this.

This failed on my first attempt because driving the power pin LOW of the DS18B20 would Cause the rest of the sensors to also go low. I didn't go into great detail on why this happened, but I knew something had to change. But, when the power/ground pin of a sensor was floating, the rest of the sensors were unaffected.

So, I decided to tie the power pin to the supply, data pin to the 1wire pin, and use the MCP23017 to activate a transistor (acting as a switch) to switch the ground pin of the DS18B20. At that point I had accomplished what I set out to do. Read from a specific sensor to provide feedback for proportional control of a heat source. Or, ,to simply know the physical location of the sensor I was reading from so i could use it.

For those of you who are as excited as I was when I first got it working, and who may not have an idea how to get started... I have some useful information below, the rest of you are welcome...

I have no real idea if this information will be found useful, or if its just me, so I am not wasting time with diagrams or software examples right now. In essence, you switch each pin of the MCP23017 where you connected the transistor and sensor and assign it a location in software.

Things you will need:

  • Arduino of choice (mine was not an arduino but an esp8266)
  • Multiple DS18B20's
  • A MCP23017 GPIO expansion chip
  • Same number of transistors as sensors
  • Same number of resistors as transistors

Well, how do you choose a transistor you might ask... That is extremely complicated to really explain to someone who isn't an EE, so here is what I used and how you can determine what you should use.

Transistors I used are 2n 2222a's
Resistors I used are 43k @ 1%

NOTE: Without a resistor, if the current inst regulated, you will destroy your transistor. You Should generally always include one anyways even if the current is limited.

DISCLAIMER: I am not an EE, so don't freakin bash me semantics. Politely correct me and have me edit the post.. thanks

When choosing a transistor for switching you will likely use an NPN type. You need to choose one with a decently high minimum current gain (hfe). The higher the minimum current gain the less current you will need to switch the base junction and allow current to flow from the collector to the emitter. In my opinion 100 to 400 hfe is sufficient. You will need to gather the following info to then calculate the resistor:

  • The max current of the load you will be switching. DS18B20's are 1.5a
  • The max current gain of the transistor you are looking to use.
  • Voltage that will be supplied to the base pin of the transistor.

Then you need to make the following calculations:

  • Determine the current needed on the base to allow the amount of current required for your load to flow from collector to emitter. (loadCurrent / hfe) In my case it is 1.5ma / 100 = .015ma.
  • Give yourself some wiggle room.. I chose to round up to .02ma.
  • Determine the resistance needed. (voltage - drop across PN gate) / amps required to switch = resistance. In most transistors the voltage drop is .7v which i suppose is the magic number. Also, convert your miliamps to amps. In my case it is (5v - .7v) / .00002a = 215,000ohms

Now, that is a pretty heft resistor in my case, so I wanted to make a bit of an adjustment. The GPIO pins of my device can handle 12ma so, even if somehow I drew that much from maybe an external supply, I would be safe bumping up the current gain a bit. I worked backwards to get smaller and cheaper resistor of 43k.

10ma / 100hfe = .1ma = .0001a
(5v - .7v) / .0001a = 43,000ohms

This will allow me to supply 5v through the 43k resistor at .1ma to the base pin of the NPN transistor which in turn, allows up to 10ma of power to flow from the collector pin to the emitter pin.

This transistor setup will work for all sorts of stuff (as long as it draws less than 10ma) for my device. LED's, Sensors, small peripherals. The only thing I can note here is, if you intend on using it with a solenoid or other conductor (coil), you will need to place a "flyback diode" around the coil to avoid high voltage spikes that will destroy the transistor when the EMF collapses.

Hope this helps somebody out on a few different levels! And if anyone wants a wiring diagram or would like me to expand on this, feel free to ask.

SIDEBAR: I am a bit disgusted at a lot of the responses I see to members of this forum, and it has discouraged me from actually posting questions. I see posts that are a bit malformed or incorrect, where members (Brattain included) will be so condescending using snark remarks and very short answers with little to no value. I run a couple of forums, I get it. But, when your demographic is driven towards enthusiasts and the questions are NOT coming from EE's, why is there a lack of willingness to provide actual help. Why are responses like "Why are you trying to do it this way, that's not right, you should be using this verbiage instead of that word, blah, blah, blah" even allowed?

I can understand there is a need to correct someone who misunderstands a concept, or lead them in the right direction by having them rethink their approach, but some comments just blow my mind. And a lot of times it is simply preference. There are also wild claims that are blatantly incorrect, sometimes telling people that something cannot be done and it really can if it is just thought about differently. (maybe such as this post) This forum should promote creativity, not destroy it. END RANT

cheers

1 Like

There's no reason a DS18B20 would ever fail if wired correctly with decoupling capacitor and proper one-wire bus setup. I've never seen it happen over years of continuous use with many of them.

However if you have counterfeit DS18B20's all bets are off.

m4k3r:
You can use a separate GPIO's to switch a transistor that will switch the GND pin of the DS18B20 effectively turning each sensor on one at a time and reading its address. then assign it to a physical location in software. This should be a part of your setup method...

This pulls the data pin of the swiched-off sensors below their grounds,
likely more than the 0.3volt specified in the datasheet.
Don't be surprised if they eventually fail.
Maybe safer to switch the data lines with a muxer.
Leo..