Can keep multi DS18b20 in sequence after replace one?

I am reading temperature from 8 DS18b20 sensors by one wire bus, and I can get all reading very well without any problem.

I also record the address of each one to keep them running in the correct sequence. When I replaced one of them due to damage, the whole sequence was changed, and I had to rewrite the code and re-upload it. Is there any way the sequence, despite changing the code or using individual GPIO for each wire?

1 Like

Your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with (nor for advice on) your project :wink: See About the Installation & Troubleshooting category.

It would appear that you are using the "by index" method, but you still have to edit the programme if you get the data by address. I think the only way out is to have a large stockpile of spares and a lot of luck, thereby enabling you to put a replacement in in the proper sequence.

Or use a different Arduino pin for each sensor.
Leo..

You can store the sensor addresses in EEPROM, in the order they are physically situated. At startup, check all the addresses are reachable, also check for any new ones. If one is gone and a new one has appeared, that's a simple fix.

If several are gone though, you would need a more fancy interface for the user to indicate which is which.

1 Like

I wrote a sketch to do this back in October:

// RULES:
// Re-start the sketch each time you add or remove a single device.

#include <EEPROM.h>
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

const uint16_t MaxCount = 20; // Allow room for 20 heaters
struct
{
  uint16_t activeCount;
  uint16_t inactiveCount;
  bool isActive[MaxCount];
  DeviceAddress address[MaxCount];
} AddressList;
uint16_t FullCount;

// function to print a device address
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);
  }
}

// Find this Deviceddress in the active list
int GetPositionIndexByAddress(DeviceAddress address)
{
  for (uint16_t i = 0; i < FullCount; i++)
  {
    if (AddressList.isActive[i] && AddressList.address[i] == address)
      return i;
  }
  return -1;
}

void DumpAddressList()
{
  Serial.println("AddressList");

  Serial.print("AddressList.activeCount = ");
  Serial.println(AddressList.activeCount);

  Serial.print("AddressList.inactiveCount = ");
  Serial.println(AddressList.inactiveCount);

  Serial.print("FullCount = ");
  Serial.println(FullCount);

  for (uint16_t i = 0; i < FullCount; i++)
  {
    Serial.print("PositionIndex: ");
    Serial.print(i);
    if (AddressList.isActive[i])
      Serial.print("    Active: ");
    else
      Serial.print("  Inactive: ");
    printAddress(AddressList.address[i]);
    Serial.println();
  }
}

