I²C Pins umschalten

Hallo,

ich müßte jetzt erst nachschauen oder testen, was bei einem neuen Aufruf von Wire.begin([SDA], [SCL]) passiert. Vermutlich initialisiert er I2C mit den neuen Pins, problematisch kann werden, daß nicht klar ist, welchen Status die alten Pins haben. Die müßten auf jeden Fall dann als Input gesetzt sein/werden.

Ein Wire.end() hat, soweit ich sehe, keiner eingebaut obwohl es beim ESP durchaus Sinn machen würde.
Fehlt mir auch gerade bei SD-Card und Filesystem fehlt sowas auch, ich werde eine eingebundene SD-Karte beim ESP32 nicht wieder los und das belegt diverse kB Ram, die gerne wieder hätte.

Beim BME280 könnte man ohne I2C-Mux vielleicht tricksen, das kosten aber 2 Pin für I2C und 6 weitere für die Selection. Die Adressumschaltung der BME jeweils auf einen I/O, einen so aktiv, daß der BME Adresse 0x76 hat und alle anderen 0x77. Den messen und dann auf 0x77 schalten und den nächsten auf 0x76.

Zur Bool-Diskussion: sie hilft dem TO wenig, aber:
für die Lesbarkeit des Codes wäre bool hier sinnvoller, darin stimme ich combie zu.
Den richtigen Datentyp zu nehmen hat auch den Vorteil, daß der Compiler bei Typprüfungen warnen bzw. Fehler melden kann, die sonst gern übersehen werden.

Gruß aus Berlin
Michael

gregorss:
PS/BTW: Ich habe mal auf die Schnelle nach Beispielcode gesucht, in dem für bool-Kram Integer benutzt werden. Ich habe keinen gefunden.

ich habe das mit der Pin Initialisierung verwechselt. Da sind die IDE Bsp. mit int statt mit (const) byte. Sorry.
Ansonsten bin ich auch dafür passende Datentypen zu verwenden. Erhöht die Lesbarkeit.

Nachtrag:

Ein 'Verbinden' mehrerer Bool zu einem Byte wäre mir ebenfalls noch nicht aufgefallen - lasse mich aber hier sehr gerne belehren - wäre doch toll, wenn der Kompiler hier Platz vor Geschwindigkeit stellt. (wobei auf ein einzelnes Bit Prüfen nun auch nicht sooo zeitintensiv ist - zumindest in 'Maschinennähe')

Kein Problem!
Belehrung folgt auf dem Fuße:

class MitBitfeld
{
  public:
    bool a:1;
    bool b:1;
    bool c:1;
    bool d:1;
};

class OhneBitfeld
{
  public:
    bool a;
    bool b;
    bool c;
    bool d;
};

void setup() 
{
  Serial.begin(9600);
  Serial.print("MitBitfeld: ");Serial.println(sizeof(MitBitfeld));
  Serial.print("OhneBitfeld: ");Serial.println(sizeof(OhneBitfeld));
}

void loop() 
{

}

Ausgabe:

MitBitfeld: 1
OhneBitfeld: 4

ich werde eine eingebundene SD-Karte beim ESP32 nicht wieder los und das belegt diverse kB Ram, die gerne wieder hätte.

Ja, es ist eine Marotte, auf kleinen µC alles global zu definieren.

Würde man den C++ üblichen Weg beschreiten, und die Dinge, welche man wieder verwerfen möchte, per new zu erzeugen, dann hätte man diese Probleme nicht.
(aber dafür andere)

Auch Serial, Wire, SPI, usw. tragen das Problem in sich, oder mit sich rum.

Beispiel:
Eine beliebige Sensor Lib verwendet "Wire".
Alles gut..
Aber jetzt möchte man die selbe Lib mit "Wire1" nutzen.
Und nun?
Geht nicht!
Weil das vom Lib Schreiber so nicht vorgesehen wurde.

Die Lösung für solche Probleme hat sogar einen Namen:
"Dependency injection design pattern"

Noch mein Senf zur bool / int diskussion:

