MightyCore AtMega324PB - zweiten I2C Port nutzen - Anfängerfrage

Ich habe in letzter Zeit versucht über MightyCore den zweiten I2C Port an einen
AtMega324PB zu nutzen (PE6 / PE5) - über Wire1.

Ich habe zwei Temp. Sensoren deren Adresse nicht geändert werden kann (SHT21), daher wollte
ich jeden Sensor einen eigenen I2C Port zuweisen.
Machen kann man das auch mit einen Multiplexer etc. - aber wenn ich noch einen Port frei habe
möchte ich den auch nutzen können.
Das wäre für micht die beste und auch "einfachste" Lösung.
Ein angepasster I2C Scanner zeigt mir auch die Geräte an diesen Port an - vom Grundsatz her ist
die Hardware soweit i.O.
Ich kann aber mit den Arduino Libs nicht auf das Device an den zweiten Port zugreifen - der zweite
I2C Anschluss wird nicht "angesprochen".
Ich denke es liegt daran, dass die Arduino Libs standardmäßig mit der "normalen" Wire.h.
kommunizieren und nur auf den ersten Port an A4 und A5 bei den Nanos zugreifen und eine
Kommunikation über Wire1.h nicht vorgesehen ist.
Daher meine Frage: muss ich die Libs entsprechend anpassen damit Geräte über Wire1.h.
am zweiten Port erkannt / eingesetzt werden können oder hat das schon einmal jemand gemacht. ?

Kann schon sein, dass du recht hast.
Wire1 ist nicht so verbreitet, und nicht jeder Lib Ersteller hatte es auf dem Schirm, dass es eine Welt neben Wire gibt.

Tipp:
Irgendwie erscheint es mir seltsam, über eine Lib zu jammern, Aussagen darüber zu erwarten, ohne sie zu nennen oder gar diese zu verlinken.

Ja, so ein Eiertanz irritiert mich!
Ich frage mich dann:
Will er/sie/es überhaupt eine Lösung?
Ist es überhaupt bereit dafür?
Oder soll ich lieber meines Weges gehen....
Ja, das ist auch einen gute Idee!


Ein Tab mit einer modifizierten Lib

#pragma once
#include <Wire.h>

//---------- Defines -----------------------------------------------------------
#define I2C_ADD 0x40  // I2C device address

const uint16_t POLYNOMIAL = 0x131;  // P(x)=x^8+x^5+x^4+1 = 100110001

//==============================================================================
#define TRIGGER_T_MEASUREMENT_HM 0XE3   // command trig. temp meas. hold master
#define TRIGGER_RH_MEASUREMENT_HM 0XE5  // command trig. hum. meas. hold master
#define TRIGGER_T_MEASUREMENT_NHM 0XF3  // command trig. temp meas. no hold master
#define TRIGGER_RH_MEASUREMENT_NHM 0XF5 // command trig. hum. meas. no hold master
#define USER_REGISTER_W 0XE6        // command writing user register
#define USER_REGISTER_R 0XE7            // command reading user register
#define SOFT_RESET 0XFE                 // command soft reset
//==============================================================================
// HOLD MASTER - SCL line is blocked (controlled by sensor) during measurement
// NO HOLD MASTER - allows other I2C communication tasks while sensor performing
// measurements.

template<TwoWire &wire>
class SHT21
{
   public:
     float getHumidity(void)
    {
      uint16_t result;  // return variable

      result = readSensor_hm(TRIGGER_RH_MEASUREMENT_NHM);

      return CalcRH(result);
    }

    float getTemperature(void)
    {
      uint16_t result;  // return variable

      result = readSensor_hm(TRIGGER_T_MEASUREMENT_NHM);

      return CalcT(result);
    }

    void reset()
    {
      wire.beginTransmission(I2C_ADD);
      wire.write(SOFT_RESET);
      wire.endTransmission();

      delay(15);  // wait for SHT to reset
    }

