add second same sensor in code

Hello forum members,

I'm making a code for the SHT75 (temperature and humidity sensor). the code is based on an existing code. I want to adjust the code. I've tried different things, but I can't find how to solve my problem. I want to add a second same sensor in the code. Can someone help me with that. Í don't have enough experience to do it myself, It's a step more difficult than normal.

Below you can see the code that I use!

Thanks in advance for helping me!

#include <Sensirion.h>

const uint8_t dataPin = 9; // SHT serial data
const uint8_t sclkPin = 8; // SHT serial clock
const uint8_t ledPin = 13; // Arduino built-in LED
const uint32_t TRHSTEP = 5000UL; // Sensor query period
const uint32_t BLINKSTEP = 250UL; // LED blink period

Sensirion sht = Sensirion(dataPin, sclkPin);

uint16_t rawData;
float temperature;
float humidity;
float dewpoint;

byte ledState = 0;
byte measActive = false;
byte measType = TEMP;

unsigned long trhMillis = 0; // Time interval tracking
unsigned long blinkMillis = 0;

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
delay(15); // Wait >= 11 ms before first cmd
// Demonstrate blocking calls
sht.measTemp(&rawData); // sht.meas(TEMP, &rawData, BLOCK)
temperature = sht.calcTemp(rawData);
sht.measHumi(&rawData); // sht.meas(HUMI, &rawData, BLOCK)
humidity = sht.calcHumi(rawData, temperature);
dewpoint = sht.calcDewpoint(humidity, temperature);
logData();
}

void loop() {
unsigned long curMillis = millis(); // Get current time

// Rapidly blink LED. Blocking calls take too long to allow this.
if (curMillis - blinkMillis >= BLINKSTEP) { // Time to toggle the LED state?
ledState ^= 1;
digitalWrite(ledPin, ledState);
blinkMillis = curMillis;
}

// Demonstrate non-blocking calls
if (curMillis - trhMillis >= TRHSTEP) { // Time for new measurements?
measActive = true;
measType = TEMP;
sht.meas(TEMP, &rawData, NONBLOCK); // Start temp measurement
trhMillis = curMillis;
}
if (measActive && sht.measRdy()) { // Note: no error checking
if (measType == TEMP) { // Process temp or humi?
measType = HUMI;
temperature = sht.calcTemp(rawData); // Convert raw sensor data
sht.meas(HUMI, &rawData, NONBLOCK); // Start humidity measurement
}
else {
measActive = false;
humidity = sht.calcHumi(rawData, temperature); // Convert raw sensor data
dewpoint = sht.calcDewpoint(humidity, temperature);
logData();
}
}
}

void logData() {
Serial.print("Temperature = ");
Serial.print(temperature);

Serial.print(" C, Humidity = ");
Serial.print(humidity);

Serial.print(" %, Dewpoint = ");
Serial.print(dewpoint);
Serial.println(" C");
}

I've tried different things, but I can't find how to solve my problem

Please post the code you tried and describe the problems that you had.