gregorss:
in Beispielen, die als Start- oder Orientierungshilfe gegeben werden, sollte man doch wenigstens halbwegs ordentlich programmieren. Für einen ja/nein-Kram eine Integer-Variable zu benutzen halte ich für hochgradigen Pfusch und Stümperei.

PS/BTW: Ich habe mal auf die Schnelle nach Beispielcode gesucht, in dem für bool-Kram Integer benutzt werden. Ich habe keinen gefunden.

Öffne die Arduino IDE, Beispiele - Basics - BlinkWithoutDelay

BlinkWithoutDelay:
int ledState = LOW;

Da es in diesem wertvollen Beispiel um was anderes geht als int / uint8_t / bool / boolean, würde ich zwar das Qualitätskriterium “halbwegs ordentlich” nicht so rigoros aberkennen, zumal auch später die Logik eher so formuliert ist, dass es für Anfänger möglichst verständlich ist und robust auf Modifikationen reagiert
( überflüssige Klammern … )

Diskussionswürdiger finde ich die Datentypen der Rückgabewerte / Parameter von digalRead / digitalWrite.

auto result = digitalRead(0);
if (sizeof(result) == 1) Serial.println(" Das wäre schön ");
digitalWrite(LED_BUILTIN, INPUT_PULLUP);  // Quizz - was passiert?

Leider keine Fehlermeldung über einen falschen Parameter Typ

Leider keine Fehlermeldung über einen falschen Parameter Typ

Dabei wäre das in der Planungsphase noch leicht zu realisieren gewesen.

Jetzt ist es ein gewachsenes System.

michael_x:
Noch mein Senf zur bool / int diskussion:
Öffne die Arduino IDE, Beispiele - Basics - BlinkWithoutDelay
Da es in diesem wertvollen Beispiel um was anderes geht als int / uint8_t / bool / boolean, würde ich zwar das Qualitätskriterium "halbwegs ordentlich" nicht so rigoros aberkennen, zumal auch später die Logik eher so formuliert ist, dass es für Anfänger möglichst verständlich ist und robust auf Modifikationen reagiert

Was dieses bool/int-Ding angeht, bin ich allergisch. Ich finde halt, dass man gerade in Code, der beispielhaft sein soll, die „richtigen“ Datentypen verwenden soll. Wie sonst (zur Hölle ...) soll das jemand lernen?!

Naja ... Schwamm drauf bzw. scheiß drüber. Manchmal finde ich, dass ich Papst sein sollte :slight_smile:

Schönen Sonntach!

Gregor

Manchmal finde ich, dass ich Papst sein sollte :slight_smile:

Im nachhinein ist gut, dass Rio Reiser doch nicht König von Deutschland war.


Im Beispielcode BlinkWithoutDelay wird der richtige Datentyp verwendet, das ist Teil des Problems.

digitalRead liefert ein int und digitalWrite erwartet int als Wert. Soll BlinkWithoutDelay da Verwirrung stiften?

Durch diese Definition ergibt sich, dass

volatile byte x;  // oder bool oder int ?
void setup() {
  x = digitalRead(0);
}
void loop() { }

der "optimale" Code ist, auch wenn ich noiasca (kacke) auf keinen Fall Recht geben möchte.

Übersetzt für einen Uno ergibt sich:

FLASH RAM
byte 646 10
bool 648 10
int 662 11

Der Rückgabewert muss bei bool noch unnötigerweise auf true/false gemapt werden.
int ist sowieso "kacke", weil da beide bytes des Ergebnis-Worts gespeichert werden.

michael_x:
... das ist Teil des Problems.
digitalRead liefert ein int und digitalWrite erwartet int als Wert. Soll BlinkWithoutDelay da Verwirrung stiften?

Jein :slight_smile: Die Datentypen der Rückgabe bzw. Parameter sind in diesem Fall IMO ein übler Designfehler. Sowas sollte man beheben können (und das auch tun), ohne dass jemand leiden müsste.

Gruß

Gregor

Hallo alle,

ich habe alle eure Beiträge mit Interesse gelesen, mann lernt ja dabei immer etwas.