    uint8_t getSerialNumber(uint8_t return_sn)
    {

      uint8_t serialNumber[8];

      // read memory location 1
      wire.beginTransmission(I2C_ADD);
      wire.write(0xFA);
      wire.write(0x0F);
      wire.endTransmission();

      wire.requestFrom(I2C_ADD, 8);
      while (wire.available() < 8) {}

      serialNumber[5] = wire.read();  // read SNB_3
      wire.read();          // CRC SNB_3 not used
      serialNumber[4] = wire.read();  // read SNB_2
      wire.read();          // CRC SNB_2 not used
      serialNumber[3] = wire.read();  // read SNB_1
      wire.read();          // CRC SNB_1 not used
      serialNumber[2] = wire.read();  // read SNB_0
      wire.read();          // CRC SNB_0 not used

      // read memory location 2
      wire.beginTransmission(I2C_ADD);
      wire.write(0xFC);
      wire.write(0xC9);
      wire.endTransmission();

      wire.requestFrom(I2C_ADD, 6);
      while (wire.available() < 6) {}

      serialNumber[1] = wire.read();  // read SNC_1
      serialNumber[0] = wire.read();  // read SNC_0
      wire.read();          // CRC SNC_1/SNC_0 not used
      serialNumber[7] = wire.read();  // read SNA_1
      serialNumber[6] = wire.read();  // read SNA_0
      wire.read();          // CRC SNA_1/SNA_0 not used

      return serialNumber[return_sn];
    }
  private:

    uint16_t readSensor_hm(uint8_t command)
    {
      uint8_t checksum;
      uint8_t data[2];
      uint16_t result;
      uint8_t n = 0;
      uint8_t d;

      if (command == TRIGGER_RH_MEASUREMENT_HM || command == TRIGGER_RH_MEASUREMENT_NHM) d = 30;
      if (command == TRIGGER_T_MEASUREMENT_HM || command == TRIGGER_T_MEASUREMENT_NHM) d = 85;

      wire.beginTransmission(I2C_ADD);
      wire.write(command);
      wire.endTransmission();
      delay(d);
      wire.requestFrom(I2C_ADD, 3);

      while (wire.available() < 3)
      {
        delay(10);
        n++;
        if (n > 10) return 0;
      }

      data[0] = wire.read();  // read data (MSB)
      data[1] = wire.read();  // read data (LSB)
      checksum = wire.read(); // read checksum

      result = (data[0] << 8);
      result += data[1];

      if (CRC_Checksum (data, 2, checksum))
      {
        reset();
        return 1;
      }

      else return result;
    }

    float CalcRH(uint16_t rh)
    {

      rh &= ~0x0003;  // clean last two bits

      return (-6.0 + 125.0 / 65536 * (float)rh); // return relative humidity
    }

    float CalcT(uint16_t t)
    {

      t &= ~0x0003; // clean last two bits

      return (-46.85 + 175.72 / 65536 * (float)t);
    }

    uint8_t CRC_Checksum(uint8_t data[], uint8_t no_of_bytes, uint8_t checksum)
    {
      uint8_t crc = 0;
      uint8_t byteCtr;

      //calculates 8-Bit checksum with given polynomial
      for (byteCtr = 0; byteCtr < no_of_bytes; ++byteCtr)
      {
        crc ^= (data[byteCtr]);
        for (uint8_t bit = 8; bit > 0; --bit)
        {
          if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
          else crc = (crc << 1);
        }
      }
      if (crc != checksum) return 1;
      else return 0;
    }

};

Ein Beispiel mit Wire und Wire1

//==============================================================================
//    E - R A D I O N I C A . C O M,  H.Kolomana 6/A, Djakovo 31400, Croatia
//==============================================================================
// Project   :  SHT21 Arduino Library
// File      :  SHT21 Demo Arduino Example
// Author    :  e-radionica.com 2017
// Licence   :  Open-source ! 
//==============================================================================
//==============================================================================
// Use with any SHT21 breakout. Check ours: 
// https://e-radionica.com/en/sht21-humidity-and-temperature-sensor.html
// Shows temperature and humidity from SHT21 sensor in Serial monitor.
// If any questions, 
// just contact techsupport@e-radionica.com
//==============================================================================

