He could put it in a structure and then simple assignment works by copying the elements. How consistent and sensible is that when compare to the rest of language regarding assignment? I can see the OP's point, I use many languages and the only consistent thing is that they aren't consistent in the syntax or order of evaluation rules.
I'm trying to do the same thing. Did you ever get this to work?
This thread is very old, and one of the dumbest ones as well. If you want get a start on using the DS18B20, there are better places to come to.
There is more than one way to use the sensor, and they are well-documented. The source I started with is here.
The nonsense problem above is not really a problem at all. You simply identify a sensor by its internal address, and assign a plain-english name to it that Arduino prints. Printing the address on the LCD is just silly, and involves using code you don't otherwise need. Because of the one-wire system, you DO need to know which sensor is which. Coloured heatshrink, or sticky labels, work wonders here.
Welcome to this forum.
I don't care how old this post is, it is not relevant to solving the problem at hand. Namely handling multiple DS1820B devices dynamically.
I figured out how to do this, one issue is that I run out of memory if using more than about 18 devices.
Key parts are here, not sure if it compiles:
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(6);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device addresses
DeviceAddress probes[20];
void setup(void)
{
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
sensors.setResolution(12);
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
// Search for devices on the bus and assign based on an index. Ideally,
// you would do this to initially discover addresses on the bus and then
// use those addresses and manually assign them (see above) once you know
// the devices on your bus (and assuming they don't change).
//
// method 1: by index
for(int i = 0 ; i < 20; i++){
if (!sensors.getAddress(probes[i], i)) Serial.println("Unable to find address for Device 0");
// show the addresses we found on the bus
Serial.print("Device Address: ");
printAddress(probes[i]);
Serial.println();
// set the resolution to 12 bit per device
sensors.setResolution(probes[i], 12);
Serial.print("Device ");
Serial.print(i+1);
Serial.print(" Resolution: ");
int res = sensors.getResolution(probes[i]);
if(res == 0){
shutdown();
}
Serial.print(res, DEC);
Serial.println();
}
}
void loop(void){
for(int i = 0 ; i < 20; i++){
Serial.println(sensors.getTempC(probes[i]));
Serial.println(saveAddress(probes[i]));
//logAddress(probes[i], &logFile);
//printAddress(probes[i]);
//delay(50);
}
}
// function to display address to Serial Monitor
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);
}
}
/* function to save a device address as a string*/
String saveAddress(DeviceAddress deviceAddress)
{
String address = "";
for (uint8_t i = 0; i < 8; i++) {
// zero pad the address if necessary
if (deviceAddress[i] < 16)
address += 0;
address += String(deviceAddress[i],HEX);
}
return address;
} //end print address function
//// function to log to SD Card a device address
//pass it the device address and a pointer to a log file
void logAddress(DeviceAddress deviceAddress, File* logfile)
{
for (uint8_t i = 0; i < 8; i++) {
// zero pad the address if necessary
if (deviceAddress[i] < 16)
(*logfile).print("0");
logfile->print(deviceAddress[i], HEX);
}
}
Here is the actual sketch where the above ideas were used, I have an ADS1115, a DS1307, and a microSD card module.
Feel free to make serious suggestions on how it could be improved. If anyone has a way to handle out of memory errors specifically with the DeviceAddress array please let me know. If a temporary file can be put on the SD card to hold the addresses that would be awesome.
Anyways here is the sketch I used to calibrate multiple DS1820B's to a reference NTC 10K thermister.
//NEG (-) ----- 10K -----A0 + thermister --- VCC
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_ADS1015.h>
#include <SPI.h>
#include <SD.h>
#include <math.h>
#include <RTClib.h>
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
Adafruit_ADS1115 ads(0x48);
boolean firstRun = true;
float Steinhart_Hart(float Vi, float Vo) {
float R1 = 10000;
float logR2, R2, T, Tc, Tf;
float c1 = 1.127374020e-03, c2 = 2.343869593e-04, c3 = 0.8685178645e-07;
R2 = (float)R1 * ((float)Vi / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
return(T - 273.15f);
}
float averageAnalog(char pin, int numRead)
{
float total = 0;
for(int i=0; i<numRead; i++){
total = total + ads.readADC_SingleEnded(pin);
delay(10);
}
delay(50);
return ((float)total/(float)numRead);
}
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(6);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device addresses
DeviceAddress probes[20];
void shutdown()
{
// optionally do stop motors dim the LED's etc.
Serial.print("stopped"); // or other warning
while(1);
}
void setup(void)
{
ads.setGain(GAIN_TWOTHIRDS);
ads.begin();
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
sensors.setResolution(12);
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
// Search for devices on the bus and assign based on an index. Ideally,
// you would do this to initially discover addresses on the bus and then
// use those addresses and manually assign them (see above) once you know
// the devices on your bus (and assuming they don't change).
//
// method 1: by index
for(int i = 0 ; i < 20; i++){
if (!sensors.getAddress(probes[i], i)) Serial.println("Unable to find address for Device 0");
// show the addresses we found on the bus
Serial.print("Device Address: ");
printAddress(probes[i]);
Serial.println();
// set the resolution to 12 bit per device
sensors.setResolution(probes[i], 12);
Serial.print("Device ");
Serial.print(i+1);
Serial.print(" Resolution: ");
int res = sensors.getResolution(probes[i]);
if(res == 0){
shutdown();
}
Serial.print(res, DEC);
Serial.println();
}
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
// --- rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time
// rtc.adjust(DateTime(2016, 4, 20, 15, 58, 00));
}
//sd
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(10)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
}
// 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);
}
}
//// function to print a device address
void logAddress(DeviceAddress deviceAddress, File* logfile)
{
for (uint8_t i = 0; i < 8; i++) {
// zero pad the address if necessary
if (deviceAddress[i] < 16)
(*logfile).print("0");
logfile->print(deviceAddress[i], HEX);
}
}
/*
* Main function, calls the temperatures in a loop.
*/
//float voltage = 0;
float old_ref = 0;
void loop(void)
{
DateTime now = rtc.now();
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures();
Serial.println("DONE");
float T_dig = 0;
//See when logFile is open
Serial.println("Open");
// digitalWrite(LED_BUILTIN, HIGH);
File logFile = SD.open("DS18B.CSV", FILE_WRITE);
if (logFile) {
if (firstRun) {
firstRun = false;
logFile.print("Date");
logFile.print(',');
logFile.print("Time");
logFile.print(',');
logFile.print("Vo");
logFile.print(',');
logFile.print("Vi");
logFile.print(',');
logFile.print("Address");
logFile.print(',');
logFile.print("T_dig");
logFile.print(',');
logFile.print("T_Aref");
logFile.print(',');
logFile.println("T_Change");
}
float Vi = averageAnalog(1, 64);;
float Vo = averageAnalog(0, 64);;
float T_Aref = Steinhart_Hart(Vi, Vo);
for(int i = 0 ; i < 20; i++){ //The loop that goes through the sensors
T_dig = sensors.getTempC(probes[i]);
logFile.print(now.year(), DEC);
logFile.print('/');
logFile.print(now.month(), DEC);
logFile.print('/');
logFile.print(now.day(), DEC);
logFile.print(',');
logFile.print(now.hour(), DEC);
logFile.print(':');
logFile.print(now.minute(), DEC);
logFile.print(':');
logFile.print(now.second(), DEC);
logFile.print(',');
logFile.print(Vo);
logFile.print(',');
logFile.print(Vi);
logFile.print(',');
logAddress(probes[i], &logFile); //weird way before I figured out how to use Strings
logFile.print(',');
logFile.print(T_dig,4);
logFile.print(',');
logFile.print(T_Aref);
logFile.print(',');
logFile.println(T_Aref-old_ref,4);
printAddress(probes[i]);
Serial.print(": ");
Serial.print(T_dig, 4);
Serial.println(" C");
Serial.print("T_ref: ");
Serial.print(T_Aref,4);
Serial.print(" C. Change: ");
Serial.println(T_Aref-old_ref,4);
Serial.print("Thermister: ");
Serial.print("Vo: ");
Serial.print(Vo);
Serial.print(',');
Serial.print("Vi: ");
Serial.println(Vi);
delay(50); //some random probably unnecessary delay
}
old_ref = T_Aref;
delay(1000); //delay to allow printing to Serial Monitor to complete
logFile.close();
}
Serial.println("Close");
digitalWrite(LED_BUILTIN, LOW);
delay(2000);
}
I come to this rather late in the day after wasting time on TMP36s
I have been trying to do similar with finding addresses on the fly, and averaging the temperature readings, but the max no of DS18B20s I found I could address with one 4.7K resistor between data and Vcc on a Nano is four.
I just post this as others suggest higher numbers.
freddie43:
others suggest higher numbers.
I don't think it's a suggestion, it's a certainty. If a Nano was limited to four sensors, I believe it would be common knowledge by now.
I'm sure the standard address finder from Hacktronics will do several on the fly. Since you are averaging several, I don't see why you need to do this anyway, and I think the procedure by index would suffice. Indeed, while I have never used it myself, I think this is the only time when working by index is probably a good idea. An example is included in the DallasTemperature library.
Actually I was wrong about the four. I can only get proper readings with three.
Why am I doing this? I was surprised at the rather large difference in readings from the sensors, and I wanted to run six together to compare them 'live', but the most I have managed really is three.
I haven't studied all the code in the texts above, but I find that using getDeviceCount() is very effective for dealing with a variable number of sensors when you are swapping them in and out and pressing reset to start again.
I submit your problem can only be explained by
Wiring
inadequate power
user abuse
misunderstanding
Your code is apparently a secret, and your real objective unclear but, if you can get one sensor to give a proper result, there might be nothing wrong with it, and you might look there last.
What I use is at http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html\
I use it because I want to know which sensor is saying what, and where it is.
Why are you always so negative?
Ottehoman sums you up quite well.
Have you ever thought it might be you who has the misunderstandings?
I've just wired up 7 DS18B20s on a Nano with a 4.7k pullup on the data pins. The onewire scanner sketch sees them all.
- do you have them wired in parasite mode?
- how long are the wires to each sensor?
Try 3.3k with the 6 sensors.
Pete
freddie43:
Why are you always so negative?Ottehoman sums you up quite well.
Have you ever thought it might be you who has the misunderstandings?
No, and Ottehoman was clearly an idiot. Any misunderstanding on my part is solely due to the lack of information on your part - no code, no wiring, no proper explanation of intent, just a comment that amounts to nonsense. That aside, you might give some though as to why you have a problem connecting four DS18B20s to an Arduino, and nobody else has. Some misunderstanding on your part may go quite some way to explain this, and it might be more constructive to ignore the ancient stuff anyway. So, for further clarification on wiring, read reply #30, again. The first sentence says it all - rather like the first par in reply #26
Thank you el_supremo. That is encouraging. I will try your resistor suggestion.
As this is just a calibration experiment my sensors are wired in parallel in adjacent holes adjacent to the Nano all on the same breadboard in two lines of three all joined by the shortest of patch wires. The three sensors work in any combination of the six positions, but adding a fourth or more messes it up.
I wondered what range of temperatures your seven sensors display and what sort of drift you get?
Thanks again for your helpful reply.
As you have problem in the simultaneous operation of 7xDS18B20 sensors, it is the time to isolate the problem for which I would suggest to follow linear and sequential strategy to collect the addresses, start conversions, compute temperatures of the sensors. When the sensors are found working, proceed to optimize the codes using loop, subroutine, and 2-dimensional array. Uses OneWire.h Library only.
Tested for 2xDS18B20 using NANO
//12-bit default resolution; external power supply
#include<OneWire.h>
OneWire ds(10); //Signal in is DPin-10.
//--declare arrays to hold addresses of the sensors
byte ds1Add[8]; //to hold 64-bit ROM Codes/Address of DS1
//-------------
byte ds7Add[8];
//--declare arrays to hold scratchpad (Temp) data of the sensors
byte ds1Temp[9];
//-------------
byte ds7Temp[9];
float dsTempC;
void setup()
{
Serial.begin(9600);
//--reset all addresses at the same time----
ds.reset();
//-collect addresses of the sensors----
ds.search(ds1Add);
//----------------
ds.search(ds7Add);
}
void loop()
{
DST(ds1Add, ds1Temp);
Serial.print("DS1 Temp in deg C = "); Serial.println(dsTempC);
//--------
DST(ds7Add, ds7Temp);
Serial.print("DS7 Temp in deg C = "); Serial.println(dsTempC);
Serial.println();
}
void DST(byte *dsAdd, byte *dsTemp)
{
//--start conversion, wait for conversion, and acquire data --
ds.reset();
ds.select(dsAdd);
ds.write(0x44);
delay(1000);
//-----------
ds.reset();
ds.select(dsAdd);
ds.write(0xBE);
ds.read_bytes(dsTemp, 9);
//--compute tempC (Temperaure in degree C)----------
unsigned int dsRawTemp = (dsTemp[1] << 8) | dsTemp[0];
dsTempC = (float)dsRawTemp / 16.0; //default 12-bit resolution
}
Struggling with a heatwave here in UK (although I expect these are normal temperatures for the rest of the world!)
Forgot to say I am using Arduino 1-Wire Address Finder
and also getDeviceCount()
Followed Pete's suggestion and switched to 3.3K and managed to pick up addresses and readings from 5 sensors - 6th still elusive. 2.2K produced no readings
Realised my Nano is a clone, so switched to a pukka Uno but same results.
Thanks for your code Golam, which I expanded to cover my six sensors, but the same problem.
I have been playing with Arduinos since early 2016 and written over 1,000 sketches for scores of devices and produced lots of things that work, but beginning to think there is a problem with my DS18B20s!
Thanks for the help, but today the heat wins!
I would like to share your journey in the adventure of operating 7xDS18B20 sensors simultaneously. I have one more sensor in my house which I have just connected and the three are working fine with NANO. Inshalla, tomorrow I will collect 7 more and will put them together!
I've written a sketch which enumerates up to 16 DS18B20 sensors.
It then reads their temperatures every 10 seconds. It does this by issuing a SKIP ROM command followed by the CONVERT T command. This makes all the sensors do a conversion at the same time. The code can then read all the sensors with only one delay instead of having to delay while each sensor in turn does a conversion.
I have 7 sensors on pin 4 of a NANO with a 4.7kohm pullup resistor.
ds18b20_test_2.ino
11:45:03 CST Aug 5 2018
Chip = DS18B20 ROM = 28 60 D5 00 04 00 00 CF
Chip = DS18B20 ROM = 28 84 77 A5 05 00 00 09
Chip = DS18B20 ROM = 28 D4 C9 00 04 00 00 49
Chip = DS18B20 ROM = 28 1E C2 00 04 00 00 69
Chip = DS18B20 ROM = 28 E1 A3 00 04 00 00 E3
Chip = DS18B20 ROM = 28 25 AC 00 04 00 00 CF
Chip = DS18B20 ROM = 28 AF 42 A4 05 00 00 9E
ROM = 28 60 D5 00 04 00 00 CF
Temperature = 23.0000 Celsius
ROM = 28 84 77 A5 05 00 00 09
Temperature = 22.1250 Celsius
ROM = 28 D4 C9 00 04 00 00 49
Temperature = 21.8750 Celsius
ROM = 28 1E C2 00 04 00 00 69
Temperature = 23.0000 Celsius
ROM = 28 E1 A3 00 04 00 00 E3
Temperature = 21.8750 Celsius
ROM = 28 25 AC 00 04 00 00 CF
Temperature = 22.1250 Celsius
ROM = 28 AF 42 A4 05 00 00 9E
Temperature = 22.0000 Celsius
After an hour the readings have settled down to this:
ROM = 28 60 D5 00 04 00 00 CF
Temperature = 22.6250 Celsius
ROM = 28 84 77 A5 05 00 00 09
Temperature = 21.7500 Celsius
ROM = 28 D4 C9 00 04 00 00 49
Temperature = 21.6250 Celsius
ROM = 28 1E C2 00 04 00 00 69
Temperature = 22.7500 Celsius
ROM = 28 E1 A3 00 04 00 00 E3
Temperature = 21.6250 Celsius
ROM = 28 25 AC 00 04 00 00 CF
Temperature = 21.8750 Celsius
ROM = 28 AF 42 A4 05 00 00 9E
Temperature = 21.7500 Celsius
Pete
Here's the code:
#include <OneWire.h>
// Reads up to 16 DS18B20 and prints rom
// addresses
// Then reads temperatures every 10 seconds
// Tested on a NANO
/*
- need ds.reset before issuing commands
- Do SKIP ROM and CONVERT T.
- Don't change the precision - currently 11
Pete (El_Supremo)
*/
// http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
// The two bugs in the conversion of the temperature have been fixed.
// The first bug didn't handle the precision correctly for anything
// other than 12 bits.
// The second bug was that the temperature was converted as an
// unsigned int which meant that it wouldn't convert a negative
// temperature correctly.
// Use pin 4
OneWire ds(4);
//>>> SELECT a precision here
// t_precision #bits - delay(ms)
// 0 9 - 93.75
// 1 10 - 187.5
// 2 11 - 375
// 3 12 - 750
#define ds18b20_PRECISION 2
unsigned char t_precision = ds18b20_PRECISION;
// array for 16xDS18B20 addresses
byte addr[16][8];
// and scratchpad
byte data[12];
const unsigned char t_mask[4] = {
0x7, 0x3, 0x1, 0x0
};
void print_rom(byte *p)
{
Serial.print("ROM =");
for(int i = 0; i < 8; i++) {
Serial.write(' ');
if(*p < 16)Serial.print("0");
Serial.print(*p++, HEX);
}
Serial.println(" ");
}
byte numdev;
void setup(void)
{
byte i;
byte type_s;
Serial.begin(9600);
i = 0;
Serial.println(__FILE__);
Serial.print(__TIME__);
Serial.print(" CST ");
Serial.println(__DATE__);
// Initial scan to get the ROM addresses
while(ds.search(addr[i])) {
if (OneWire::crc8(addr[i], 7) != addr[i][7]) {
print_rom(addr[i]);
Serial.println("CRC is not valid! - ignored");
continue;
}
// the first ROM byte indicates which chip
switch (addr[i][0]) {
case 0x10:
Serial.print(" Chip = DS18S20 "); // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.print(" Chip = DS18B20 ");
type_s = 0;
break;
case 0x22:
Serial.print(" Chip = DS1822 ");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
continue;
}
print_rom(addr[i]);
i++;
}
if(i == 0) {
Serial.println("Nothing found");
Serial.println();
ds.reset_search();
delay(250);
while(1);
}
numdev = i;
}
void loop(void)
{
byte present = 0;
float celsius, fahrenheit;
// Issue SKIP ROM command followed by
// Convert T so that sensors do a
// temperature conversion simultaneously
// This works ONLY in NON-parasite mode
present = ds.reset();
ds.write(0xCC,0);
ds.write(0x44,0);
delay(800);
// Now read all the temperatures
for(int j=0;j<numdev;j++) {
Serial.println();
print_rom(addr[j]);
present = ds.reset();
ds.select(addr[j]);
ds.write(0xBE,0); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
// BUG - this must NOT be unsigned otherwise it won't handle
// negative temperatures.
int raw = (data[1] << 8) | data[0];
// The original version of this code had a bad bug here which
// only worked when it was reading with 12-bit precision.
// This code fixes it (and I emailed the author).
// int cfg = (data[4] & 0x60) >> 5;
int cfg = t_precision;
raw &= ~t_mask[cfg];
celsius = (float) raw / 16.0;
Serial.print(F(" Temperature = "));
Serial.print(celsius,4);
Serial.println(F(" Celsius"));
// fahrenheit = celsius * 1.8 + 32.0;
// Serial.print(fahrenheit);
// Serial.println(" Fahrenheit");
}
Serial.println("=================");
delay(10000);
}
Thank you Golam. I have only 6, but when I paid only 3 x 0.99 GBP for the lot I cannot expect too much!
Temperatures have been a big disappointment for me with the Arduino. Most books and tutorials use TMP36 - which I found to read 10'C high (today 21'C high!).
DS18B20 are good in small quantities, but testing 3 all together they give very different readings, and siting them round the house is not as simple as it sounds. I have got two operating in parasitic mode, but not more than two.
BMP280 is very accurate - but temperature is just a byproduct there!
Pete. Thanks for your code which came in while I was replying here. I will give it a whirl!
Wow Pete. What a crafty bit of code! No wonder you chose a handle 'el_supremo'!
Having been in the coding business since the early '60s I can see I am getting too old for this game.
Your code works great on the Nano with 4.7K and three sensors.
I then add the fourth in the second column and that is ok.
But when I add the fifth I get 'Nothing found'
Changing to 3.3K it works ok with four as above.
But adding a fifth I get 'CRC is not valid! - ignored'
So thanks for all your time, but I have still a way to go. I will get the specs out and check parameters on my devices
Just a wild shot from the hip - are you sure the resistor is 4.7k and not 47k? It definitely won't work with 47k.
Pete