Aber zurück zum eigentlichen Thema.

Ich habe es mit zwei Bme280 ausprobiert.

Wire.begin(4, 5);
    if (!bme.begin()) {
      Serial.println("Keinen BME280 Sensor gefunden! 4&5");
    }
     bme.read(pres, temp, hum, tempUnit, presUnit);
...........

Wire.begin(12, 5);
    if (!bme.begin()) {
      Serial.println("Keinen BME280 Sensor gefunden! 12&5");
    }
     bme.read(pres1, temp1, hum1, tempUnit, presUnit);
..........

Beide Bme280 im Sekundentakt abgefragt.

Serielle Ausgabe:

Wire.begin(4, 5) 72.14% 22.11°C 1020.14hPa
Wire.begin(12, 5) 67.13% 24.13°C 1020.01hPa
Wire.begin(4, 5) 72.32% 22.11°C 1020.14hPa
Wire.begin(12, 5) 66.64% 24.13°C 1020.01hPa
Wire.begin(4, 5) 72.05% 22.10°C 1020.13hPa
Wire.begin(12, 5) 67.33% 24.13°C 1020.00hPa
Wire.begin(4, 5) 72.26% 22.11°C 1020.20hPa
Wire.begin(12, 5) 67.44% 24.13°C 1020.07hPa
Wire.begin(4, 5) 72.30% 22.10°C 1020.13hPa
Wire.begin(12, 5) 67.98% 24.13°C 1020.00hPa
Wire.begin(4, 5) 72.18% 22.10°C 1020.13hPa
Wire.begin(12, 5) 66.86% 24.14°C 1020.00hPa
Wire.begin(4, 5) 72.44% 22.11°C 1020.15hPa
Wire.begin(12, 5) 67.71% 24.13°C 1020.02hPa
Wire.begin(4, 5) 72.47% 22.11°C 1020.11hPa
Wire.begin(12, 5) 67.12% 24.14°C 1019.98hPa
Wire.begin(4, 5) 72.29% 22.11°C 1020.20hPa
Wire.begin(12, 5) 67.22% 24.13°C 1020.07hPa
Wire.begin(4, 5) 72.52% 22.10°C 1020.13hPa
Wire.begin(12, 5) 67.06% 24.14°C 1020.00hPa
Wire.begin(4, 5) 72.21% 22.10°C 1020.13hPa
Wire.begin(12, 5) 66.96% 24.14°C 1020.00hPa
Wire.begin(4, 5) 72.22% 22.10°C 1020.18hPa
Wire.begin(12, 5) 66.16% 24.13°C 1020.05hPa
Wire.begin(4, 5) 72.20% 22.10°C 1020.16hPa
Wire.begin(12, 5) 66.81% 24.13°C 1020.03hPa
Wire.begin(4, 5) 72.31% 22.10°C 1020.10hPa
Wire.begin(12, 5) 66.54% 24.13°C 1019.97hPa
Wire.begin(4, 5) 72.34% 22.10°C 1020.19hPa
Wire.begin(12, 5) 66.96% 24.13°C 1020.06hPa
Wire.begin(4, 5) 72.14% 22.12°C 1020.10hPa
Wire.begin(12, 5) 66.74% 24.13°C 1019.97hPa

Gruß Fips

Hallo,

scheint also zu klappen wenn ich Dich richtig verstehe?
Laß Dir mal dazwischen den freien Heap ausgeben ob der Kram halbwegs sauber wieder freigegeben wird.

Bei Wire.begin(4, 5) reicht auch nur Wire.begin(), GPIO4 und 5 sind Default I2C beim ESP8266 in der ArduinoIDE.

Lies die BME nicht so oft aus, die (Chip-)Temperatur weicht dann generell nach oben ab. Außerdem hat ein nicht wirklich belasteter AMS1117 in 2cm Abstanf ür rund +2 Grad gesorgt.

Feuchte ist bei meinen BME erst nach mehreren Stunden sinnvoll stabil wenn man nur in der Nähe von den Teilen war.

