-->
Page 1 of 2

Mutiple I2C Devices with SAME Address - SHT21/HTU21D

PostPosted: Wed Jan 04, 2017 1:23 pm
by GengusKahn
This is an example of solving the problem of I2C devices with no user adjustable Device Address.

There are probably other solutions but this is very simple.......

There are no Library changes..........

Code: Select all/*
This is an Arduino library for SHT21 & HTU21D Digital Humidity & Temperature Sensor

Adapted for Multiple Sensors with no way to change device address.........
Pins, any you have spare on your ESP8266, But NOT A0 or D16(D0 Node)

The devices can share a Clock pin but not the data pin if they share an address.....
In this example I have used...(I only have 3 spare SHT21's)

pin 5 for SCL
Pin 0 for SDA Bus 0
Pin 2 for SDA Bus 1
Pin 4 for SDA Bus 2

Written by enjoyneering79
Adapted Jan 2017

These sensors use I2C to communicate, 2 pins are required to interface

Connect HTU21D to pins :  SDA  SCL
Uno, Redboard, Pro:       A4   A5
Mega2560, Due:            20   21
Leonardo:                 2    3





BSD license, all text above must be included in any redistribution
*/
/**************************************************************************/

#include <Wire.h>
#include "HTU21D.h"


HTU21D myHTU21D;


int flip=0;


void setup()
{
 
  Serial.begin(115200);
  //Serial.set_tx (2);
  Serial.println(F(""));
  delay(10);
  Wire.begin(4,5); 
  delay(250);
  while (myHTU21D.begin() != true)
  {
    Serial.println(F("HTU21D sensor is not present"));
    delay(5000);
  }
 
  Serial.println(F("HTU21D sensor is present"));
}

void loop()
{
  if(flip==0){
    flip=1;
    delay(250);
    Wire.begin(0, 5);
    delay(100);
    myHTU21D.begin(); 
    delay(250);
    Serial.println(F("Sensor Bus 0"));
  }else if (flip==1){
    flip=2;
    delay(250);
    Wire.begin(2, 5);
    delay(100);
    myHTU21D.begin(); 
    delay(250);
     Serial.println(F("Sensor Bus 1"));   
  }else{
    flip=0;
    delay(250);
    Wire.begin(4, 5);
    delay(100);
    myHTU21D.begin(); 
    delay(250);
     Serial.println(F("Sensor Bus 2"));   
  }
  Serial.println(F(""));
  Serial.println(F("<<DEMO: Default settings, %RH: 12Bit, Temperature - 14Bit>>"));
 
  Serial.println(F(""));
  Serial.print(F("Compensated Humidity: "));
  Serial.print(myHTU21D.readCompensatedHumidity());
  Serial.println(F(" +-2%RH     in range 0%RH - 100%RH at tmp. range 0deg.C - 80deg.C"));

  Serial.println(F(""));
  Serial.print(F("Temperature: "));
  Serial.print(myHTU21D.readTemperature());
  Serial.println(F(" +-0.5 deg.C"));

  Serial.println(F(""));
  Serial.println(F("\r\n\r\n"));
  delay(5000);
}

Re: Mutiple I2C Devices with SAME Address - SHT21/HTU21D

PostPosted: Wed Jan 04, 2017 2:18 pm
by danbicks
@GengusKahn,

As always a great way to utilize I2C devices with the same address, great example....

Dans

Re: Mutiple I2C Devices with SAME Address - SHT21/HTU21D

PostPosted: Fri Jan 06, 2017 2:25 pm
by GengusKahn
This can be used for Multiple Displays, with separate or copied data..... using ESP8266 OLED SSD1306 Driver
I added the logging of High / Low values to the EEPROM Space in the Flash....


