I am going to have a string of DS18B20s connected to an Arduino. I'm using the Mega2560 and version 2.1 of the OneWire library. When I have two of them on the bus, I get values that are reasonable.
When I have three or more, though, two of the values will always be identical. The correct number of sensors is found and all three show up as having unique addresses, but, again, two of the sensors will always read the same. I have tested different sensors (different models, even - also tried a small batch of DS18S20s) and I've moved their positions around on the bus and I always get the same thing, an example of which is below.
The ROM codes (R=) are incorrect, the LSB should always be 0x28. So I'd say the rest of the data is suspect as well, whether it seems reasonable or not.
The code is just the example program from the Onewire library. The only modification I made is to change the pin the sensors are on. I see code in this example to check for 0x10, but that was not triggered. Isn't address 0x10 the same as hex 10, which is what is reported?
When I had two sensors, I was able to touch either of them and have the temp (or whatever data they are reading) rise. If I have three sensors, touching two of them will make the values rise, but when I touch the other, the value will not rise. That sensor instead tracks one of the other two sensors.
thanks,
Eli
Here is the code for reference:
#include <OneWire.h>
/* DS18S20 Temperature chip i/o */
OneWire ds(2); // on pin 10
void setup(void) {
Serial.begin(9600);
}
void loop(void) {
byte i;
byte present = 0;
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
Serial.print("No more addresses.\n");
ds.reset_search();
delay(250);
return;
}
Serial.print("R=");
for( i = 0; i < 8; i++) {
Serial.print(addr[i], HEX);
Serial.print(" ");
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n");
return;
}
if ( addr[0] != 0x10) {
Serial.print("Device is not a DS18S20 family device.\n");
return;
}
// The DallasTemperature library can do all this work for you!
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
Serial.print("P=");
Serial.print(present,HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print( OneWire::crc8( data, 8), HEX);
Serial.println();
}
The code is just the example program from the Onewire library. The only modification I made is to change the pin the sensors are on. I see code in this example to check for 0x10, but that was not triggered. Isn't address 0x10 the same as hex 10, which is what is reported?
Hello! I've used that sample code too, it works OK for me. Yes, hex 10 is 0x10, which I see is the 8-bit family code for DS18S20. I was thinking the sample output was from B20s, in which case the family code is 0x28. Are you using parasitic power? The two bytes after the P bit (1) is the temperature, so 0x33, 0x34, 0x36 in your example. DS18S20 has 0.5°C resolution, so these just need to be converted to decimal and divided by two, so 25.5, 26.0, 27.0°C respectively. So those are reasonable but if they can't be moved around individually by touching each sensor, then something is fishy.
Just checking versions, I didn't have v2.1 of OneWire, I had v2.0. Your code looks like the example from v2.0. The example from v2.1 will distinguish between B20s and S20s and print actual temperatures.
Which Arduino version are you using? If you're using 1.0, be sure to use OneWire v2.1.
[quote author=Jack Christensen link=topic=90834.msg682297#msg682297 date=1328665182]
The ROM codes (R=) are incorrect, the LSB should always be 0x28. So I'd say the rest of the data is suspect as well, whether it seems reasonable or not.
Not so, the unique code the the DS18S20 is 0x10 - beware the difference between the DS18B20 and DS18S20!
[/quote]
Right, see previous post. I thought we were dealing with 'B20s, and hadn't checked the datasheet to know that 0x10 was the code for the 'S20.
Sorry for the confusion. Yes, I think in the data that I presented, I used the B20s. I've tested both B and S versions of the sensors, because we first bought five S versions and then realized that we needed better temp resolution and then bought five B versions. As far as the problem goes though, when I test with either B or S, I get the same problem. I have also tried to put in five sensors and it is always exactly one of them that has an identical value to one of the other sensors and does not respond. I verified that I am using version 2.1 of the OneWire library. I can see the comment in the .cpp code and it says 2.1. We are not using parasitic power. Is there a code change that I should be making for that, since I think the example is using parasitic power?
elimorris:
We are not using parasitic power. Is there a code change that I should be making for that, since I think the example is using parasitic power?
Don't think so, I don't remember having to change anything, and I just used "regular" power.
Just remove the second argument on the call to write() when starting a conversion...
Has this issue been resolved? I looked at the search() code in the OneWire library but its not exactly intuitive to follow so couldn't convince myself it was correct. I've used this library before with a dozen sensors to see how closely matched they were but I wouldn't have been looking for this erroneous behaviour - I think all my DS18B20's are now soldered into separate boards now so can't test this now!!
Well I think I've discovered a bug in OneWire library! Its got the wrong timing for the presence-pulse detection in the reset() function. Unfortunately this isn't the issue here (and its unlikely to ever be a problem with real devices which shouldn't be so close to the edge of the spec...)
I didn't find the problem, but I do think I traced it to the 'DallasTemperature' package. In my original post, I think I said I got the problem with the OneWire library and that wasn't right. I was confused going back and forth between program versions or something. I have a program based on the 'OneWire' library and it is working fine. A program based on the 'DallasTemperature' example, however, does seem to have the problem of listing duplicate values for the last two sensors in the string. If someone has three sensors lying around, I think it would be worth it to fire up the DallasTemp example, put code in for reading all three values ( Serial.print(sensors.getTempFByIndex(3)) and see if you have the problem.
Here is the complete program...
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SD.h>
#include <Wire.h>
File myFile;
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// 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);
void setup(void) {
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
Wire.begin();
// Start up the library
sensors.begin(); // IC Default 9 bit. If you have troubles consider upping it 12. Ups the delay giving the IC more time to process the temperature measurement
delay(1000);
Serial.print("number of sensors: ");
Serial.print(sensors.getDeviceCount() );
Serial.println("");
}
void loop(void) {
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.print(sensors.getTempFByIndex(1)); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
Serial.print(" ");
Serial.print(sensors.getTempFByIndex(2));
Serial.print(" ");
Serial.print(sensors.getTempFByIndex(3));
Serial.println("");
delay(1000);
}
loops are easy too once you have the device count.
an example below of filling an array of addresses during startup.
for (byte x = 0; x < mid_tempSensors; x++){
if (!TempSens_Mid.getAddress(mid_Thermometer[x], x)){
if (Debug) Serial.println("Unable to find address for mid_tempSensor");
}
}