I added the code below in my first written text/question, I want to add a second same sensor. One sensor is already working but now I find a way to add a second sensor to do two measurements with two same sensors. I don't know how to do that. I hope you can help me with this problem. Át this moment I don't have enough experience with this kind of sensors (I'm not familiar with words like BLOCK, NON BLOCK, TRHSTEP etc.).

What I meant was for you to post the code that you tried with 2 sensors. The code in your first post only has one sensor defined in it.

Bocking implies a significant wait whilst something happens which is undesirable when try to do 2 things in quick succession. Non blocking is the opposite or at least an attempt to do things without holding up the rest of the code.

TRHSTEP is just the name of a variable holding a value in the program.

Thank you for answer.

Sorry I was not entirely clear. I tried to copy things and then put some values behind some (text)values. But I can not figure it out. I don't have experience with these sensors, so one sensor goes on, but add a second sensor does not work, I don't know what to add and need to adapt to get it done.

joostbudding:
Thank you for answer.

Sorry I was not entirely clear. I tried to copy things and then put some values behind some (text)values. But I can not figure it out. I don't have experience with these sensors, so one sensor goes on, but add a second sensor does not work, I don't know what to add and need to adapt to get it done.

where did you get the library?

#include <Sensirion.h>

I tried to copy things and

So, lets see that attempt.

You need to start with two instances of the Sensirion class. But, do not call them sht1 and sht2. Name the instances based on what you are actually using the sensors to measure.

Clearly, each instance needs its own clock and data pins, so you can't share them. Each returns a temperature and humidity value, so you need two variables to hold those value for each sensor.

Hello Paul,

Below you can see the things I've tried.

I hope you can help me further with this.


#include <Sensirion.h>

const uint8_t dataPin = 9; // SHT serial data
const uint8_t sclkPin = 8; // SHT serial clock
const uint8_t dataPin2 = 10;
const uint8_t sclkPin2 = 11;

const uint8_t ledPin = 13; // Arduino built-in LED
const uint32_t TRHSTEP = 5000UL; // Sensor query period
const uint32_t BLINKSTEP = 250UL; // LED blink period

Sensirion sht = Sensirion(dataPin, sclkPin);
Sensirion sht2 = Sensirion(dataPin2, sclkPin2);

uint16_t rawData;
float temperature;
float humidity;
float dewpoint;

uint16_t rawData2;
float temperature2;
float humidity2;
float dewpoint2;

byte ledState = 0;
byte measActive = false;
byte measType = TEMP;

unsigned long trhMillis = 0; // Time interval tracking
unsigned long blinkMillis = 0;

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
delay(15); // Wait >= 11 ms before first cmd
// Demonstrate blocking calls
sht.measTemp(&rawData); // sht.meas(TEMP, &rawData, BLOCK)
temperature = sht.calcTemp(rawData);
sht.measHumi(&rawData); // sht.meas(HUMI, &rawData, BLOCK)
humidity = sht.calcHumi(rawData, temperature);
dewpoint = sht.calcDewpoint(humidity, temperature);
logData();
}

void loop() {
unsigned long curMillis = millis(); // Get current time

// Rapidly blink LED. Blocking calls take too long to allow this.
if (curMillis - blinkMillis >= BLINKSTEP) { // Time to toggle the LED state?
ledState ^= 1;
digitalWrite(ledPin, ledState);
blinkMillis = curMillis;
}

// Demonstrate non-blocking calls
if (curMillis - trhMillis >= TRHSTEP) { // Time for new measurements?
measActive = true;
measType = TEMP;
sht.meas(TEMP, &rawData, NONBLOCK); // Start temp measurement
trhMillis = curMillis;
}
if (measActive && sht.measRdy()) { // Note: no error checking
if (measType == TEMP) { // Process temp or humi?
measType = HUMI;
temperature = sht.calcTemp(rawData); // Convert raw sensor data
sht.meas(HUMI, &rawData, NONBLOCK); // Start humidity measurement
}
else {
measActive = false;
humidity = sht.calcHumi(rawData, temperature); // Convert raw sensor data
dewpoint = sht.calcDewpoint(humidity, temperature);
logData();
}
}
}

void logData() {
Serial.print("Temperature = ");
Serial.print(temperature);

Serial.print(" C, Humidity = ");
Serial.print(humidity);

Serial.print(" %, Dewpoint = ");
Serial.print(dewpoint);
Serial.println(" C");

delay(1000);

Serial.print("Temperature2 = ");
Serial.print(temperature2);

Serial.print(" C, Humidity2 = ");
Serial.print(humidity2);

Serial.print(" %, Dewpoint2 = ");
Serial.print(dewpoint2);
Serial.println(" C");

delay(5000);
}

I hope you can help me further with this.

Did you see the part about using reasonable names. sht and sht2 show a COMPLETE lack of thought.

No. Until you are willing to THINK, I can not help you.

Just tacking a 2 onto the second instance is not showing any understanding.

If you created an array of instance, of temperatures, of humidities, etc., you could write a function to read the data for the each sensor, without caring which sensor it was. Use that function to get the data for the 0th sensor, putting it in the 0th position in the arrays. Use the same function to get the data for the 1th sensor.

Then, develop a function to print the data for the ith sensor.

It will then be VERY easy to see that you need to call the getSensorData() function twice and that you need to call the printSensorData() function twice.

You do not appear to be reading temperature2 or humidity2 from the second sensor or calculating dewpoint2

You're quiet right,

But do you mean this?

Sensirion Measurement 1 shade 1 Xyleen = Sensirion(dataPin, sclkPin);
Sensirion Measurement 2 shade 2 Formaldehyde = Sensirion(dataPin2, sclkPin2);

I'll give you background information:

At this moment I do measurement with different VOC's (Volatile Organic Compounds). I have two shades, in every shade a different VOC (Xyleen and Formaldehyde). But I want to meassure also temperature and Relative humidity in every shade. I use the SHT75 for this measurements, so I need two sensors in my meassure circuit. I hope that you know what I mean. You have to know that I don't have enough experience with this sensors in combination with Arduino, that's why I'm asking for help, and I hope that you'll help me with this problem

so when you have multiple of anything, it is time to think about object oriented programming, especially when you are doing like tasks.

something like this (untested):

#include <Sensirion.h>

struct Sensor{
  Sensor(int data, int clock, char* name){dataPin = data; sclkPin = clock; friendlyName = name; sht = new Sensirion(dataPin, sclkPin);}
  uint8_t dataPin;
  uint8_t sclkPin;
  char* friendlyName;
  float temperature;
  float humidity;
  float dewpoint;
  Sensirion* sht;
};

Sensor sensor[] = {{9,8, "Sensor1"},{10,11, "Sensor2"}};

Sensor* SomeAlias = &sensor[0];  // see loop() below

void setup() {
    Serial.begin(9600);
    delay(15);                           // Wait >= 11 ms before first cmd
    for (auto& s : sensor)
    {
      s.sht->measure(&s.temperature, &s.humidity, &s.dewpoint);
    }
    logData();
}

void loop() 
{
  static unsigned long lastPrintMillis = 0;
  if(millis() - lastPrintMillis > 5000)
  {
    for (auto& s : sensor)
    {
      s.sht->measure(&s.temperature, &s.humidity, &s.dewpoint);
    }
    logData();
    lastPrintMillis = millis();
  }

  // or using SomeAlias:
  //SomeAlias->sht->measure(&SomeAlias->temperature, &SomeAlias->humidity, &SomeAlias->dewpoint);
}

void logData() 
{
    for (auto s : sensor)
    {
      Serial.println(s.friendlyName);
      Serial.print("Temperature = ");
      Serial.print(s.temperature);
  
      Serial.print(" C, Humidity = ");
      Serial.print(s.humidity);
  
      Serial.print(" %, Dewpoint = ");
      Serial.print(s.dewpoint);
      Serial.println(" C");
    }
    Serial.println();
}

Thank you for answer my question, I agree with you!

Tomorrow I go further with this, and I'll tried what you said. I'll let it know if it's succeeded.

Thank you very much for your time and help!

You're code works, my sensors work both with your code, thanks!

There is only one question, how can I bifurcate the data for OLED display? the (old) code below is for one SHT sensor and it's another kind of pgrogramming. How can I do that for two sensors (in combination with my other code of course)

