You are currently viewing Mehrere (viele!!) BH1750 am Arduino / ESP8266

Mehrere (viele!!) BH1750 am Arduino / ESP8266

Der BH1750 ist ein toller Heligkeitssensor, der über den I²C-Bus digital seine Werte ausschreibt.. Es gibt an dem BH1750 eien Addresspin, der (wenn er zum Aufstarten high oder low gelegt wird) die Adresse des Sensors für den I²C vorgibt. Es ist als möglich, zwei BH1750 an einem I²C-Bus zu betreiben. EInen mit High-Pegel auf dem Adresspin und einen mit Low-Pegel auf dem Adress-Pin. Die Adressen sind dann 0x23 und 0x5C.

Desweiteren kann die Genauigkeit der Daten vorgegeben werden. Dies macht dann Sinn, wenn die Abfragegeschwindigkeit hoch sein soll (hohe Abfrageraten bei kleinerer Genauigkeit und umgekehrt). Wolle hat dazu einen schönen Artikel geschrieben.

Wer aber mehr als zwei Sensoren betreiben möchte, und nicht mehrere I²C-Bussysteme aufbauen möchte, muss sich etwas einfallen lassen.

Mein erster Versuch scheiterte, als ich versucht habe mit einem 8-Bit Schieberegister (IC sn74hc595n) den Adresspin jeweils HIGH zu setzen, und dann die Abfrage zu starten. Das geht nicht, da der Adresspin des BH1750 zum Start des Moduls sein Niveau haben muss und nicht unter Spannung wechseln kann. Aber grundsätzlich machen Schieberegister schon Spaß am Arduino 😉 – Hier ein schönes Video dazu:

Zurück zum eigentlichen Problem und dessen Lösung.

Grundsätzlich war nämlich die Abfrage nacheinander schon eine gute Idee, aber eben nicht mit dem Umschalten der Adresspins, sondern mit der Datenleitung! Die SDA des I²C immer auf den auszulesenden BH1750 zu legen funktioniert nämlich tadellos. Dann kann jeder Chip immer die Adresse behalten und wird nacheinander abgefragt. Klatt gut mit einem Multiplexer!

Ich habe es mit einem „sn74hc4051n“ aufgebaut und es läuft. Geholfen hat mit dabei dieses Video:

Der Autor „Mark Ahn“ beschreibt in seinem Blog „/blog.naver.com/ysahn2k/“ diese Methode… Leider behersche ich die Schriftzeichen nicht 😉
Daher hier meine Zusammenfassung mit einigen Tipps!

Der Aufbau:

Ich beschreibe hier erst einmal den Grundlegenden Aufbau. Später gehe ich auf ein paar Extras ein.
Wie gesagt verwende ich
– einen Multiplexer „sn74hc4051n
– eine ESP 8266 NodeMCU – (Ich beschreibe auch die Differenzen zwischen Arduino Nano und NodeMCU)
– ein 2×16 LCD-Display
– und später einen Portextender PCF8574 (Siehe hier)
Mark Ahn beschreibt die Nutzung eine OLED-Dispays… Das tut aber nichts zur Sache.. Hier geht es ja um die Sensoren.

Schaltplan / Schema von blog.navar