void setup()
{
  Serial.begin(115200);
  delay(200);

  EEPROM.get(0, AddressList);

  FullCount = AddressList.activeCount + AddressList.inactiveCount;

  // Check for a valid count
  if (FullCount > MaxCount)
  {
    // Bad count.  Reset the array
    Serial.print("Bad counts: active=");
    Serial.print(AddressList.activeCount);
    Serial.print(" inactive=");
    Serial.print(AddressList.inactiveCount);
    Serial.print(" MaxCount=");
    Serial.println(MaxCount);
    AddressList.activeCount = 0;
    AddressList.inactiveCount = 0;
    FullCount = 0;
  }

  DumpAddressList();

  // Start up the DallasTemperature library
  sensors.begin();

  // Find the number of devices on the bus.
  uint16_t newActiveCount = sensors.getDeviceCount();

  // Check for valid counts
  // Are we removing one device?
  if (newActiveCount == AddressList.activeCount - 1 &&
      AddressList.inactiveCount == 0) // Removed one device
  {
    // Removed one device. Find it and mark it as 'inactive'
    for (uint16_t index = 0; index < FullCount; index++)
    {
      if (AddressList.isActive[index])
      {
        float tempC = sensors.getTempC(AddressList.address[index]);
        if (tempC == DEVICE_DISCONNECTED_C)
        {
          AddressList.isActive[index] = false;
          AddressList.inactiveCount++;
          AddressList.activeCount--;
          EEPROM.put(0, AddressList);
          DumpAddressList();
        }
      }
    }
  } // End: Removing one device
  else // Are we adding one device?
    if (newActiveCount == AddressList.activeCount + 1 &&
        AddressList.inactiveCount <= 1)
    {
      // Adding one device.  Find the one that isn't already active

      // Test each of the currently active addresses to see if they are
      // already in the active list
      for (uint16_t bussIndex = 0; bussIndex < newActiveCount; bussIndex++)
      {
        DeviceAddress address;

        if (!sensors.getAddress(address, bussIndex))
        {
          Serial.print("Error: Failed to get address at bussIndex ");
          Serial.println(bussIndex);
          while (1) {}
        }

        int positionIndex = GetPositionIndexByAddress(address);
        if (positionIndex == -1) // Not found in active list
        {
          // Found the address that is newly active.

          if (AddressList.inactiveCount == 0)
          {
            // We have no inactive entry so put the new address at the end of the list
            memcpy (AddressList.address[FullCount], address, sizeof address);
            AddressList.isActive[FullCount] = true;
            AddressList.activeCount++;
            FullCount++;
            EEPROM.put(0, AddressList);
            DumpAddressList();
          }
          else
          {
            // Find a place to put it in the list
            for (uint16_t positionIndex = 0; positionIndex < FullCount; positionIndex++)
            {
              if (!AddressList.isActive[positionIndex])
              {
                // Found the inactive entry
                AddressList.inactiveCount--;

                memcpy (AddressList.address[FullCount], address, sizeof address);
                AddressList.isActive[positionIndex] = true;
                AddressList.activeCount++;
                EEPROM.put(0, AddressList);
                DumpAddressList();
              }
            }
          }
        }
      }
    } // End of adding one device
    else if (newActiveCount == AddressList.activeCount)
    {
      Serial.println("Number of active addresses unchanged.");
      DumpAddressList();
    }
    else
    {
      // Something is wrong!
      Serial.println("Something went wrong.  Either more than one device has");
      Serial.println("been removed or more than one device has been added.");
      DumpAddressList();
      while (1) {}
    }


  // Now you have a list of addresses in order of position

  // Tell each active address to set resolution
  for (uint16_t i = 0; i < FullCount; i++)
  {
    if (AddressList.isActive[i])
      sensors.setResolution(AddressList.address[i], TEMPERATURE_PRECISION);
  }

} // End: setup()


void loop() {}
1 Like

Why do you think they will fail.
When used properly they shouldn't fail.
For starters, don't believe the "waterproof" claim.
Leo..

Thank you so much @johnwasser. That was helpful. In case one of these sensors got damaged and needs to be replaced with a new one, will that make any difference?

The addresses are kept in the order that they are originally added. If a sensor dies it is marked as inactive and the next sensor to be added will take its place.

Thank you @johnwasser, for your help. I tried your sketch, but I couldn't fully understand it. It works for only one sensor on the bus. if I add more than one, I get below in serial
I fully reset the EEPROM to ensure nothing was saved from the previous project, just in case, following your conversation in
https://forum.arduino.cc/t/dallas-temperature-how-to-use-the-method-2-search/1039794/2

Your advice, please.

........................................................................................

AddressList

AddressList.activeCount = 0

AddressList.inactiveCount = 0

FullCount = 0

Something went wrong. Either more than one device has

been removed or more than one device has been added.

AddressList

AddressList.activeCount = 0

AddressList.inactiveCount = 0

FullCount = 0

Did you reset the Arduino after adding EACH sensor? Remember the rule:

1 Like

Thank you, @johnwasser, for your reply. Yes, I did and if one sensor is only on the bus, I get

AddressList
AddressList.activeCount = 0
AddressList.inactiveCount = 0
FullCount = 0
AddressList
AddressList.activeCount = 1
AddressList.inactiveCount = 0
FullCount = 1
PositionIndex: 0 Active: 28504FB3122201A4
...........................................................................
If I add one more and reset the ESP32, I get

AddressList
AddressList.activeCount = 0
AddressList.inactiveCount = 0
FullCount = 0
Something went wrong. Either more than one device has
been removed or more than one device has been added.
AddressList
AddressList.activeCount = 0
AddressList.inactiveCount = 0
FullCount = 0
.............................
Does ESP32 make any difference if it is used instead of an Arduino board?

I think it might. ESP32 doesn't have real EEPROM and emulates it with FLASH. You have to call "EEPROM.commit();" to write the emulated EEPROM to FLASH. Add that after all three cases of:
EEPROM.put(0, AddressList);

1 Like

Thank you @johnwasser, and happy new year. It did not work for me for ESP32. I will try to upload the sketch to an Arduino board to see it. I will just read the address manually and sort them out by address. If any change or swap, I will have to edit the sketch and re-upload it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.