Gerade mal nach meinen Balkonsensoren geschaut:
FOST02 (HopeRF, 8 Jahre alt) T: 21,1 Grad, F: 72%
BME280 (China, 1 Jahr alt) T: 12,1 Grad, F: 71%

Temperatur zwischen beiden max. 0,5 Grad auseinander, Feuchte bis ca. 60% +- 5%, darüber geht der vor.
Über 95% brauchen beide ein paar Stunden bis sie wieder "zu sich gekommen" sind.
Wundergroud sagt 20 Grad und 70% irgendwo hier in der Gegend.

Ich brauche da auch nicht wirklich irgendwelche sonderlichen Genauigkeiten.

Gruß aus Berlin
Michael

Derfips:
Ich habe es mit zwei Bme280 ausprobiert.

Und offensichtlich ist es so, wie uns Derfips zeigt, es funktioniert doch.
Wohl aber nur mit einer angepassten Wire-Library, oder ?

Man lernt ja nie aus, danke.

HotSystems:
Und offensichtlich ist es so, wie uns Derfips zeigt, es funktioniert doch.
Wohl aber nur mit einer angepassten Wire-Library, oder ?

Man lernt ja nie aus, danke.

Die Wire-Lib ist original.

Hallo,

HotSystems:
Und offensichtlich ist es so, wie uns Derfips zeigt, es funktioniert doch.
Wohl aber nur mit einer angepassten Wire-Library, oder ?

Man lernt ja nie aus, danke.

Der ESP kann im Gegensatz zum AVR die I2C-Hardware auf nahezu alle Pins mappen.
Die Erweiterung von Wire.begin() mit Pinangabe ist meines Wissens nach extra deshalb eingebaut worden.
Ich bin beim ESP nur immer etwas unsicher, ob alle Resourcen der alten Zuweisung sauber freigegeben werden.
Bei ESP32 sorgt das durchaus noch für einige Überraschungen.

Gruß aus Berlin
Michael

Dann muss ich meine hier rumliegenden Wemos doch endlich mal aktivieren.
Jetzt erst recht. :wink:

Danke euch beiden.

Ich bin beim ESP nur immer etwas unsicher, ob alle Resourcen der alten Zuweisung sauber freigegeben werden.

Es werden keine Ressourcen "verwaltet"

Die ESP8266 I2C Implementierung ist eine klassische Software I2C Implementierung.
Das alles liegt bei jedem Arduino-ESP8266 Nutzer im Quellcode vor.

Die Neugier kann also rundrum zufriedenstellend befriedigt werden.
Man muss nur hinschauen.

Wire
twi.h
SoftTwi

Hallo,

combie:
Es werden keine Ressourcen "verwaltet"

Die ESP8266 I2C Implementierung ist eine klassische Software I2C Implementierung.
Das alles liegt bei jedem Arduino-ESP8266 Nutzer im Quellcode vor.

Die Neugier kann also rundrum zufriedenstellend befriedigt werden.
Man muss nur hinschauen.

Stimmt. Problem dabei: ich schau in die Core-Sourcen meist erst dann, wenn ich entweder ein Problem damit habe oder wenn es etwas exotisches ist, was mich interessiert.
Wenn es erwartungsgemäß funktioniert, begnüge ch mich meist mit der Doku der Aufrufe. :wink:

Gruß aus Berlin
Michael

Moin,

wer hätte das gedacht, das sich hier so ein Nebenschauplatz eröffnet?!
Naja, egal… ich hab einfach das “int” gegen “bool” im Sketch getauscht und war damit fertig. Funktioniert genauso.

Hier nun mein Sketch, mit dem ich inzwischen sogar 8 Sensoren in 4 Gruppen abfrage:

#include <Wire.h>
#include "BlueDot_BME280.h"
BlueDot_BME280 bme1;                                     //Object for Sensor 1
BlueDot_BME280 bme2;                                     //Object for Sensor 2
bool bme1Detected = 0;                                    //Checks if Sensor 1 is available
bool bme2Detected = 0;                                    //Checks if Sensor 2 is available
void InitSensor() {  
  bme1.parameter.communication = 0;                    //I2C communication for Sensor 1 (bme1)
  bme2.parameter.communication = 0;                    //I2C communication for Sensor 2 (bme2)
  bme1.parameter.I2CAddress = 0x76;                    //I2C Address for Sensor 1 (bme1)
  bme2.parameter.I2CAddress = 0x77;                    //I2C Address for Sensor 2 (bme2)
  bme1.parameter.sensorMode = 0b11;                    //Setup Sensor mode for Sensor 1
  bme2.parameter.sensorMode = 0b11;                    //Setup Sensor mode for Sensor 2
  bme1.parameter.IIRfilter = 0b100;                    //IIR Filter for Sensor 1
  bme2.parameter.IIRfilter = 0b100;                    //IIR Filter for Sensor 2
  bme1.parameter.humidOversampling = 0b101;            //Humidity Oversampling for Sensor 1
  bme2.parameter.humidOversampling = 0b101;            //Humidity Oversampling for Sensor 2
  bme1.parameter.tempOversampling = 0b101;             //Temperature Oversampling for Sensor 1
  bme2.parameter.tempOversampling = 0b101;             //Temperature Oversampling for Sensor 2
  bme1.parameter.pressOversampling = 0b101;            //Pressure Oversampling for Sensor 1
  bme2.parameter.pressOversampling = 0b101;            //Pressure Oversampling for Sensor 2
  bme1.parameter.pressureSeaLevel = 1013.25;           //default value of 1013.25 hPa (Sensor 1)
  bme2.parameter.pressureSeaLevel = 1013.25;           //default value of 1013.25 hPa (Sensor 2)
  bme1.parameter.tempOutsideCelsius = 15;              //default value of 15°C
  bme2.parameter.tempOutsideCelsius = 15;              //default value of 15°C
  bme1.parameter.tempOutsideFahrenheit = 59;           //default value of 59°F
  bme2.parameter.tempOutsideFahrenheit = 59;           //default value of 59°F
  bme1.init();
  bme2.init();
}
void setup() {
  Serial.begin(9600);
}
void loop() {
  Wire.begin(2,5); //2 as SDA and 5 as SCL, Sensoren 1+2
  InitSensor();
  Serial.println();
  Serial.print(F("\tTemperature[C]:  "));
  Serial.print(F("Humidity[%]:  "));
  Serial.println(F("Pressure [hPa]:"));
  Serial.print(F("Sensor 1:     "));
  Serial.print(bme1.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme1.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme1.readPressure());
  delay(7500);
  Serial.print(F("Sensor 2:     "));
  Serial.print(bme2.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme2.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme2.readPressure());
  delay(7500);
  Wire.begin(0,5); //0 as SDA and 5 as SCL, Sensoren 3+4
  InitSensor();
  Serial.print(F("Sensor 3:     "));
  Serial.print(bme1.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme1.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme1.readPressure());
  delay(7500);
  Serial.print(F("Sensor 4:     "));
  Serial.print(bme2.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme2.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme2.readPressure());
  delay(7500);
  Wire.begin(4,5); //4 as SDA and 5 as SCL, Sensoren 5+6
  InitSensor();
  Serial.print(F("Sensor 5:     "));
  Serial.print(bme1.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme1.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme1.readPressure());
  delay(7500);
  Serial.print(F("Sensor 6:     "));
  Serial.print(bme2.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme2.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme2.readPressure());
  delay(7500);
  Wire.begin(14,5); //14 as SDA and 5 as SCL, Sensoren 7+8
  InitSensor();
  Serial.print(F("Sensor 7:     "));
  Serial.print(bme1.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme1.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme1.readPressure());
  delay(7500);
  Serial.print(F("Sensor 8:     "));
  Serial.print(bme2.readTempC());
  Serial.print(F("\t\t"));
  Serial.print(bme2.readHumidity());
  Serial.print(F("\t\t"));
  Serial.println(bme2.readPressure());
  delay(7500);
}