Grundsätzlich brauchen wir für die 8-Bit-Adressierung des Multiplexers drei GPIOs. Wie oben zu sehen werden zum Beispiel die GPIO D5, D6 und D/ auf die Eingänge A, B und C des Multiplexers zur Addressierung gelegt.
Den SDA aus aus dem Arduino (bei einem ESP8266 NODEMCU V3 sind die SDA und SCL die Pins D2 und D1!) legen wir auf den IO-Null-Port des Multiplexers. Wir wollen ja den Datenstrom vom BH1750 und vom Arduino durch den Multiplexer an den richtigen Sensor senden.
Die IO-1 bis IO-8-Ports können wir dann mit den SDA der Sensoren verbinden. SCL als Clocksignal geben wir direkt und immer auf die Sensoren und (wer mag) auf ein Display. Das Display kann dann auch direkt mit dem SDA verbuden werden. Ich habe zusätzlich (oben nicht im Schema enthalten, aber im Netz gut dokumentiert, – z.B. hier) zwei Pull-Up-Wiederstände auf den I²C-Bus gelegt. Also immer 3,3V über je einen 10K-Ohm-Wiederstand auf die SDA und einen auf die SCL gelegt. Das erhöht die Zuverlässigkeit, wenn man etwas Leitungslänge braucht.
Alle Adresspins legen wir auf Masse – So haben alle Sensoren als Adresse die 0x23. Jetzt noch Spannungsversorgung an die Sensoren und den Multiplexer. Bei dem Arduino Nano kein Ding, Aber Obacht! Die BH1750 vertragen sowohl 3,3V, als auch 5V… Die GPIOS des ESP8266NodeMCU-V3 mögen keine 5V! Entweder arbeitet Ihr mit den 3,3V aus dem Bord, oder ihr müsst Pegelwandler einsetzen. Ich habe mit 3,3V gute Erfahrungen gemacht.
Am Ende sollte es dann ungefähr so aussehen:

Beschaltung Arduino – ESP8266 bitte mit SDA und SCL auf D2 und D1

SOFTWARE:

Wie oben schon mehrfach angerissen. Es gibt unterschiede zwischen Arduinos und ESP NodeMCUs. Nachfolgendes Script ist für ein Arduino!