curMillis = millis();
if (curMillis -blinkMillis >= BLINKSTEP)
{
// Time to toggle the LED state?
ledState ^= 1;
blinkMillis = curMillis;
}
switch (shtState) {
case 0:
if (curMillis -trhMillis >= TRHSTEP) {

// Start new temp/humi measurement?
sht.meas(TEMP, &rawData, NONBLOCK);
shtState++;
trhMillis = curMillis;
}
break;
case 1:
if (sht.measRdy())
{
// Process temperature measurement?
temperature = sht.calcTemp(rawData);
sht.meas(HUMI, &rawData, NONBLOCK);
shtState++;
}
break;
case 2:

if (sht.measRdy()) { // Process humidity measurement?
humidity = sht.calcHumi(rawData, temperature);
dewpoint = sht.calcDewpoint(humidity, temperature);
shtState = 0;
Serial.println("SHT75-TEMP:");
SeeedGrayOled.setTextXY(3,6);
Serial.println(temperature);
dtostrf(temperature,2,1 ,temp);
SeeedGrayOled.putString(temp);
SeeedGrayOled.setTextXY(3,11);
SeeedGrayOled.putString("C");
SeeedGrayOled.setTextXY(5,6);
Serial.println("\nSHT75-HUM:");
Serial.println(humidity);
dtostrf(humidity,2,1 ,temp);
SeeedGrayOled.putString(temp);
SeeedGrayOled.setTextXY(5,11);
SeeedGrayOled.putString("%");
SeeedGrayOled.setTextXY(6,6);
Serial.println("\nSHT75-DEW:");
Serial.println(dewpoint);
dtostrf(dewpoint,2,1 ,temp);
SeeedGrayOled.putString(temp);
SeeedGrayOled.setTextXY(6,11);
SeeedGrayOled.putString("C");

}
break;

default:
Serial.println("How did I get here?");
break;

your code isn't readable, but are you simply trying to toggle the display between readings of both sensors?

BulldogLowell:
your code isn't readable, but are you simply trying to toggle the display between readings of both sensors?

if yes, you can try like this:

#include "Sensirion.h"

#define DISPLAY_INTERVAL 1500 // 1.5 seconds

struct Sensor{
  Sensor(int data, int clock, char* name){dataPin = data; sclkPin = clock; friendlyName = name; sht = new Sensirion(dataPin, sclkPin);}
  uint8_t dataPin;
  uint8_t sclkPin;
  char* friendlyName;
  float temperature;
  float humidity;
  float dewpoint;
  Sensirion* sht;
};

Sensor sensor[] = {{9,8, "Sensor1"},{10,11, "Sensor2"}};

Sensor* SomeAlias = &sensor[0];

void setup() 
{
    Serial.begin(9600);
    delay(15);                           // Wait >= 11 ms before first cmd
    for (auto& s : sensor)
    {
      s.sht->measure(&s.temperature, &s.humidity, &s.dewpoint);
    }
    logData();
}

void loop() 
{
  static unsigned long lastPrintMillis = 0;
  if(millis() - lastPrintMillis > 5000)
  {
    for (auto& s : sensor)
    {
      s.sht->measure(&s.temperature, &s.humidity, &s.dewpoint);
    }
    logData();
    lastPrintMillis = millis();
  }

  // or using SomeAlias:
  //SomeAlias->sht->measure(&SomeAlias->temperature, &SomeAlias->humidity, &SomeAlias->dewpoint);
  
  static uint32_t displayIndex = 0;
  static uint32_t lastDisplayChangeMillis = 0;
  if (millis() - lastDisplayChangeMillis > DISPLAY_INTERVAL)
  {
    displayIndex++;
    displayIndex %= sizeof(sensor)/sizeof(sensor[0]);  // iterate over the number of instances of sensor

    char value[6];  // check this!!

    // indicate somewhere on the screen which sensor.  you need to check this location and update the friendlyNames.
    SeeedGrayOled.setTextXY(0, 0);
    SeeedGrayOled.putString(sensor[displayIndex].friendlyName);
    
    // print over the last displayed values
    SeeedGrayOled.setTextXY(3, 6);
    dtostrf(sensor[displayIndex].temperature, 2, 1, value);
    SeeedGrayOled.putString(value);
    SeeedGrayOled.setTextXY(3, 11);
    SeeedGrayOled.putString("C");
    SeeedGrayOled.setTextXY(5, 6);
    dtostrf(sensor[displayIndex].humidity, 2, 1, value);
    SeeedGrayOled.putString(value);
    SeeedGrayOled.setTextXY(5, 11);
    SeeedGrayOled.putString("%");
    SeeedGrayOled.setTextXY(6, 6);
    dtostrf(sensor[displayIndex].dewpoint, 2, 1 , value);
    SeeedGrayOled.putString(value);  // edit transposition error
    SeeedGrayOled.setTextXY(6, 11);
    SeeedGrayOled.putString("C");

    lastDisplayChangeMillis =millis();
  }
  
}

void logData() 
{
    for (auto s : sensor)
    {
      Serial.println(s.friendlyName);
      Serial.print("Temperature = ");
      Serial.print(s.temperature);
  
      Serial.print(" C, Humidity = ");
      Serial.print(s.humidity);
  
      Serial.print(" %, Dewpoint = ");
      Serial.print(s.dewpoint);
      Serial.println(" C");
    }
    Serial.println();
}

yes I know you can't understand my written code, It's only a little part of my totally code. This is the code before with one sensor.

Now I've got a code from you, what's working, but now I'll display it on a OLED display.

At this moment the serial monitor give every moment two different results, but I don't know how you can display it on a OLED, two different values/sensors. (I've a few more sensors connected on it, but that's not important for this)

joostbudding:
yes I know you can't understand my written code, It's only a little part of my totally code. This is the code before with one sensor.

Now I've got a code from you, what's working, but now I'll display it on a OLED display.

At this moment the serial monitor give every moment two different results, but I don't know how you can display it on a OLED, two different values/sensors. (I've a few more sensors connected on it, but that's not important for this)

look at the code I posted just above your reply...

I don't know how you can display it on a OLED, two different values/sensors

Print one value in one position and another in another position. Sounds simple.

Your code works great, but you forgot one another thing, the display had to be initialized, but that's already done

But what I meant, both sensorvalues on one display, so no switching between both sensors.