#include "SHT21.h"  // include SHT21 library

SHT21<Wire> sht; 
SHT21<Wire1> sht1; 

float temp;   // variable to store temperature
float humidity; // variable to store hemidity

void setup() {
  Wire.begin();   // begin Wire(I2C)
  Wire1.begin();   // begin Wire1(I2C)
  Serial.begin(9600); // begin Serial
}

void loop() {

  temp = sht.getTemperature();  // get temp from SHT 
  humidity = sht.getHumidity(); // get temp from SHT

  Serial.print("Temp: ");     // print readings
  Serial.print(temp);
  Serial.print("\t Humidity: ");
  Serial.println(humidity);


  temp = sht1.getTemperature();  // get temp from SHT1
  humidity = sht1.getHumidity(); // get temp from SHT1

  Serial.print("Temp1: ");     // print readings
  Serial.print(temp);
  Serial.print("\t Humidity1: ");
  Serial.println(humidity);

  delay(85);  // min delay for 14bit temp reading is 85ms
}

Die Idee heißt:
Dependency Injection über Template Parameter.
Constuctor Injection würde auch gehen, wenn man denn einen solchen einführt.

Die Arduino-IDE bzw die Bibliotheken kennen standartmäßig keinen 328PB und darum gibt es keine unterstüzung für die zusätzliche Hardware des PB.
Darum mußt Du entweder einen Bibliothek für den PB finden oder selbst schreiben bzw die Zusatzhardware direkt in Deinem Sketch ansprechen.
Grüße Uwe

@Uwe

324 =! 328.

Ich werde wahrscheinlich das dann über Soft I2C lösen oder einen Multiplexer nehmen.
Eine Library zu schreiben / umzuschreiben oder das zu "Fuß" zu machen, dass übersteigt dann doch
meine Fertigkeiten.
Trotzdem herzlichen Dank für die Bemühungen !

maik_s:
Eine Library zu schreiben / umzuschreiben oder das zu "Fuß" zu machen, dass übersteigt dann doch
meine Fertigkeiten.

Ich habe keinen AtMega324PB und keinen Sensor SHT21, daher kann ich praktisch nichts probieren. Aber wenn ich MightyCore auf AtMega324PB stelle, kann ich ein Programm mit Wire1 kompilieren. Daher kann ich Dein Problem leider nicht erkennen.

maik_s:
Ich kann aber mit den Arduino Libs nicht auf das Device an den zweiten Port zugreifen - der zweite
I2C Anschluss wird nicht "angesprochen".

Welche Libs meinst Du? Es gibt sehr, sehr viele verschiedene teilweise mit gleichlautenden Namen!

In #1 sehe ich ein Beispiel mit einer Bibliothek für SHT21, die ganz offensichtlich mit Wire1 umgehen kann. Warum nutzt Du nicht diese?

Hab ich probiert - kein Erfolg.
Ich bekomme keine Daten vom Sensor - am "normalen" I2C Port läuft alles.
Mit meinen Latein bin ich am Ende - daher meine anderen Lösungsvorschläge.
Den Sensor kann man auch ohne Lib auslesen - ich muss mal sehen ob ich das schaffe.
Ansonsten bleibt nur einen anderen Sensor zu verwenden wo ich die Adresse ändern kann
oder eben Multiplexing / Soft I2C (ich bin eben kein Profi).
Ich wollte eben gern das nehmen was ich hier schon zu liegen habe.

Hast Du denn die angepasste Lib, die combie für Dich in #1 geschrieben hat, überhaupt benutzt und den Beispielcode von ihm dazu?

Gruß Tommy

Edit: @combie: Die Liblösung über Templates ist genial. Das ist eine Combielösung.

Edit: @combie: Die Liblösung über Templates ist genial. Das ist eine Combielösung.

Danke, für die Blumen.