//    Aufbau:
//
//    VCC -> 3V3 or 5V
//    GND -> GND
//    SCL -> SCL (A5 auf Arduino Uno, auf esp8266 D1)
//    SDA -> SDA (A4 auf Arduino Uno, auf esp8266 D2)
//
//    ADD pin der Sensoren auf GND, damit die Adressen aller Sensoren immer auf 0x23 bleiben
 include  <Wire.h>    // für die generelle Kommunikation der Pins
 include  <BH1750.h>  //Für BH1750-Sensor
 
 // Messmethoden!!! Nachfolgend bitte die Messmethode festlegen - Es geht hauptsächlich um die Geschwindigkeit des Rohdatens.
 // Wert 0x10 ergibt Messung mit 1Lux-Genauigkeit - ermöglicht Messung in  120ms
 // Wert 0x11 ergibt Messung mit 0,5Lux-Genauigkeit - ermöglicht Messung in  120ms
 // Wert 0x13 ergibt Messung mit 4Lux-Genauigkeit - ermöglicht Messung in  16ms
 // Wert 0x20 ergibt Messung mit 1Lux-Genauigkeit - ermöglicht Messung in  120ms
 // Wert 0x21 ergibt Messung mit 1Lux-Genauigkeit - ermöglicht Messung in  120ms
 // Wert 0x23 ergibt Messung mit 4Lux-Genauigkeit - ermöglicht Messung in  16ms
 define RES_MODE 0x10  // Messung mit 1Lux-Genauigkeit - ermöglicht Messung in 120ms
 // I2C Addresse
 define BH1750Adresse 0x23  // Sensoren auf GND
 // LED auf dem Bord festlegen - Status-LED
 define LED_PIN 13
 // Definition der Multiplexerports !!! ACHTUNG !!! BEI ESP8266NODEMCUS müssen hier die Pins mit einem D beschrieben Werden - Also D5, D6, D7 usw.!!
 int16_t s_en = 4;     // Der Enable-Port 
 int16_t s0 = 5;        // Der Adressieungspin A am Multiplexer
 int16_t s1 = 6;        // Der Adressieungspin B am Multiplexer
 int16_t s2 = 7;        // Der Adressieungspin C am Multiplexer
 int16_t RawData;    //Die Rohdaten aus dem Sensor zurück
 int16_t SensorValue[4]; //Anzahl der Sensoren am Multiplexer - Maximal 8! Bei einem Multiplexer - Gern Mehr mit mehreren
 boolean blinkState = false;
 void setup() {
   Wire.begin();
   Serial.begin(115200); // Baud Rate
 pinMode(s_en, OUTPUT);        //Initialisieren der Pins als Ausgänge für den Enable-Switch
   pinMode(s0, OUTPUT);            //Initialisieren der Pins als Ausgänge für den Adresseingang A
   pinMode(s1, OUTPUT);            //Initialisieren der Pins als Ausgänge für den Adresseingang B
   pinMode(s2, OUTPUT);            //Initialisieren der Pins als Ausgänge für den Adresseingang C
 digitalWrite(s_en, HIGH);        //Auf High legen für die Initialisierung (nicht zwingend erforderlich
   digitalWrite(s0, HIGH);
   digitalWrite(s1, HIGH);
   digitalWrite(s2, HIGH);
 pinMode(LED_PIN, OUTPUT);
   digitalWrite(LED_PIN, HIGH);
 }
 void loop() {
 digitalWrite(s_en, LOW); // Einschalten des Multiplexers / Durchschalten der Daten
 for(int i = 0; i < 4; i++){         //Anzahl der Sensoren eintragen - Hier sind 4 eingetragen
     Auslesen(i);                    // Untenstehende Funktion "Auslesen" aufrufen und Daten zurückbekommen
 init_BH1750(BH1750Adresse, RES_MODE);  // Daten in gewünschter Auflösung abrufen delay(120); RawData_BH1750(BH1750Adresse); SensorValue[i] = RawData / 1.2;  // Schreiben der Daten in die vier Variablen delay(20);
 }
 Serial.print("Sensor_1 = "); Serial.print(SensorValue[0]); //Log-Schreiben für die Sensoren 
   Serial.print(" | Sensor_2 = "); Serial.print(SensorValue[1]);
   Serial.print(" | Sensor_3 = "); Serial.print(SensorValue[2]);
   Serial.print(" | Sensor_4 = "); Serial.println(SensorValue[3]);
 blinkState = !blinkState;
   digitalWrite(LED_PIN, blinkState);
 }  //Ende des Loops
 // Initialisieren der Sensoren
 void init_BH1750(int ADDRESS, int MODE){
   //BH1750 Initializing & Reset
   Wire.beginTransmission(ADDRESS);
   Wire.write(MODE);  // PWR_MGMT_1 register
   Wire.endTransmission(true);
 }
 // Abruf
 void RawData_BH1750(int ADDRESS){
   Wire.beginTransmission(ADDRESS);
   Wire.requestFrom(ADDRESS,2,true);  // Abruf der zwei Registereinträge
   RawData = Wire.read() << 8 | Wire.read();  // Lesen der Rohdaten des BH1750
   Wire.endTransmission(true);
 }
 // Setzen der Adressen am Multiplexer. Als Schleife durch die acht Möglichkeiten. Je nach Anzahl der Sensoren.
 int Auslesen(int channel) { 
   int controlPin[] = {s0, s1, s2}; 
   int muxChannel[8][3] = { 
     {0,0,0}, //channel 0 
     {1,0,0}, //channel 1 
     {0,1,0}, //channel 2 
     {1,1,0}, //channel 3 
     {0,0,1}, //channel 4 
     {1,0,1}, //channel 5 
     {0,1,1}, //channel 6 
     {1,1,1}, //channel 7  //Schleife durch die Signale
   };
   for(int i = 0; i < 3; i++){ // Setzen der drei GPIOs für die Adressierung des Multiplexers
     digitalWrite(controlPin[i], muxChannel[channel][i]); 
   }   
 }

Bitte nicht vergessen, die Bibliotheken vorher zu laden und das passende Board einzustellen;)

Der Nächste Schritt ist das Einbinden des WLAN und des Displays… das folgt in den kommenden Tagen! Viel Spaß beim Basteln

Dieser Beitrag hat 2 Kommentare

  1. Axel Schmidt

    Hallo,
    I2C ist eigentlich nicht für längere Strecken ausgelegt. Mit je einem P82B96 kann man aber doch bis zu 100 m erreichen (getestet im Prüflabor!). Wenn dann noch I2C-Multiplexer genutzt werden, wird der Aufbau doch schnell größer und könnte den Anforderungen genügen.

    1. msp

      Sory, der Post ist mir untergegangen :$ … Danke für den Tipp

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.