Multiple Serial Humidity sensors - SHT71

I want to have multiple ( up to 10 ) humidity sensors connected to my Mega2560.

I already have 4 ds18b20 temp sensors connected to 1 input pin working perfectly.

Have been looking at the Sensirion SHT71 sensors and need advice. Component link : http://za.rs-online.com/web/p/temperature-sensor/6675278/

From what I understand, these are digital serial sensors. Their connection pins are : DATA, SCK, VDD & GND.

I have looked at the tutorial (http://www.arduino.cc/en/Tutorial/SoftwareSerial) but I am still unsure of :

  1. can I connect multiple sensors to the same DATA and SCK pins ?
  2. if I need to seperate for each sensor, can one of the above 2 pins be common ( so I only need one additional pin for each additional sensor ) ?
  3. if multiple sensors can be added to the same 2 pins, how do I get the humidity reading from a specific sensor ? Do they have some sort of unique internal address like the ds18b20 temp sensors ?

Appreciate your sharing experience and expertise.

SOftwareSerial is depreciated, use NewSoftSerial instead - NewSoftSerial | Arduiniana -

Looks like the SHT71 is not an asynchronous serial device so SoftwareSerial and NewSoftSerial won't help you directly. It connects as if it were an I2C device but it doesn't have an I2C address so you can't use more than one on the bus AND you have to do some odd stuff to keep from interfering with any I2C devices on the bus.

Perhaps a One Wire device or I2C device with a programmable address would be better for your purposes. If you really want to use this particular sensor you might want to connect a processor to each one to translate.

Many thanks to all for the prompt replies.

johnwasser: Looks like the SHT71 is not an asynchronous serial device so SoftwareSerial and NewSoftSerial won't help you directly. It connects as if it were an I2C device but it doesn't have an I2C address so you can't use more than one on the bus AND you have to do some odd stuff to keep from interfering with any I2C devices on the bus.

Perhaps a One Wire device or I2C device with a programmable address would be better for your purposes. If you really want to use this particular sensor you might want to connect a processor to each one to translate.

Will go looking for another more suitable device in the same price range ( and available locally ).

In the event of not being able to find an alternative, would this be feasable ? :

Scenario : I only need to read one sensor at a time, and only about once per minute,

  1. connect all DATA pins to one Arduino pin ( say, pin 6 )
  2. connect all SCK pins to one pin ( say, pin 7 )
  3. connect all Gnd pins to GND
  4. connect each VDD pin to a seperate Arduino output pin ( say, pins 8,9,10, etc)

so the logic in the code would be :

set pins 8, 9 & 10 LOW set the comms pins to 6 & 7 set pin 8 HIGH ( sensor #1 ) - ( giving 5V to sensor 1 ) get the readings / data from sensor 1 set pin 9 HIGH ( sensor #2 ) get the readings / data from sensor 2 set pin 10 HIGH ( sensor #3 ) get the readings / data from sensor 3

OK. I appreciate the range of things that could go wrong with constantly powering up / down the sensors, and the potential damage to them that this could have.

So how about we swing the idea around a bit and change to :

  1. connect each DATA pins to seperate Arduino pins ( say, pin 8,9,10, etc )
  2. connect all SCK pins to one pin ( say, pin 7 )
  3. connect all Gnd pins to GND
  4. connect all VDD pin to the 3.3V arduino output ( so they are permanently powered up ).

Then the code would simply make changes to read the data from pin 8 ( for sensor 1 ), pin 9 ( for sensor 2 ), and so on.

There was recently posted an I2C mux for parts that did not have addressing capability.

http://www.dsscircuits.com/i2c-multiplexer.html

See if that will suit your needs.

If not, could probably make your own version of dual signal switch with 1 of 16 data selector like this http://www.maxim-ic.com/datasheet/index.mvp/id/1002/t/al

The SHT7x (and SHT1x) parts do not use I2C communication. The newer SHT21 does but has a fixed I2C address (it is also intended for 3.3V operation). I have not tried this but it might be possible to save pins by connecting multiple SHT1x/7x devices to a single data line while dedicating individual clock lines to each part.

I played around with connecting more than one SHT75 to a single Arduino. I tried powering them individually from a digital output but I think I got some kind of conflict from them being alternately powered from feedback from their clk or data line so I didn't follow up on that. You can operate them with a common data line and a separate clk to each device. When you hold the clk low, they are effectively asleep. You have to pull the data line up with a 10K resistor. I didn't try using the internal pull-up.

Hi, I think these sensors all have nonstandard protocols.

See: http://arduino.cc/playground/Main/DHTLib

and some info here: http://arduino-info.wikispaces.com/DHT11-Humidity-TempSensor

DaveO: OK. I appreciate the range of things that could go wrong with constantly powering up / down the sensors, and the potential damage to them that this could have.

So how about we swing the idea around a bit and change to :

  1. connect each DATA pins to seperate Arduino pins ( say, pin 8,9,10, etc )
  2. connect all SCK pins to one pin ( say, pin 7 )
  3. connect all Gnd pins to GND
  4. connect all VDD pin to the 3.3V arduino output ( so they are permanently powered up ).

Then the code would simply make changes to read the data from pin 8 ( for sensor 1 ), pin 9 ( for sensor 2 ), and so on.

Hi Dave, did you get it running like you described it here ? Thanks AgeBee

Hi AgeBee

No, sorry. I didn't.

I got too involved in another project and this one wasn't as interesting as the newer one was.

Regards

DaveO: Hi AgeBee

No, sorry. I didn't.

I got too involved in another project and this one wasn't as interesting as the newer one was.

Regards

Hi DaveO, I got it working like you described it in your post #4 in this thread. If you use two SHT71 sensors you have to use different data inputs. Both sensors share the same clock (SLK), GND and VDD. It works perfectly. Regards AgeBee

AgeBee: Hi DaveO, I got it working like you described it in your post #4 in this thread. If you use two SHT71 sensors you have to use different data inputs. Both sensors share the same clock (SLK), GND and VDD. It works perfectly. Regards AgeBee

Hi AgeBee

It was really just a thought at the time, and I never got round to testing it.

Very glad to hear you tried it and it works.

Regards Dave

another way is to put the data line to a multiplexer analog switch.

shooter: another way is to put the data line to a multiplexer analog switch.

like the PCA9544A ?

Hi AgeBee,

Would you mind linking the code you used to get your array of sensors to run properly? I'm running into an issue in my code and would like to cross-reference it with someone else's.

//SHT71_Double_Temp_Hum_Logging
//measuring temperature and humidity with two precise sensors (Sensirion SHT71)

//SHT71 can be connected to I2C but hasn't got an address -> cannot be addressed by I2C protocol
//the sensor can be connected to an I2C bus without interference with other devices connected to the bus.

//Sensor 1
//data PIN 1 (clock) -> D8  both sensors use the same clock
//data PIN 2 (VDD) -> + 3 V  recommended supply voltage is 3.3V for higher precision.
//data PIN 3 (GND) -> GND
//data PIN 4 -> D9

//Sensor 2
//data PIN 1 (clock) -> D8  both sensors use the same clock
//data PIN 2 (VDD) -> + 3 V  recommended supply voltage is 3.3V for higher precision.
//data PIN 3 (GND) -> GND
//data PIN 4 -> D7


//time with DS1370 real time clock
//use examples -> DS1307RTC -> SetTime.ino to set the time
//also works with RTC from DataLogging shield
//SDA -> A4
//SCL -> A5
//VDD -> 5 V
//GND -> GND


//logging to SD card via Adafruit Micro-SD breakout board or DataLogging shield from Ebay
//GND -> GND
//5 V -> 5 V
//CLK -> D13
//DO -> D12
//DI -> D11
//CS -> D10 




#include <SPI.h>
#include <Sensirion.h>
#include <SD.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>

const uint8_t dataPin1  =  9;//Luft
const uint8_t dataPin2  =  7;//Biene
const uint8_t clockPin =  8;

const uint8_t fileWritePin =  13;

long previousMillis = 0;

long interval = 86400; //3000 = 3 sec; 300000 = 5 min; 1000 measurements per day -> every 86400 msec


float temperature1;
float humidity1;
float dewpoint1;


float temperature2;
float humidity2;
float dewpoint2;

const int chipSelect = 10;

Sensirion tempSensor1 = Sensirion(dataPin1, clockPin);//air
Sensirion tempSensor2 = Sensirion(dataPin2, clockPin);//bees

template<class T> inline Print &operator <<(Print &obj, T arg) 
{ 
  obj.print(arg); 
  return obj; 
}

void setup()
{
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);

  pinMode(fileWritePin, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  //while (!Serial) ; // wait until Arduino Serial Monitor opens
  setSyncProvider(RTC.get);   // the function to get the time from the RTC

  time_t sometime = RTC.get();
}

void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {

    tempSensor1.measure(&temperature1, &humidity1, &dewpoint1);
    tempSensor2.measure(&temperature2, &humidity2, &dewpoint2);
    
    digitalClockDisplay();
    Serial.print("Temperature 1: ");
    Serial.print(temperature1);
    Serial.print(" C, Humidity 1: ");
    Serial.print(humidity1);
    Serial.print(" %, Dewpoint 1: ");
    Serial.print(dewpoint1);
    Serial.println(" C");
    
    Serial.print("Temperature 2: ");
    Serial.print(temperature2);
    Serial.print(" C, Humidity 2: ");
    Serial.print(humidity2);
    Serial.print(" %, Dewpoint 2: ");
    Serial.print(dewpoint2);
    Serial.println(" C");

    //log to file
    File dataFile = SD.open("templog.txt", FILE_WRITE);

    // if the file is available, write to it:
    if (dataFile) {

      digitalWrite(fileWritePin, HIGH);   // turn the LED on (HIGH is the voltage level)
      delay(1000);              // wait for a second
      digitalWrite(fileWritePin, LOW);    // turn the LED off by making the voltage LOW
      delay(1000);
            
      dataFile.print(day());
      dataFile.print(".");
      dataFile.print(month());
      dataFile.print(".");
      dataFile.print(year()); 
      dataFile.print(" ");
      dataFile.print(hour());
      dataFile.print(":");
      dataFile.print(minute());
      dataFile.print(":");
      dataFile.print(second());
      dataFile.print("|");
      dataFile.print(temperature1);
      dataFile.print("|");
      dataFile.print(humidity1);
      dataFile.print("|");
      dataFile.print(temperature2);
      dataFile.print("|");
      dataFile.println(humidity2);
      dataFile.close();
    }  
    previousMillis = currentMillis;
          
  }//if
  //delay(5000);  
}


void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(day());
  Serial.print(".");
  Serial.print(month());
  Serial.print(".");
  Serial.print(year()); 
  Serial.print(" ");
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

In case another absolute novice (completely new to both electronics and programming, like, this was my first project) like myself comes across this forum looking for help:

  1. First, check to be sure that each one of the jumpers (and all of the other components for that matter) that you’re using works (the resistance should be no more than an Ohm or so). In my array of five sensors, two weren’t working. After much time spent testing, I knew it had to be a connection to the serial clock that was messing up. It took days to realize that a faulty wire was even a possibility. It was a two-minute fix after this epiphany.

  2. AgeBee posted his/her code, which has much more functionality than mine does, and I’m thankful because there are some additional features (time) I’d like to implement into my own. I’ve posted my code below because it includes only reading and writing from the sensors, so it may be easier to get a person started. As DaveO first asked, this directs all five sensors using one serial clock pin. I used sht75s, but to my knowledge, any sht7x should work. The program was originally written for people in my research group (especially future members who may encounter the code long after I’ve graduated), so some of the comments, especially at the beginning, may be disregarded.

  3. If you’re looking at the code and wondering why I chose to print it that way, it’s to make post-processing of the data easier, as you can read the .txt file as comma delimited (every time a comma is encountered, it makes a new column; very useful for getting data into a spreadsheet).

/*
 * Query an array of SHT7x temperature and humidity sensors
 * and communicate results via serial connection.
 *
 * Currently, error handling is omitted, though error
 * handling will be implemented when I have the skill
 * and time.
 * 
 * Currently looking for a way to print the timestamp.
 * Use PuTTy to print to a .txt file in real time.
 */

//Libraries
#include <Sensirion.h>

//Constants
#define dataPin0 2
#define dataPin1 4
#define dataPin2 7
#define dataPin3 8
#define dataPin4 12
#define clockPin SCL
uint16_t rawData;
Sensirion sht [] = {
  Sensirion(dataPin0, clockPin),
  Sensirion(dataPin1, clockPin),
  Sensirion(dataPin2, clockPin),
  Sensirion(dataPin3, clockPin),
  Sensirion(dataPin4, clockPin),
};

//Variables
float temp[5];//Be sure to change the value to match the # of sensors
float hum[5];

void setup()//Code that runs once goes here
{
  Serial.begin(9600);
  delay(20);//According to the manufacturer, a delay of >= 11 milliseconds should occur after starting the sensor.
}

void loop()//Code that runs infinitely until the plug is pulled runs here
{
  delay(5000);//Queries once per this time (given in milliseconds)
    for (int i = 0; i < 5; i++) { //Again, be sure to match the sensor # to the i
    sht[i].measTemp(&rawData);
    temp[i] = sht[i].calcTemp(rawData);
    sht[i].measHumi(&rawData);
    hum[i] = sht[i].calcHumi(rawData, temp[i]);
  };

Serial.print(temp[0]); Serial.print(","); Serial.print(hum[0]); Serial.print(",");
Serial.print(temp[1]); Serial.print(","); Serial.print(hum[1]); Serial.print(",");
Serial.print(temp[2]); Serial.print(","); Serial.print(hum[2]); Serial.print(",");
Serial.print(temp[3]); Serial.print(","); Serial.print(hum[3]); Serial.print(",");
Serial.print(temp[4]); Serial.print(","); Serial.println(hum[4]);
  
}

I hope this helps someone. If anyone has any suggestions or improvements for my code, I’d be glad to hear them.

-ctcalvert

If anyone has any suggestions or improvements for my code, I'd be glad to hear them.

In particular, I'd love to implement the Serial.print part as a for loop, though it never turns out quite how I'd like it. Pointers are much appreciated.

-ctcalvert