Naja.... (auf die schnelle aus dem Ärmel geschüttelt)
Konnte nicht testen, hatte weder den µC noch diese Sensoren.
Schätze aber schon, dass das so funktioniert

Ehre, wem Ehre gebührt :wink:

Gruß Tommy

Ja, wie schon gesagt:
Schöne Blümchen!

Und: Ich fühle mich gebauchpinselt, wenn es gefällt.

Ein paar Dinge würde ich allerdings schon noch anders machen.....

  1. Den Wire Type per Template Parameter übergeben
  2. Die Wire Instanz per Konstruktor

Dann tuts das auch mit SoftI2C, TinyWire und sonstigen, solange sie das Wire Interface implementieren. Auf jedem Kesselchen, welcher irgendwie in den Arduino Zoo gehört. Zudem bleibt sich der Flashverbrauch etwas angenehmer.

Dass dann die Instanziierung irgendwie so aussieht:

SHT21<TwoWire> sht(Wire); // wenn man den Type kennt


SHT21<decltype(Wire1)> sht1(Wire1); // Type zur Kompilezeit ermitteln

Mit C++11 ist an der Stelle kein auto erlaubt, was die Sache vereinfachen würde, wenn dem so wäre.

Die Type Ermittlung ist nötig, weil es z.B. für den UNO kein TinyWire gibt, und so das Wort TinyWire dann nicht im Quellcode auftauchen darf.

#pragma once
#include <Wire.h>

//---------- Defines -----------------------------------------------------------
#define I2C_ADD 0x40  // I2C device address

//const uint16_t POLYNOMIAL = 0x131;  // P(x)=x^8+x^5+x^4+1 = 100110001
#define POLYNOMIAL  0x131u
//==============================================================================
#define TRIGGER_T_MEASUREMENT_HM 0XE3   // command trig. temp meas. hold master
#define TRIGGER_RH_MEASUREMENT_HM 0XE5  // command trig. hum. meas. hold master
#define TRIGGER_T_MEASUREMENT_NHM 0XF3  // command trig. temp meas. no hold master
#define TRIGGER_RH_MEASUREMENT_NHM 0XF5 // command trig. hum. meas. no hold master
#define USER_REGISTER_W 0XE6        // command writing user register
#define USER_REGISTER_R 0XE7            // command reading user register
#define SOFT_RESET 0XFE                 // command soft reset
//==============================================================================
// HOLD MASTER - SCL line is blocked (controlled by sensor) during measurement
// NO HOLD MASTER - allows other I2C communication tasks while sensor performing
// measurements.

template<typename WireType>
class SHT21
{
  public:
    SHT21(WireType &wire): wire(wire) {}
    float getHumidity(void)
    {
      uint16_t result;  // return variable

      result = readSensor_hm(TRIGGER_RH_MEASUREMENT_NHM);

      return CalcRH(result);
    }

    float getTemperature(void)
    {
      uint16_t result;  // return variable

      result = readSensor_hm(TRIGGER_T_MEASUREMENT_NHM);

      return CalcT(result);
    }

    void reset()
    {
      wire.beginTransmission(I2C_ADD);
      wire.write(SOFT_RESET);
      wire.endTransmission();

      delay(15);  // wait for SHT to reset
    }

