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?
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 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.
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.
// 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() {}
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
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);
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.