Code: Select all/**************************************************************************/
/*
This is an Arduino library for SHT21 & HTU21D Digital Humidity & Temperature Sensor

Written by enjoyneering79

These sensor uses I2C to communicate, 2 pins are required to interface

Connect HTU21D to pins :  SDA  SCL
Uno, Redboard, Pro:       A4   A5
Mega2560, Due:            20   21
Leonardo:                 2    3

Adapted for Multiple Sensors with no way to change device address.........
Pins, any you have spare on your ESP8266, But NOT A0 or D16(D0 Node)

The devices can share a Clock pin but not the data pin if they share an address.....

In this example I have used...

pin 5 for SCL

Pin 4 for SDA Bus 0  DO NOT USE PIN 0 IF USING THE Reset EEPROM Button !!!!
Pin 2 for SDA Bus 1
Pin 10 for SDA Bus 2  //Only for the devices with access......

EEPROM Locations can be specified for any variable,
just squeeze into and out of the 32bit Long.....


  HighHum  EEPROM Address 0
  LowHum   EEPROM Address 4
  HighTemp EEPROM Address 8
  LowTemp  EEPROM Address 12


BSD license, all text above must be included in any redistribution
*/
/**************************************************************************/

#include <Wire.h>
#include "HTU21D.h"
#include "SSD1306.h"
#include <ESP8266WiFi.h>
#include <EEPROM.h>


HTU21D myHTU21D;

int HighTemp,LowTemp,HighHum,LowHum;
int flip=0;
int diSp=1;


// needed to avoid link error on ram check
extern "C"
{
#include "user_interface.h"
}


// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 0;     // the number of the pushbutton pin (Flash Button)

// variables will change:
int buttonState = 1;         // variable for reading the pushbutton status (Pullup for boot....)

SSD1306  display(0x3c, 4, 5);

//This function will write a 4 byte (32bit) long to the eeprom at
//the specified address to address + 3.
void EEPROMWritelong(int address, long value)
       {
       //Decomposition from a long to 4 bytes by using bitshift.
       //One = Most significant -> Four = Least significant byte
       byte four = (value & 0xFF);
       byte three = ((value >> 8) & 0xFF);
       byte two = ((value >> 16) & 0xFF);
       byte one = ((value >> 24) & 0xFF);

       //Write the 4 bytes into the eeprom memory.
       EEPROM.write(address, four);
       EEPROM.write(address + 1, three);
       EEPROM.write(address + 2, two);
       EEPROM.write(address + 3, one);
       EEPROM.commit();
       }

//This function will return a 4 byte (32bit) long from the eeprom
//at the specified address to address + 3.
long EEPROMReadlong(long address)
       {
       //Read the 4 bytes from the eeprom memory.
       long four = EEPROM.read(address);
       long three = EEPROM.read(address + 1);
       long two = EEPROM.read(address + 2);
       long one = EEPROM.read(address + 3);

       //Return the recomposed long by using bitshift.
       return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
       }