    uint8_t getSerialNumber(uint8_t return_sn)
    {

      uint8_t serialNumber[8];

      // read memory location 1
      wire.beginTransmission(I2C_ADD);
      wire.write(0xFA);
      wire.write(0x0F);
      wire.endTransmission();

      wire.requestFrom(I2C_ADD, 8);
      while (wire.available() < 8) {}

      serialNumber[5] = wire.read();  // read SNB_3
      wire.read();          // CRC SNB_3 not used
      serialNumber[4] = wire.read();  // read SNB_2
      wire.read();          // CRC SNB_2 not used
      serialNumber[3] = wire.read();  // read SNB_1
      wire.read();          // CRC SNB_1 not used
      serialNumber[2] = wire.read();  // read SNB_0
      wire.read();          // CRC SNB_0 not used

      // read memory location 2
      wire.beginTransmission(I2C_ADD);
      wire.write(0xFC);
      wire.write(0xC9);
      wire.endTransmission();

      wire.requestFrom(I2C_ADD, 6);
      while (wire.available() < 6) {}

      serialNumber[1] = wire.read();  // read SNC_1
      serialNumber[0] = wire.read();  // read SNC_0
      wire.read();          // CRC SNC_1/SNC_0 not used
      serialNumber[7] = wire.read();  // read SNA_1
      serialNumber[6] = wire.read();  // read SNA_0
      wire.read();          // CRC SNA_1/SNA_0 not used

      return serialNumber[return_sn];
    }

  private:
    WireType &wire;

    uint16_t readSensor_hm(uint8_t command)
    {
      uint8_t checksum;
      uint8_t data[2];
      uint16_t result;
      uint8_t n = 0;
      uint8_t d;

      if (command == TRIGGER_RH_MEASUREMENT_HM || command == TRIGGER_RH_MEASUREMENT_NHM) d = 30;
      if (command == TRIGGER_T_MEASUREMENT_HM || command == TRIGGER_T_MEASUREMENT_NHM) d = 85;

      wire.beginTransmission(I2C_ADD);
      wire.write(command);
      wire.endTransmission();
      delay(d);
      wire.requestFrom(I2C_ADD, 3);

      while (wire.available() < 3)
      {
        delay(10);
        n++;
        if (n > 10) return 0;
      }

      data[0] = wire.read();  // read data (MSB)
      data[1] = wire.read();  // read data (LSB)
      checksum = wire.read(); // read checksum

      result = (data[0] << 8);
      result += data[1];

      if (CRC_Checksum (data, 2, checksum))
      {
        reset();
        return 1;
      }

      else return result;
    }

    float CalcRH(uint16_t rh)
    {

      rh &= ~0x0003;  // clean last two bits

      return (-6.0 + 125.0 / 65536 * (float)rh); // return relative humidity
    }

    float CalcT(uint16_t t)
    {

      t &= ~0x0003; // clean last two bits

      return (-46.85 + 175.72 / 65536 * (float)t);
    }

    uint8_t CRC_Checksum(uint8_t data[], uint8_t no_of_bytes, uint8_t checksum)
    {
      uint8_t crc = 0;
      uint8_t byteCtr;

      //calculates 8-Bit checksum with given polynomial
      for (byteCtr = 0; byteCtr < no_of_bytes; ++byteCtr)
      {
        crc ^= (data[byteCtr]);
        for (uint8_t bit = 8; bit > 0; --bit)
        {
          if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
          else crc = (crc << 1);
        }
      }
      if (crc != checksum) return 1;
      else return 0;
    }

};

maik_s:
Hab ich probiert - kein Erfolg.

Die Lib, welche ich modifiziert habe?
Sie sollte funktionieren.
Irgendwelche Gegenanzeigen kann ich nicht erkennen.

Hmmm ....
Ist mit den Pullup alles in Ordnung?

Ich würde jetzt bei mir zuhause, mit einem LA und Oszi die Signale untersuchen, ob und wo es klemmt.
Und reichlich Debugausgaben in die Lib streuen.

Leider sehe ich nicht, was du getan hast.....

Ich will nicht unhöflich sein - aber am WE ist bei mir die Zeit knapp.
Daher auch meine verhaltene Reaktion auf die hier geleistete Hilfe.
Im allgemeinen liegt mir die Hardware mehr als die Software (dass sieht man auch in meinen Beiträgen).
In der Woche nach Feierabend ist mehr Zeit und da werde ich mich mit dem Thema noch weiter beschäfftigen.
Pullups sind vorhanden - der I2C Scanner zeigt ja alle Devices/Adressen an.
Sorry, aber vor Mo. oder Die. werde ich es nicht schaffen weitere Neuigkeiten zu verkünden.
Ich denke, das Thema Wire1 ist auch für andere von Interesse - im Web gibt es zu diesen Thema genügend
Fragen und einige weichen dann auf Soft I2C oder Multiplexer aus.