Geht bestimmt auch schöner und aufgeräumter, aber das soll ja nur ein Test auf dem Breadboard über einige Tage oder wenige Wochen von den Sensoren gegeneinander sein und keine Dauerinstallation, die man Pflegen können möchte.

Funktionieren tut es, ob ich mir aber den Speicher oder so vollmülle weiß ich nicht.
Nun werde ich noch die Übergabe an die Datenbank einbauen und denn kann der Testbetrieb beginnen.

Gibt’s noch Verbesserungsvorschläge, die sinnvoll sind?

Lieben Gruß und lieben Dank für die angeregte Diskussion :slight_smile: ,
Chris

Haben die Werte (besonders für die eigentlich gewollten Ergebnisse), die Du in InitSensor() setzt eigentlich einen tieferen Sinn?

Gruß Tommy

Moin Tommy,

keine Ahnung, die kommen original aus dem Beispielsketch zu der Library, die ich für meine Zwecke eingedampft habe soweit ich konnte.
Ich habe die Werte mal testweise weggelassen, dann lieferten die Sensoren keine Daten mehr.
Ich denke die Library ist so aufgebaut, dass man alle Einstellungen der Sensoren editieren kann, aber dennoch braucht sie die Daten, egal ob defaultwerte oder modifizierte Werte.
Diese Werte im Sketch sind die defaultwerte.
Der Vollständigkeitshalber hier auch das Beispielsketch aus der BlueDot_BME280.h Library:

/***************************************************************************
  Example for BME280 Weather Station using two Sensors with I2C Communication
  written by Thiago Barros for BlueDot UG (haftungsbeschränkt)
  BSD License

  This sketch was written for the Bosch Sensor BME280.
  The BME280 is a MEMS device for measuring temperature, humidity and atmospheric pressure.
  For more technical information on the BME280, please go to ------> http://www.bluedot.space

 ***************************************************************************/


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

BlueDot_BME280 bme1;                                     //Object for Sensor 1
BlueDot_BME280 bme2;                                     //Object for Sensor 2

int bme1Detected = 0;                                    //Checks if Sensor 1 is available
int bme2Detected = 0;                                    //Checks if Sensor 2 is available


