DS18B20 multiple sensors

Hi,

I have connected 9 of DS18B20 sensors on the arduino mega (pin 3) and one DHT22 sensor on pin 2. With 5minutes delay, the arduino board on serial monitor prints all addresses of those DS18B20 with their temperatures and temperature and humidity of that DHT22 sensor. Everything works fine, until i connect the 10th DS18B20 sensor. When i connect the 10th sensor the board prints only the temperature and humidity from DHT22 sensor. Any suggestions what should be wrong?

I wired the DS18B20 sensors like that: http://bildr.org/blog/wp-content/uploads/2011/06/DS18S20-hookup.png

How are you powering that many sensors?

All to the same 5V pin on arduino board. Arduino is powered by 9V adapter.

If you are using the 4.7k resistor shown in the diagram try changing it to 2.2k or 1k.

Pete

Ok, so it is possible that 5V is not enough power supply for all of them, but i have in mind to connect about 5-10 more sensors, will that 5V be enough you think?

what if i connect 5V cable to data cable without resistor?

It's not the 5V, it's the 5V -through- the Arduino. You want to draw 200 mA or less total -through- the Arduino. Think about external power through transistors.

Ok, so it is possible that 5V is not enough power supply for all of them

No, that is not why. I assume that you are using them in parasite mode in which case the pullup must not be high enough that it prevents parasite mode from working properly. The spec for the DS18B20 says that it uses 1mA while doing a conversion. The 4.7k resistor you are using may not permit enough current when you have so many devices on the bus. So, reduce the resistor to 2.2k or 1k and see if that fixes the problem.
However, when you have that many devices (and you say you want to add more) I presume you are spreading them around. If you are using parasite mode with that many devices you will have to take note of what the datasheet says about how to power the I2C bus properly.

Pete

I don't really know how does the parasite mode looks like :slight_smile: I have one wire for +5V, one wire for GND and one wire for data going out of the Arduino. Then those wires splits up in 9 different ways and then realy close to the sensors i have resistors (connecting 5V and data) on each of the sensors. Is that ok, or i should better use just one resistor in the begining (near to Arduino board) for all of the sensors?

I would try it with 1k resistor, but i have one problem. The senzors are already in place, with the 4.7k resistors. So if i understand it right, if i connect one more sensor (10th), not with 4.7k resistor but with the 1k resistor, then the Arduino should read at least that sensor. I don't want to happen that i would disassemble all of the sensors and replace the resistors and then it wouldn't work.

You appear to be providing a 5V line to each of the sensors, in which case you don't need to use parasite mode, but I don't think you need a 4k7 resistor on each sensor either.
If you post your code we can tell whether your code is using parasite mode and take it from there.

Pete

Ok, here is the code:

#include <DHT22.h>
#include <OneWire.h>

#define DHT22_PIN 2 // DHT22 on pin X

OneWire  ds(3);  // DS18B20s on pin X

void setup()
{
   Serial.begin(9600);
}

void loop()
{
	byte data[12];
	byte addr[8];

	DHT22 myDHT22(DHT22_PIN);

	delay(2000); //DHT22 can only be read 1-2 s


	//while number of DS18B20 sensors are connected
	while( ds.search(addr)) {

		printAddressDS18B20(addr);

		readDataDS18B20(addr, data);

		float celsius = getTemperatureDS18B20(data);
                Serial.print(";");
		Serial.print(celsius);
		Serial.println();

	} 

	resetDS18B20DsSearch();

	printTemperatureHumidityDHT22(myDHT22);

        delay(298000);


}

float getTemperatureDS18B20(byte data[12]){
	
	unsigned int raw = (data[1] << 8) | data[0];
	  
	byte cfg = (data[4] & 0x60);
	if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
	else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
	else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
	// default is 12 bit resolution, 750 ms conversion time

	return (float)raw / 16.0;
}

void readDataDS18B20(byte addr[8], byte data[12]){

	  byte present = 0;

	  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

	  for ( byte i = 0; i < 9; i++) {           // we need 9 bytes
		data[i] = ds.read();
	  }
}