maik_s:
Ich denke, das Thema Wire1 ist auch für andere von Interesse - im Web gibt es zu diesen Thema genügend
Fragen und einige weichen dann auf Soft I2C oder Multiplexer aus.

Das denke ich auch, weshalb ich viele Bibliotheken, die das unterstützen, erwartet hätte. Eine kurze Suche ergab aber, daß scheinbar alle von einer Quelle abgeschrieben haben. Zumindest konnte ich keine Unterstützung für Wire1 finden. Schon merkwürdig :confused:

Morgen ist Wartung, daher dann wohl bis Dienstag ... oder nie :wink:

Zumindest konnte ich keine Unterstützung für Wire1 finden. Schon merkwürdig :confused:

Das wundert mich eigentlich nicht.

Wire selber, ist ganz ok.
Aber die Integration in die Arduino Welt ist krank, schwer verletzt.
Es leidet unter den Spätfolgen der Geburt und den ersten Revisionen.
Das ist der Fluch der Simplifizierung.

Wirklich hilfreich wäre, wenn die verschiedensten Wire Inkarnationen ein gemeinsames Interface hätten.
Dann hätten es die Lib Ersteller viel leichter.

Ich habe jetzt noch einmal alles in Ruhe gemacht und die Lib oben eingebunden.
Fehlermeldung : SHT21.cpp:171:2: error: explicit instantiation of non-template type 'SHT21'
Außerdem fehlt oben in der Lib nach #include unter #pragma once`noch etwas - der Compiler meckert an dieser Stelle.
Ansosnsten keine Auswertung auf den zweiten Port über wire1 möglich.
Ich denke es liegt nur an der Library - der I2C Scanner läuft und zeigt auch beide Devices an.
Hier der Code vom Scanner (etwas modifizert entgegen dem Orginal für Mightycore mit AtMega324pb):

/* I2C SCANNER
Arduino Playground - I2cScanner

This sketch tests the standard 7-bit addresses
Devices with higher bit address might not be seen properly.
*/

#include <Wire.h>
#include <Wire1.h>

byte error, address;

int nDevices = 0;

void setup()
{
Wire1.begin();
Wire.begin();

Serial.begin(9600);
Serial.println("\nI2C Scanner");
}

void loop()
{

Serial.println("Scanning...");

for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.

Wire.beginTransmission(address);
error = Wire.endTransmission();

if (error == 0)
{
  Serial.print("I2C device found at first Port at address 0x");
  if (address<16) 
    Serial.print("0");
  Serial.print(address,HEX);
  Serial.println("  !");

  nDevices++;
}
else if (error==4) 
{
  Serial.print("Unknow error at address 0x");
  if (address<16) 
    Serial.print("0");
  Serial.println(address,HEX);
}    

}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");

for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.

Wire1.beginTransmission(address);
error = Wire1.endTransmission();

if (error == 0)
{
  Serial.print("I2C device found at second Port at address 0x");
  if (address<16) 
    Serial.print("0");
  Serial.print(address,HEX);
  Serial.println("  !");

  nDevices++;
}
else if (error==4) 
{
  Serial.print("Unknow error at address 0x");
  if (address<16) 
    Serial.print("0");
  Serial.println(address,HEX);
}    

}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");

delay(5000); // wait 5 seconds for next scan
}

EDIT:
Da hast du wahr!
Das einsame #include muss da weg.
Oder durch #include <Wire.h> ersetzt werden

PS:
Der neue Code Formatierer tötet die Spitzen Klammern im Programmtext!
#include <Wire.h>
wird zu

#include  

Ich versuchs nochmal:

