DS18B20 - getTempbyID() - an alternative use for the alarm field

Last weeks I created 2 examples for the Dallas Temperature Library to solve a known problem when using multiple DS18B20 on a single onewire bus and one needs to replace one sensor.

Problem description
The problem is that if you have multple sensors on a onewire bus and one failes you need to code the new address in your code or worse, redo the search and order of the sensors, or find one that pops on the same place when the device search is done

Solution
By using the seldom used Alarm field as userdata one can write an unique ID to every DS18B20. By filling a table during setup one can map this ID on the address used. If now a DS18B20 is broken, one only needs to replace it with one with the same ID and the sketch itself does not need to be modified.

Note: if you use the alarm field this trick won't work.

The sketches
UserDataWriteBatch.ino - assigns the same ID to all DS18B20 on the onewire bus. This way you can "label" a single DS18B20 or mass produce many with the same "ID". This sketch is needed to prepare DS18B20 for the other demo sketch.

UserDataDemo.ino - implements getTempByID(int ID) function.
This function uses a lookup table that maps individual addresses to ID's. This lookup table is initialized during setup. One should take care that every DS18B20 used has an unique ID. This example needs 4 prepared DS18B20's but it show the working with only one (the others will fail but its just a demo)

Where to find
A PR is made to have these sketches in the official repository

but I'll add them here for those who cannot wait :slight_smile:

//
// FILE: UserDataWriteBatch.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: use of alarm field as user identification demo
// DATE: 2019-12-23
// URL:
//
// Released to the public domain
//

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

#define ONE_WIRE_BUS      2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

uint8_t deviceCount = 0;

void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}



void setup(void)
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.println("Write user ID to DS18B20\n");

  sensors.begin();

  // count devices
  deviceCount = sensors.getDeviceCount();
  Serial.print("#devices: ");
  Serial.println(deviceCount);
  
  Serial.println();
  Serial.println("current ID's");
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    DeviceAddress t;
    sensors.getAddress(t, index);
    printAddress(t);
    Serial.print("\t\tID: ");
    int id = sensors.getUserData(t);
    Serial.println(id);
  }
  
  Serial.println();
  Serial.print("Enter ID for batch: ");
  int c = 0;
  int id = 0;
  while (c != '\n' && c != '\r')
  {
    c = Serial.read();
    switch(c)
    {
    case '0'...'9':
      id *= 10;
      id += (c - '0');
      break;
    default:
      break;
    }
  }
  Serial.println();
  Serial.println(id);
  Serial.println();

  Serial.println("Start labeling ...");
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    Serial.print(".");
    DeviceAddress t;
    sensors.getAddress(t, index);
    sensors.setUserData(t, id);
  }
  Serial.println();

  Serial.println();
  Serial.println("Show results ...");
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    DeviceAddress t;
    sensors.getAddress(t, index);
    printAddress(t);
    Serial.print("\t\tID: ");
    int id = sensors.getUserData(t);
    Serial.println(id);
  }
  Serial.println("Done ...");

}

void loop(void) {}

// END OF FILE
//
// FILE: UserDataDemo.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: use of alarm field as user identification demo
// DATE: 2019-12-23
// URL:
//
// Released to the public domain
//

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

#define ONE_WIRE_BUS      2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

uint8_t deviceCount = 0;

// Add 4 prepared sensors to the bus
// use the UserDataWriteBatch demo to prepare 4 different labeled sensors
struct
{
  int id;
  DeviceAddress addr;
} T[4];

float getTempByID(int id)
{
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    if (T[index].id == id)
    {
      return sensors.getTempC(T[index].addr);
    }
  }
  return -999;
}

void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

void setup(void)
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.println("Dallas Temperature Demo");

  sensors.begin();
  
  // count devices
  deviceCount = sensors.getDeviceCount();
  Serial.print("#devices: ");
  Serial.println(deviceCount);

  // Read ID's per sensor
  // and put them in T array
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    // go through sensors
    sensors.getAddress(T[index].addr, index);
    T[index].id = sensors.getUserData(T[index].addr);
  }

  // Check all 4 sensors are set
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    Serial.println();
    Serial.println(T[index].id);
    printAddress(T[index].addr);
    Serial.println();
  }
  Serial.println();

}


void loop(void)
{
  Serial.println();
  Serial.print(millis());
  Serial.println("\treq temp");
  sensors.requestTemperatures();

  Serial.print(millis());
  Serial.println("\tGet temp by address");
  for (int i = 0; i < 4; i++)
  {
    Serial.print(millis());
    Serial.print("\t temp:\t");
    Serial.println(sensors.getTempC(T[i].addr));
  }

  Serial.print(millis());
  Serial.println("\tGet temp by ID");  // assume ID = 0, 1, 2, 3
  for (int id = 0; id < 4; id++)
  {
    Serial.print(millis());
    Serial.print("\t temp:\t");
    Serial.println(getTempByID(id));
  }

  delay(1000);
}

// END OF FILE

As always remarks and comments are welcome

Nice.

you mi friend just made my day! I have a large sensor array (40 to 60 per chain) heading off down to Antarctica and after soldering the chain realised I had messed up the order. initially I was going to create a table however this will make it so much easier to give the sensors an ID that is in logical order :slight_smile:

a great solution, thanks for sharing