void setup()
{
  EEPROM.begin(512);
  delay(100);
  Serial.begin(115200);
  //Serial.set_tx (2);
  Serial.println(F(""));
  delay(10);
  Wire.begin(4,5); 
  delay(250);
  while (myHTU21D.begin() != true)
  {
    Serial.println(F("HTU21D sensor is not present"));
    delay(5000);
  }
 
  Serial.println(F("HTU21D sensor is present"));
  delay(100);
  display.init();
  display.flipScreenVertically();
  //Setup the Hig/Low from EEPROM.....
  HighHum=EEPROMReadlong(0);
  LowHum=EEPROMReadlong(4);
  HighTemp=EEPROMReadlong(8);
  LowTemp=EEPROMReadlong(12);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

void loop()
{
  // Use the Flash Button to Reset EEPROM......Do NOT USE PIN 0 for IIC if used......
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is LOW:
  if (buttonState == LOW) {
  float IntHum=myHTU21D.readCompensatedHumidity()*100;
  delay(100);
  EEPROMWritelong(0, IntHum);
  EEPROMWritelong(4, IntHum);
  delay(100);
  float IntTemp=myHTU21D.readTemperature()*100;
  delay(100);
  EEPROMWritelong(8, IntTemp);
  EEPROMWritelong(12, IntTemp);
  HighHum=EEPROMReadlong(0);
  LowHum=EEPROMReadlong(4);
  HighTemp=EEPROMReadlong(8);
  LowTemp=EEPROMReadlong(12);
  Serial.println(F("\r\nEEPROM RESET !!!!!"));
  }

  if(flip==0){  // Use these for Multiple Sensors....Sketch using 2, 4 + 10(-12E) for SDA and 5 for SCL
    flip=1;
    delay(250);
    Wire.begin(4, 5);
    delay(100);
    myHTU21D.begin(); 
    delay(250);
    Serial.println(F("Sensor Bus 0"));
  }else {
    flip=0;
    delay(250);
    Wire.begin(2, 5);
    delay(100);
    myHTU21D.begin(); 
    delay(250);
    Serial.println(F("Sensor Bus 1"));   
  }/*else{
    flip=0;
    delay(250);
    Wire.begin(10, 5); // DIO Mode ONLY!!!!! on ESP8266-12E
    delay(100);
    myHTU21D.begin(); 
    delay(250);
    Serial.println(F("Sensor Bus 2"));   
  }*/
 
 Serial.println(F("<<DEMO: Default settings, %RH: 12Bit, Temperature - 14Bit>>"));
  // Multiplication by 100 is to preserve the decimals when written to EEROM.....
  // Remember to divide when using the data.....read as float to regain the decimals.....
  // float samples=EEPROMReadlong(0); is used below, then /100 or combine........
  // This will produce the odd rounding error of 0.01, I do not need any more accuracy........
  // The HTU21/SHT21 Library reports an error by sending a value of 0.00, do not log the error...
 float IntHum=myHTU21D.readCompensatedHumidity()*100;
 delay(100);
 if(IntHum!=0.00){
 if(IntHum>HighHum){EEPROMWritelong(0, IntHum);HighHum=IntHum;diSp=1;}
 if(IntHum<LowHum){EEPROMWritelong(4, IntHum);LowHum=IntHum;diSp=1;}
  Serial.println(F(""));
  Serial.print(F("Compensated Humidity: "));
  Serial.print(IntHum/100);
  Serial.println(F(" +-2%RH     in range 0%RH - 100%RH at tmp. range 0deg.C - 80deg.C"));
 }
 float IntTemp=myHTU21D.readTemperature()*100;
 delay(100);
 if(IntTemp!=0.00){
 if(IntTemp>HighTemp){EEPROMWritelong(8, IntTemp);HighTemp=IntTemp;diSp=1;}
 if(IntTemp<LowTemp){EEPROMWritelong(12, IntTemp);LowTemp=IntTemp;diSp=1;}
  Serial.println(F(""));
  Serial.print(F("Temperature: "));
  Serial.print(IntTemp/100);
  Serial.println(F(" +-0.5 deg.C\r\n\r\n"));
 }
float samples=EEPROMReadlong(0);
  Serial.print(F("Sampled from EEROM 0,  All Time High Humidity    "));
  Serial.println(samples/100);
  samples=EEPROMReadlong(4);
  Serial.print(F("Sampled from EEROM 4,  All Time Low  Humidity    "));
  Serial.println(samples/100);
  samples=EEPROMReadlong(8);
  Serial.print(F("Sampled from EEROM 8,  All Time High Temperature "));
  Serial.println(samples/100);
  samples=EEPROMReadlong(12);
  Serial.print(F("Sampled from EEROM 12, All Time Low  Temperature "));
  Serial.println(samples/100);
  Serial.println(F("\r\n\r\n"));
    if(diSp==1){
    diSp=0;
    delay(250);
    Wire.begin(4, 5);              //***** Start the Display Explicitly on Bus 0, Maybe Use a Seperate Display on each bus......
    delay(100);                    //***** Comment out lines marked with ***** to run a seperate screen on each bus.....
    display.init();                //***** Seperate the samples by using the next 4 addresses for each sensor (512 Byte Total!).....
    display.flipScreenVertically();//***** 0,4,8,12 are Sensor Bus 0, use 16,20,24,28 for the next and 32,36,40,44 and so on....
    display.clear();
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 0, "High Temp " + String(HighTemp));
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 16, "Low Temp " + String(LowTemp));
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 32, "High Hum  " + String(HighHum));
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 48, "Low Hum   " + String(LowHum));
    // write the buffer to the display
    display.display();
  }
  delay(5000);
}

Re: Mutiple I2C Devices with SAME Address - SHT21/HTU21D

PostPosted: Thu Feb 02, 2017 6:56 am
by fra_savio
@GengusKahn
I have verified the first program with the IDE but it gives me this error:

C:\Users\Desktop\arduino-1.8.1\hardware\arduino\avr\libraries\Wire\src/Wire.h:54:10: note: candidate expects 1 argument, 2 provided

exit status 1
no matching function for call to 'TwoWire::begin(int, int)'