Das erste Tab eine *.ino



 
//==============================================================================
//    E - R A D I O N I C A . C O M,  H.Kolomana 6/A, Djakovo 31400, Croatia
//==============================================================================
// Project   :  SHT21 Arduino Library
// File      :  SHT21 Demo Arduino Example
// Author    :  e-radionica.com 2017
// Licence   :  Open-source ! 
//==============================================================================
//==============================================================================
// Use with any SHT21 breakout. Check ours: 
// https://e-radionica.com/en/sht21-humidity-and-temperature-sensor.html
// Shows temperature and humidity from SHT21 sensor in Serial monitor.
// If any questions, 
// just contact techsupport@e-radionica.com
//==============================================================================

#include "SHT21.h"  // include SHT21 library

SHT21<TwoWire> sht(Wire); // wenn man den Type kennt
SHT21<decltype(Wire1)> sht1(Wire1); // Type zur Kompilezeit ermitteln

//SHT21<Wire> sht; 
//SHT21<Wire1> sht1; 

float temp;   // variable to store temperature
float humidity; // variable to store hemidity

void setup() {
  Wire.begin();   // begin Wire(I2C)
  Wire1.begin();   // begin Wire1(I2C)
  Serial.begin(9600); // begin Serial
}

void loop() {

  temp = sht.getTemperature();  // get temp from SHT 
  humidity = sht.getHumidity(); // get temp from SHT

  Serial.print("Temp: ");     // print readings
  Serial.print(temp);
  Serial.print("\t Humidity: ");
  Serial.println(humidity);


  temp = sht1.getTemperature();  // get temp from SHT1
  humidity = sht1.getHumidity(); // get temp from SHT1

  Serial.print("Temp1: ");     // print readings
  Serial.print(temp);
  Serial.print("\t Humidity1: ");
  Serial.println(humidity);

  delay(85);  // min delay for 14bit temp reading is 85ms
}


Das 2te Tab, die SHT21.h

#pragma once
#include <Wire.h>

//---------- Defines -----------------------------------------------------------
#define I2C_ADD 0x40  // I2C device address

//const uint16_t POLYNOMIAL = 0x131;  // P(x)=x^8+x^5+x^4+1 = 100110001
#define POLYNOMIAL  0x131u
//==============================================================================
#define TRIGGER_T_MEASUREMENT_HM 0XE3   // command trig. temp meas. hold master
#define TRIGGER_RH_MEASUREMENT_HM 0XE5  // command trig. hum. meas. hold master
#define TRIGGER_T_MEASUREMENT_NHM 0XF3  // command trig. temp meas. no hold master
#define TRIGGER_RH_MEASUREMENT_NHM 0XF5 // command trig. hum. meas. no hold master
#define USER_REGISTER_W 0XE6        // command writing user register
#define USER_REGISTER_R 0XE7            // command reading user register
#define SOFT_RESET 0XFE                 // command soft reset
//==============================================================================
// HOLD MASTER - SCL line is blocked (controlled by sensor) during measurement
// NO HOLD MASTER - allows other I2C communication tasks while sensor performing
// measurements.

template<typename WireType>
class SHT21
{
   public:
   SHT21(WireType &wire):wire(wire){}
     float getHumidity(void)
    {
      uint16_t result;  // return variable

      result = readSensor_hm(TRIGGER_RH_MEASUREMENT_NHM);

      return CalcRH(result);
    }

    float getTemperature(void)
    {
      uint16_t result;  // return variable

      result = readSensor_hm(TRIGGER_T_MEASUREMENT_NHM);

      return CalcT(result);
    }

    void reset()
    {
      wire.beginTransmission(I2C_ADD);
      wire.write(SOFT_RESET);
      wire.endTransmission();

      delay(15);  // wait for SHT to reset
    }