void setup() {
  Serial.begin(9600);
  Serial.println(F("Basic Weather Station"));

  //*********************************************************************
  //*************BASIC SETUP - SAFE TO IGNORE**************************** 
  
  //This program is set for the I2C mode

    bme1.parameter.communication = 0;                    //I2C communication for Sensor 1 (bme1)
    bme2.parameter.communication = 0;                    //I2C communication for Sensor 2 (bme2)
    

  
  //*********************************************************************
  //*************BASIC SETUP - SAFE TO IGNORE****************************
    
  //Set the I2C address of your breakout board  

    bme1.parameter.I2CAddress = 0x77;                    //I2C Address for Sensor 1 (bme1)
    bme2.parameter.I2CAddress = 0x76;                    //I2C Address for Sensor 2 (bme2)

    
  
  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE*************************
    
  //Now choose on which mode your device will run
  //On doubt, just leave on normal mode, that's the default value

  //0b00:     In sleep mode no measurements are performed, but power consumption is at a minimum
  //0b01:     In forced mode a single measured is performed and the device returns automatically to sleep mode
  //0b11:     In normal mode the sensor measures continually (default value)
  
    bme1.parameter.sensorMode = 0b11;                    //Setup Sensor mode for Sensor 1
    bme2.parameter.sensorMode = 0b11;                    //Setup Sensor mode for Sensor 2 


                  
  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE*************************
  
  //Great! Now set up the internal IIR Filter
  //The IIR (Infinite Impulse Response) filter suppresses high frequency fluctuations
  //In short, a high factor value means less noise, but measurements are also less responsive
  //You can play with these values and check the results!
  //In doubt just leave on default

  //0b000:      factor 0 (filter off)
  //0b001:      factor 2
  //0b010:      factor 4
  //0b011:      factor 8
  //0b100:      factor 16 (default value)

    bme1.parameter.IIRfilter = 0b100;                   //IIR Filter for Sensor 1
    bme2.parameter.IIRfilter = 0b100;                   //IIR Filter for Sensor 2

    

  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE*************************

    //Next you'll define the oversampling factor for the humidity measurements
  //Again, higher values mean less noise, but slower responses
  //If you don't want to measure humidity, set the oversampling to zero

  //0b000:      factor 0 (Disable humidity measurement)
  //0b001:      factor 1
  //0b010:      factor 2
  //0b011:      factor 4
  //0b100:      factor 8
  //0b101:      factor 16 (default value)

    bme1.parameter.humidOversampling = 0b101;            //Humidity Oversampling for Sensor 1
    bme2.parameter.humidOversampling = 0b101;            //Humidity Oversampling for Sensor 2

    

  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE*************************
  
  //Now define the oversampling factor for the temperature measurements
  //You know now, higher values lead to less noise but slower measurements
  
  //0b000:      factor 0 (Disable temperature measurement)
  //0b001:      factor 1
  //0b010:      factor 2
  //0b011:      factor 4
  //0b100:      factor 8
  //0b101:      factor 16 (default value)

    bme1.parameter.tempOversampling = 0b101;              //Temperature Oversampling for Sensor 1
    bme2.parameter.tempOversampling = 0b101;              //Temperature Oversampling for Sensor 2

    

  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE*************************
  
  //Finally, define the oversampling factor for the pressure measurements
  //For altitude measurements a higher factor provides more stable values
  //On doubt, just leave it on default
  
  //0b000:      factor 0 (Disable pressure measurement)
  //0b001:      factor 1
  //0b010:      factor 2
  //0b011:      factor 4
  //0b100:      factor 8
  //0b101:      factor 16 (default value)  

    bme1.parameter.pressOversampling = 0b101;             //Pressure Oversampling for Sensor 1
    bme2.parameter.pressOversampling = 0b101;             //Pressure Oversampling for Sensor 2 

     
  
  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE*************************
  
  //For precise altitude measurements please put in the current pressure corrected for the sea level
  //On doubt, just leave the standard pressure as default (1013.25 hPa);
  
    bme1.parameter.pressureSeaLevel = 1013.25;            //default value of 1013.25 hPa (Sensor 1)
    bme2.parameter.pressureSeaLevel = 1013.25;            //default value of 1013.25 hPa (Sensor 2)

  //Also put in the current average temperature outside (yes, really outside!)
  //For slightly less precise altitude measurements, just leave the standard temperature as default (15°C and 59°F);
  
    bme1.parameter.tempOutsideCelsius = 15;               //default value of 15°C
    bme2.parameter.tempOutsideCelsius = 15;               //default value of 15°C
  
    bme1.parameter.tempOutsideFahrenheit = 59;            //default value of 59°F
    bme2.parameter.tempOutsideFahrenheit = 59;            //default value of 59°F

  
    
  //*********************************************************************
  //*************ADVANCED SETUP IS OVER - LET'S CHECK THE CHIP ID!*******

Teil2 wegen 9000 Zeichen Limit:

  if (bme1.init() != 0x60)
  {    
    Serial.println(F("Ops! First BME280 Sensor not found!"));
    bme1Detected = 0;
  }

  else
  {
    Serial.println(F("First BME280 Sensor detected!"));
    bme1Detected = 1;
  }

  if (bme2.init() != 0x60)
  {    
    Serial.println(F("Ops! Second BME280 Sensor not found!"));
    bme2Detected = 0;
  }

  else
  {
    Serial.println(F("Second BME280 Sensor detected!"));
    bme2Detected = 1;
  }

  if ((bme1Detected == 0)&(bme2Detected == 0))
  {
    Serial.println();
    Serial.println();
    Serial.println(F("Troubleshooting Guide"));
    Serial.println(F("*************************************************************"));
    Serial.println(F("1. Let's check the basics: Are the VCC and GND pins connected correctly? If the BME280 is getting really hot, then the wires are crossed."));
    Serial.println();
    Serial.println(F("2. Did you connect the SDI pin from your BME280 to the SDA line from the Arduino?"));
    Serial.println();
    Serial.println(F("3. And did you connect the SCK pin from the BME280 to the SCL line from your Arduino?"));
    Serial.println();
    Serial.println(F("4. One of your sensors should be using the alternative I2C Address(0x76). Did you remember to connect the SDO pin to GND?"));
    Serial.println();
    Serial.println(F("5. The other sensor should be using the default I2C Address (0x77. Did you remember to leave the SDO pin unconnected?"));

    Serial.println();
    
    while(1);
  }
    
  Serial.println();
  Serial.println();

}

  //*********************************************************************
  //*************NOW LET'S START MEASURING*******************************