void resetDS18B20DsSearch(){
	ds.reset_search();
	delay(250);
}
void printAddressDS18B20(byte addr[8]){
      
	  for( byte i = 0; i < 8; i++) {
		Serial.print(addr[i], HEX);
	  }
}

void printTemperatureHumidityDHT22(DHT22 DHT22){
	DHT22_ERROR_t errorCode = DHT22.readData();

		switch(errorCode)
	  {
		case DHT_ERROR_NONE:
		  Serial.print("DHT22;");
		  Serial.print(DHT22.getTemperatureC());
		  Serial.print(";");
		  Serial.println(DHT22.getHumidity());
      
		  break;
	   }
}

Is there any other, simplier way to get temperature from DS18B20?

I look at those delays and think "no, I don't have time to rewrite the whole thing".

BlinkWithoutDelay. Finite State Machine.

	  ds.write(0x44,1);         // start conversion, with parasite power on at the end

Yep, you are using parasite power. Your description of how you have wired up the sensors suggests that you don't need this, so change it to:

	  ds.write(0x44,0);         // start conversion.

and try again.

Pete

The OP wrote: "I have one wire for +5V, one wire for GND and one wire for data going out of the Arduino. Then those wires splits up in 9 different ways and then realy close to the sensors i have resistors (connecting 5V and data) on each of the sensors. Is that ok, or i should better use just one resistor in the begining (near to Arduino board) for all of the sensors?"

I think he has a resistor on each sensor, making for 10 resistors when he has 10 sensors. If that's the case, then that's the problem. Only one pullup resistor to +5V on the data line. With all those resistors in parallel, the devices can't pull the bus low.

EDIT: I suggest the OP read some Dallas documentation on powering the 1-wire data bus. He could get rid of a wire (+5V) by using parasitic power mode thru the data line. Then he'd only have to run the Data(Q) and Gnd wires to the sensors. Handier sometimes.

Why would you want to pull the power line low?

But then why put a resistor between power and data? Between power and the chip, I could see.
First time I read that I just figured it was some kind of typo.

Dallas 1-wire devices are open-collector. You have to supply a pull-up resistor from the data line to +5V (Vcc) on the data bus. Only one resistor is needed for the entire bus.

Ok i have now tried with only one 4.7k resistor (between DATA and +5V wires), and it works with 11 sensors, with the same code used before. Now i will try it with at least 22 sensors, and we will see what happens :slight_smile:

At some point, it will stop working again. If you have an oscilloscope, you can see how the signal degrades as you pile on sensors. It's not like it's a very clean signal to start with. Long cables will add to your woes because of the capacitance of the wiring. Lower value pull-up resistors will help in many situations. As you already saw, you could go as low as 1k if needed since it was working until you got it below about 500 ohms. The sensors were only designed to sink 4mA which means even 1k is a little small.

At some point, it will stop working again.

Yes, i realize that, and when it does i will try with smaller resistor or something like that.

Is there any difference in number of sensors which can be connected or in code how to retrieve temperature if i would wire it like you (@afremont) said?

I suggest the OP read some Dallas documentation on powering the 1-wire data bus. He could get rid of a wire (+5V) by using parasitic power mode thru the data line. Then he'd only have to run the Data(Q) and Gnd wires to the sensors. Handier sometimes.

afremont:
At some point, it will stop working again. If you have an oscilloscope, you can see how the signal degrades as you pile on sensors. It's not like it's a very clean signal to start with. Long cables will add to your woes because of the capacitance of the wiring. Lower value pull-up resistors will help in many situations. As you already saw, you could go as low as 1k if needed since it was working until you got it below about 500 ohms. The sensors were only designed to sink 4mA which means even 1k is a little small.

You're beyond me but could he use a circuit to drive a led as a line indicator?

Also, couldn't an Arduino support more than one 1-wire bus?

Time to look at the datasheet, it tells all. The only difference is that you have to supply extra power when a temp conversion (or EEPROM write) is in progress. The datasheet shows how to do it, it's simple; it takes an extra i/o pin though. You just enable the pin after issuing the conversion command. That in turn bypasses the pull-up resistor on the data line (Q) so that the device has plenty of power to do the temp conversion or write to its EEPROM. Look at the datasheet, they have a nice write-up on how it all works.