    uint8_t getSerialNumber(uint8_t return_sn)
    {

      uint8_t serialNumber[8];

      // read memory location 1
      wire.beginTransmission(I2C_ADD);
      wire.write(0xFA);
      wire.write(0x0F);
      wire.endTransmission();

      wire.requestFrom(I2C_ADD, 8);
      while (wire.available() < 8) {}

      serialNumber[5] = wire.read();  // read SNB_3
      wire.read();          // CRC SNB_3 not used
      serialNumber[4] = wire.read();  // read SNB_2
      wire.read();          // CRC SNB_2 not used
      serialNumber[3] = wire.read();  // read SNB_1
      wire.read();          // CRC SNB_1 not used
      serialNumber[2] = wire.read();  // read SNB_0
      wire.read();          // CRC SNB_0 not used

      // read memory location 2
      wire.beginTransmission(I2C_ADD);
      wire.write(0xFC);
      wire.write(0xC9);
      wire.endTransmission();

      wire.requestFrom(I2C_ADD, 6);
      while (wire.available() < 6) {}

      serialNumber[1] = wire.read();  // read SNC_1
      serialNumber[0] = wire.read();  // read SNC_0
      wire.read();          // CRC SNC_1/SNC_0 not used
      serialNumber[7] = wire.read();  // read SNA_1
      serialNumber[6] = wire.read();  // read SNA_0
      wire.read();          // CRC SNA_1/SNA_0 not used

      return serialNumber[return_sn];
    }
    
  private:
   WireType &wire;
   
    uint16_t readSensor_hm(uint8_t command)
    {
      uint8_t checksum;
      uint8_t data[2];
      uint16_t result;
      uint8_t n = 0;
      uint8_t d;

      if (command == TRIGGER_RH_MEASUREMENT_HM || command == TRIGGER_RH_MEASUREMENT_NHM) d = 30;
      if (command == TRIGGER_T_MEASUREMENT_HM || command == TRIGGER_T_MEASUREMENT_NHM) d = 85;

      wire.beginTransmission(I2C_ADD);
      wire.write(command);
      wire.endTransmission();
      delay(d);
      wire.requestFrom(I2C_ADD, 3);

      while (wire.available() < 3)
      {
        delay(10);
        n++;
        if (n > 10) return 0;
      }

      data[0] = wire.read();  // read data (MSB)
      data[1] = wire.read();  // read data (LSB)
      checksum = wire.read(); // read checksum

      result = (data[0] << 8);
      result += data[1];

      if (CRC_Checksum (data, 2, checksum))
      {
        reset();
        return 1;
      }

      else return result;
    }

    float CalcRH(uint16_t rh)
    {

      rh &= ~0x0003;  // clean last two bits

      return (-6.0 + 125.0 / 65536 * (float)rh); // return relative humidity
    }

    float CalcT(uint16_t t)
    {

      t &= ~0x0003; // clean last two bits

      return (-46.85 + 175.72 / 65536 * (float)t);
    }

    uint8_t CRC_Checksum(uint8_t data[], uint8_t no_of_bytes, uint8_t checksum)
    {
      uint8_t crc = 0;
      uint8_t byteCtr;

      //calculates 8-Bit checksum with given polynomial
      for (byteCtr = 0; byteCtr < no_of_bytes; ++byteCtr)
      {
        crc ^= (data[byteCtr]);
        for (uint8_t bit = 8; bit > 0; --bit)
        {
          if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
          else crc = (crc << 1);
        }
      }
      if (crc != checksum) return 1;
      else return 0;
    }

};


Danke - meckert aber noch : 'SHT21' is not a template.

sketch_apr13b:3:1: error: 'SHT21' is not a template
SHT21 sht(Wire); // wenn man den Type kennt
^~~~~
sketch_apr13b:3:24: error: no matching function for call to 'SHT21::SHT21(TwoWire&)'
SHT21 sht(Wire); // wenn man den Type kennt

Keine Ahnung was an der Lib noch fehlt.

Da fehlt nichts!
Es benutzt weiter die alte Lib, nicht meine Änderung.
Hast du die Datei in einem Tab untergebracht!
Und auch so eingebunden, wie ich es gezeigt habe?

Falsch:

SHT21 sht(Wire); // wenn man den Type kennt

Richtig:

 SHT21<TwoWire> sht(Wire); // wenn man den Type kennt