void loop() {
   
  Serial.print(F("Duration in Seconds:  "));
  Serial.println(float(millis())/1000);

  if (bme1Detected)
  {
    Serial.print(F("Temperature Sensor 1 [°C]:\t\t")); 
    Serial.println(bme1.readTempC());
    //Serial.print(F("Temperature Sensor 1 [°F]:\t\t"));            
    //Serial.println(bme1.readTempF());
    Serial.print(F("Humidity Sensor 1 [%]:\t\t\t")); 
    Serial.println(bme1.readHumidity());
    Serial.print(F("Pressure Sensor 1 [hPa]:\t\t")); 
    Serial.println(bme1.readPressure());
    Serial.print(F("Altitude Sensor 1 [m]:\t\t\t")); 
    Serial.println(bme1.readAltitudeMeter());
    //Serial.print(F("Altitude Sensor 1 [ft]:\t\t\t")); 
    //Serial.println(bme1.readAltitudeFeet());
    Serial.println(F("****************************************"));    
  }

  else
  {
    Serial.print(F("Temperature Sensor 1 [°C]:\t\t")); 
    Serial.println(F("Null"));
    //Serial.print(F("Temperature Sensor 1 [°F]:\t\t")); 
    //Serial.println(F("Null"));
    Serial.print(F("Humidity Sensor 1 [%]:\t\t\t")); 
    Serial.println(F("Null"));
    Serial.print(F("Pressure Sensor 1 [hPa]:\t\t")); 
    Serial.println(F("Null"));
    Serial.print(F("Altitude Sensor 1 [m]:\t\t\t")); 
    Serial.println(F("Null"));
    //Serial.print(F("Altitude Sensor 1 [ft]:\t\t\t")); 
    //Serial.println(F("Null"));
    Serial.println(F("****************************************"));   
  }

  if (bme2Detected)
  {
    Serial.print(F("Temperature Sensor 2 [°C]:\t\t")); 
    Serial.println(bme2.readTempC());
    //Serial.print(F("Temperature Sensor 2 [°F]:\t\t")); 
    //Serial.println(bme2.readTempF());
    Serial.print(F("Humidity Sensor 2 [%]:\t\t\t")); 
    Serial.println(bme2.readHumidity());
    Serial.print(F("Pressure Sensor 2 [hPa]:\t\t")); 
    Serial.println(bme2.readPressure());
    Serial.print(F("Altitude Sensor 2 [m]:\t\t\t")); 
    Serial.println(bme2.readAltitudeMeter());
    //Serial.print(F("Altitude Sensor 2 [ft]:\t\t\t")); 
    //Serial.println(bme2.readAltitudeFeet());    
  }

  else
  {
    Serial.print(F("Temperature Sensor 2 [°C]:\t\t")); 
    Serial.println(F("Null"));
    //Serial.print(F("Temperature Sensor 2 [°F]:\t\t")); 
    //Serial.println(F("Null"));
    Serial.print(F("Humidity Sensor 2 [%]:\t\t\t")); 
    Serial.println(F("Null"));
    Serial.print(F("Pressure Sensor 2 [hPa]:\t\t")); 
    Serial.println(F("Null"));
    Serial.print(F("Altitude Sensor 2 [m]:\t\t\t")); 
    Serial.println(F("Null"));
    //Serial.print(F("Altitude Sensor 2 [ft]:\t\t\t")); 
    //Serial.println(F("Null"));
  }
   
   Serial.println();
   Serial.println();

   delay(1000);
   
 
}