I2C Sensor + Relais Board = Code wird nicht ausgeführt

Hallo Zusammen,

Ich benötige eure Hilfe, bei der Umsetzung der Schaltung oder des Codes. Ich bin mir hier leider nicht sicher auf weclher Grundlage der Fehler zustande kommt.

ich habe für meine Bewässerungssteuerung einen ESP32 in Benutzung, welcher über ein Relaisboard die jeweiligen HUNTER Ventile steuert. Dies geschieht in Abhängigkeit eines Bodenfeuchtigkeitssensors, welcher über die I2C Schnittstelle die entsprechenden Daten liefert. Da im Livebetrieb die Leitung des Bodensensors ca. 10m ist, habe ich für die beiden Datenleitungen einen Pullup Widerstand der Schaltung hinzugefügt. Die Werte werden so ohne Fehler geliefert.

Situation:
Beim Starten des ESP32 werden alle Pins (3 Pins für 3 Ventile) auf LOW gesetzt. --> Damit die Magnetventile nicht geschaltet werden. Dies funkioniert ohne die Pullupwiderstände für den Sensor einwandfrei!. Nun benötige ich aber für die Daten des Sensors die Widerstände da dieser sonst nicht liefert. Wenn diese beim booten an VDD liegen, werden die Relais aber nicht auf LOW gezogen. Das Programm bleibt gefühlt stehen. Erst beim entfernen der Widerstände läuft das Programm wie gewünscht weiter. Danach kann ich die Widerstände wieder setzen und trotzdem alle Relais wie gewünscht steuern.

Das Problem was sich dadurch ergibt:
Sollte es zu einem Stromausfall kommen, würden alle Bewässerungsventile angehen und ich würde dies nicht mitbekommen, da der ESP nicht wie gewünscht bootet und die Relais -Pins entsprechend schaltet!

Was habe ich getetstet:
Den Code mit einem "Delay" ergänzt, da ich dachte das durch die Widerstände die Spannung für das Relaisboard nicht ausreicht und ich die Pins, nicht gleichzeitig sondern nacheinader schalte. --> Hat nicht funktioniert
Das Relay mit einer extra 5V Spannung versorgt --> Hat nicht funktioniert!

Leider weiß ich hier nicht weiter und würde mich freuen, wenn ihr mir einen Tipp geben könnt, wie dies Zustande kommt.

Dies ist meiner erster Post und ich hoffe das ich den nachfolgenden Code richtig hier einfüge...

#include <WiFi.h>
#include <Wire.h>

#define relay1 27 // Grau
#define relay2 26 // Lila
#define relay3 25 // Orange
#define relay4 33 // Gelb
#define relay5 32 // Blau
#define relay6 13 // Grün

//define SDA_0 27
//#define SCL_0 26
//#define I2C_Freq 100000

//TwoWire I2C_0 = TwoWire(0);

//const char* wifi_name = "wifi"; // Your Wifi network name here
//const char* wifi_pass = "12345678";    // Your Wifi network password here
const char* wifi_name = "wifi2"; // Your Wifi network name here
const char* wifi_pass = "12345678";    // Your Wifi network password here



int val1 = 0;
int val2 = 0;
int val3 = 0;
//int val4 = 0;
//int val5 = 0;
//int val6 = 0;

WiFiServer server(80);    // Server will be at port 80

//int relay_pin = 2;

void setupI2C()      //call once 
{
    Wire.begin(12,14);           // join i2c bus as master
}
int SoMoSe_getAveragedSensorValue(int Adr)
{
  int value;
  int dump;

  //Wire.beginTransmission(byte(Adr));  // transmit to device
  Wire.beginTransmission(byte(Adr));  // transmit to device
  Wire.write(byte(0x76));         // command read value
  Wire.endTransmission();         // stop transmitting

  delay(1);                   // maybe some delay is required

  Wire.requestFrom(byte(Adr), (byte)2);     // request 2 bytes from slave device 
  if (2 <= Wire.available())    // if two bytes were received
  { 
      value = Wire.read();    
        dump = Wire.read(); 
  }
  return value;
}

char SoMoSe_getTemperatureValue(int Addr)
{
    signed char value;

    Wire.beginTransmission(byte(Addr));
    Wire.write(byte(0x74));
    Wire.endTransmission();

    delay(1);

    Wire.requestFrom(byte(Addr), (byte)1);    // request 1 byte from slave device
    if (1 <= Wire.available())
    {
        value = Wire.read();
    }
    return value;
}

void setup() {
  Serial.begin (115200);

  pinMode(relay1, OUTPUT);
  digitalWrite(relay1, LOW); // HIGH makes open circuit at relay  // Attempt WIFI Connect
  delay (500);
  pinMode(relay2, OUTPUT);
  digitalWrite(relay2, LOW);
  delay (500);
  pinMode(relay3, OUTPUT);
  digitalWrite(relay3, LOW);
  delay (500);
  //pinMode(relay4, OUTPUT);
  //digitalWrite(relay4, LOW);
  //delay (500);
  //pinMode(relay5, OUTPUT);
  //digitalWrite(relay5, LOW);
  //delay (500);
  //pinMode(relay6, OUTPUT);
  //digitalWrite(relay6, LOW);

  Serial.println("Feuchtigkeitssensor");

  setupI2C();

  Serial.print ("Connecting to ");
  Serial.print (wifi_name);
  WiFi.begin (wifi_name, wifi_pass);     // Connecting to the wifi network

  while (WiFi.status() != WL_CONNECTED) // Waiting for the response of wifi network
  {
    delay (1000);
    Serial.print (".");
  }
  Serial.println("");
  Serial.println("WLAN Verbindung hersgestellt");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());           // Getting the IP address
  Serial.println("Type the above IP address into browser search bar"); 
  server.begin();                           // Starting the server

  


} 

void loop() {
   WiFiClient client = server.available(); // listen for incoming clients

  if (client) {
    String currRequestLine = ""; // buffer for the incoming request
    int lineCount = 0;
    String firstLine;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n') {
          lineCount++;
         
          // read request header (first line)
          if (lineCount == 1) {
            firstLine = currRequestLine;
            Serial.println(firstLine);
          }
          
          if (currRequestLine.length() == 0) {
            // request end
            sendResponse(firstLine, client);
            break;
          } else {
            currRequestLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currRequestLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // close the connection:
    client.stop();
  }
}
        
  void sendResponse(String reqFirstLine, WiFiClient client) {
  if (reqFirstLine == "GET / HTTP/1.1") {
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println();

    // send minified index.html file
    //client.print("<!DOCTYPE html><html><head><title>ESP32 Sensor</title><style type=\"text/css\">.box {width: 100px;height: 100px;margin: 0 auto;padding: 2.5px;position: relative;box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.24);}.point {width: 5px;height: 5px;margin-left: -2.5px;margin-top: -2.5px;background: red;border-radius: 50%;position: relative;}</style></head><body><main><div class=\"box\"><div class=\"point\"></div></div><div class=\"time\"></div></main><script src=\"https://code.jquery.com/jquery-3.2.1.min.js\" integritysha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=\" crossorigin=\"anonymous\"></script><script type=\"text/javascript\">(function(jQuery) {let box = jQuery('.box'), time = jQuery('.time'), point = jQuery('.point');function updatePoint() {jQuery.ajax({url: 'http://"+host+"/sensor',type: 'GET',success: (res) => {point.css({ 'left': res.x * box.width(), 'top': res.y * box.height() });time.html(res.time);setTimeout(updatePoint, 10);},error: () => {setTimeout(updatePoint, 1000);}})}updatePoint();})(jQuery);</script></body></html>");
  }
  //Humidity Request
  else if (reqFirstLine == "GET /humidity HTTP/1.1") {
    // response header
    int hum = SoMoSe_getAveragedSensorValue(0x01);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();

    // send sensor data in JSON format
   // client.print("{\"Bodenfeuchtigkeit\":" + String(hum) + "},");
    Serial.println(hum);
  }

  //Temperature Request
  else if (reqFirstLine == "GET /temperature HTTP/1.1") {
    // response header
    int temp = SoMoSe_getTemperatureValue(0x01);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();

    // send sensor data in JSON format
   // client.print("{\"Bodentemperatur\":" + String(temp) + "},");
    Serial.println(temp);
  }
  
// Relay Steuerung
  else if (reqFirstLine == "GET /relay1=1 HTTP/1.1") {
    // response header
    digitalWrite(relay1, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r1 On\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay1=0 HTTP/1.1") {
    // response header
    digitalWrite(relay1, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r1 Off\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay2=1 HTTP/1.1") {
    // response header
    digitalWrite(relay2, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r2 On\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay2=0 HTTP/1.1") {
    // response header
    digitalWrite(relay2, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r2 Off\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay3=1 HTTP/1.1") {
    // response header
    digitalWrite(relay3, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r3 On\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay3=0 HTTP/1.1") {
    // response header
    digitalWrite(relay3, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r3 Off\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay4=1 HTTP/1.1") {
    // response header
    digitalWrite(relay4, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r4 On\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay4=0 HTTP/1.1") {
    // response header
    digitalWrite(relay4, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r4 Off\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay5=1 HTTP/1.1") {
    // response header
    digitalWrite(relay5, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r5 On\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay5=0 HTTP/1.1") {
    // response header
    digitalWrite(relay5, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r5 Off\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relay6=1 HTTP/1.1") {
    // response header
    digitalWrite(relay6, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r6 On\"}");  delay(1);
  }

else if (reqFirstLine == "GET /relay6=0 HTTP/1.1") {
    // response header
    digitalWrite(relay6, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
    //client.println("{\"status\":\"r6 Off\"}");  delay(1);
  }

  else if (reqFirstLine == "GET /relayall=1 HTTP/1.1") {
    // response header
    digitalWrite(relay1, LOW);
    digitalWrite(relay2, LOW);
    digitalWrite(relay3, LOW);
    digitalWrite(relay4, LOW);
    digitalWrite(relay5, LOW);
    digitalWrite(relay6, LOW);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
  }

  else if (reqFirstLine == "GET /relayall=0 HTTP/1.1") {
    // response header
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    digitalWrite(relay3, HIGH);
    digitalWrite(relay4, HIGH);
    digitalWrite(relay5, HIGH);
    digitalWrite(relay6, HIGH);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: application/json");
    client.println();
  }

  else {
    // 404 not found
    client.println("HTTP/1.1 404 Not Found");
    client.println("Content-Type: text/html");
    client.println();
    client.print("This page is not available.");
  }

  val1 = digitalRead(relay1);
  val2 = digitalRead(relay2);
  val3 = digitalRead(relay3);
  val4 = digitalRead(relay4);
  val5 = digitalRead(relay5);
  val6 = digitalRead(relay6);
  int hum = SoMoSe_getAveragedSensorValue(0x01);
  int temp = SoMoSe_getTemperatureValue(0x01);
  float humwert =((float)hum/256)*100;
  client.println("{\"Bodenfeuchtigkeit\":" + String(hum) + ",\"BodenfeuchtigkeitProzent\":" + String(humwert) + ",\"Bodentemperatur\":" + String(temp) + ",\"statusR1\":" + String(val1) + ",\"statusR2\":" + String(val2) + ",\"statusR3\":" + String(val3) + ",\"statusR4\":" + String(val4) + ",\"statusR5\":" + String(val5) + ",\"statusR6\":" + String(val6) + "}");  delay(1); 

  client.println();
}

Hallo und willkommen,
was für einen Sensor verwendest du ? Bitte einen Link posten.
I2C ist ein Onboard-Datenbus der nur für kurze Verbindungen auf Platinen entwickelt wurde. Da sind 10m deutlich zu viel. Allein nur mit den Pullup-Widerständen wirst du keinen Erfolg haben. Evtl. funktioniert es mit I2C-Busextender (P82B715).

Das liegt dann vermutlich an dem nicht funktionierenden I2C-Bus.

Hallo,

laut dem Entwickler ist dies kein Problem. Der Sensor ist dieser...

Mit den Widerständen funktioniert der Sensor bei der Länge ja auch exakt genauso wie mit 20cm Jumperkabel.

Wenn ich den ESP ohne Widerstände starte, läuft alles wie gewünscht durch. Danach verbinde ich die Pullup Widerstände und kann alle Relais + den Sensor wie gewünscht nutzen. Der Fehler bzw. die Herausforderung ist nur das booten mit der eingestellten Konfiguration! Im Prinzip könnte ich nach dem booten die Widerstände einfach hinzufügen und wäre glücklich. Das Szenario des Stromausfalls wäre aber sehr problematisch, da die Ventile dann alle geschaltet werden und das Wasser läuft und läuft... diesen Zustand will und muss ich irgendwie vermeiden.

vermutlich deine Pullups ziehen zu viel Strom von schwachen 3.3V Regulator und das ist dann nicht genug Spannung um ESP selbst störungsfrei zu betreiben. ansonsten kann man Relaypin auf INPUT schalten sodas Modul nicht aktiviert ist.

Nur komischer weise schreibt der das nicht in der Beschreibung

Du kannst machen egal wie und was du willst es wird ohne Extender nicht funktionieren, hol dir noch paar ESP den mit zu kleinen Pullup kannst die Pins in Nirwana schicken
Lese dich mal schlau für was wurde I²C entwickelt, und wie der Bus funktioniert.
Und schreibe nicht das es funktioniert, hätte vernünftig funktioniert stand hier kein Beitrag

1 Like

Hallo Kolaha,

ich denke der Gedankenanstoß war genau der richtige. Im Testaufbau lief der Code durch.
Die I2C Pin's habe ich vor den Relais auf INPUT gesetzt und danach wieder auf OUTPUT.

So haben die Widerstände keinen Einfluss gehabt bis die Relais Ihren Zustand erhalten. haben.

Danke und Viele Grüße

@ Fony: Der Support seitens des Entwicklers ist als hervorragend zu bezeichen. Es wird auf alle Fragen eingegangen, welche vielleicht nicht aus der Dokumentation hervorgehen. In diesem Fall...was die Länge der Anschlüsse betrifft zum Beispiel!

Dan sollte der Schlaumeier die Doku für I²C lesen und nicht Unsinn reden.
Hauptsache Verkauft und bei beschwerde, nachfrage irgend was behauptet

Sehr nützlicher Beitrag von dir. Deine Art zu Antworten, ist weder hilfreich, noch passt es zu dem positiven Niveau dieses Forums. Wenn du keine hilfreichen Antworten zu Verfügung stellen möchtest dann spare dir die Zeit auf der Tastatur kryptische Sätze zu verfassen.
Wie auch immer deine theoretischen Ansätze aussehen. Der praktische Versuchsaufbau funktioniert wie gewünscht und damit ist die Lösung für mich vorhanden.

Kommentare

Dan Wünsche dir viel Erfolg. Es waren hier schon sehr viele beitrage wen es geht um Bus Lenge-
Persönlich habe getestet und am laufen gehabt mit 20m nur dafür habe vom NPX vorgesehenen Extender genutzt(P82B715).

Man kann sich auch komplett allen Datenblättern verweigern, so wie du es scheinbar machst. Die Datenblätter von I2C sagen alle was anderes und def. nicht, dass I2C mit 10m langem Kabel funktionieren. Es sei denn, man verwendet entsprechende Treiber dafür, die spez. für die Verwendung längerer Kabel entwickelt wurden. Davon sehe ich nichts bei dir und auch nicht in der Beschreibung des Sensors.
Und damit gebe ich dem doch hilfreichen Beitrag von @fony recht. Auch wenn du es ignorieren magst.
Auch wenn dein Aufbau kurzfristig funktioniert, wird er es im Dauerbetrieb sicher nicht ohne Probleme durchstehen.
Zumindest ist die von dir genannte Lösung kein Lösung deines I2C-Problems. Das wirst du sicher noch merken.

P.S.
Zeig uns doch bitte mal die Information, wo der Sensor am I2C mit 10m Kabel sicher funktioniert. Auch wir lernen gern dazu.

P.S.S
Interessant wäre noch die Größe deiner verwendeten Pullup-Widerstände.

Was mir grad noch auffällt, der GPIO 12 ist dein tatsächlich aktuelles Problem.
Der darf während des Bootens nicht auf HIGH gezogen werden.
Nimm da einen anderen GPIO.

Fazit: Datenblätter lesen und auch danach arbeiten. Dann gibt es def. weniger Probleme.

wie @HotSystems bereits angemerkt, hat, GPIO12 muss zum Starten low sein.
Hier habe ich eine Tabelle für den ESP32 aus der man Besonderheiten zu Pins rauslesen kann:

Was mir sonst noch so alles auffällt in deinem gezeigtem Sketch:

  • Warum verwendest nicht einfach die "Standard" I2C GPIOs 21/22?
  • Warum verwendest du nicht den WebServer am ESP32?
    #include <WebServer.h> (Beispiel Webserver / HelloServer) der erspart dir jedenfalls das manuelle Schreiben des HTTP Headers (die meist falsch sind).
  • Warum hast du so viele duplizierte Code Zeilen? Nutze doch Funktionen für Code-Teile die sich prinzipiell gleichen. Aber die meisten Zeilen bekommst schon weg, wenn du den Webserver verwendest.
  • Der Code kann eigentlich nicht kompilieren, du hast Variablen auskommentiert die aber später verwendet werden. Bei den Variablen fallen zwei Sachen auf: a) ist ein Variablenname von var? wenig beschreibend. Das solltest du schon so nennen was da drinnen wirklich steht. Z.B. pinStatus. Außerdem solltest du Arrays verwenden anstatt Variablennamen hochzuzählen. In den meisten Programmiersprachen beginnt man beim Zählen mit 0, nicht 1.
  • Auch aus relay1 - relay6 kannst du ein Array mit relay[6] machen.
  • int SoMoSe_getAveragedSensorValue(int Adr) - wozu übergibst du die Adr als int? Das führt dann dazu, dass du in der Funktion den Wert immer auf ein byte casten musst. Übergib der Funktion den Parameter gleich als byte - dann sparst du dir die casts. Außerdem wenns leicht geht, Funktionsnamen sollen mit einem kleinen Buchstaben beginnen.
  • aktiviere dir in der IDE Einstellung ALLE Warnungen ausgeben zu lassen. Dann weist dich der Compiler auch darauf hin, dass du z.B. die Variable nicht nutzt oder keine returnwerte setzt:
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_jul24c\sketch_jul24c.ino:42:7: warning: variable 'dump' set but not used [-Wunused-but-set-variable]
   int dump;
       ^~~~
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_jul24c\sketch_jul24c.ino:57:10: warning: 'value' may be used uninitialized in this function [-Wmaybe-uninitialized]
   return value;
          ^~~~~

Gute Angewohnheit wäre, lokale Variablen IMMER zu initialisieren, z.B. auf 0 zu setzen.

Wenn du bei einem der Punkte weitere Hilfe benötigst - gib bescheid.

1 Like

Also das Problem, das das Wasser nach einem Stromausfall Dauer läuft, ist m.M.n. einfach zu beheben.

Dazu muss man die Verbindung am Relais so ändern, dass es OHNE Befehl OFFEN ist, also KEIN Strom durchlässt. Wenn es sich bei den Relais um ein ky-019 Modell handelt, reicht es ein Kabel umzustecken.

Im Code muss man dann nur noch den "Schaltpin" auf HIGH setzen damit das Relais anzieht und den Stromfluss freigibt.

Lies dazu diese Seite.

Gruß

Pucki

@sj40

hab mir erlaubt mal deinen Sketch etwas zusammenzuräumen.

Das wäre der Main-Tab:

/*
    https://forum.arduino.cc/t/i2c-sensor-relais-board-code-wird-nicht-ausgefuhrt/1284590

    I2C Komponenten nicht getestest
    ESP32 WebServer funktioniert

    2024-07-24 by noiasca
*/

#include <WiFi.h>
#include <WebServer.h>                 // for the webserver
#include <Wire.h>

//#include <credentials.h>               // if you have an external file with your credentials you can use it - or comment this out

#ifndef STASSID                        // either use an external .h file containing STASSID and STAPSK - or 
#define STASSID "your-ssid"            // ... modify these line to your SSID
#define STAPSK  "your-password"        // ... and set your WIFI password
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

constexpr uint8_t circuits {6};        // wie viele Relaykreise hast
const uint8_t relayPin[circuits] {     // GPIO der einzelnen Relais
        27, // Grau
        26, // Lila
        25, // Orange
        33, // Gelb
        32, // Blau
        13  // Grün
};

const uint8_t sdaPin = 21;  // mostly used on ESP32 is 21
const uint8_t sclPin = 22;  // mostly used on ESP32 is 22

WebServer server(80);

void setupI2C() {    //call once
  Wire.begin(sdaPin, sclPin);          // join i2c bus as master
}

int soMoSe_getAveragedSensorValue(byte addr) {
  int value = 0;
  //int dump = 0;
  Wire.beginTransmission(addr);        // transmit to device
  Wire.write((byte)0x76);              // command read value
  Wire.endTransmission();              // stop transmitting
  delay(1);                            // maybe some delay is required
  Wire.requestFrom(addr, (byte)2);     // request 2 bytes from slave device
  // if two bytes were received
  if (2 <= Wire.available()) {
    value = Wire.read();
    //dump = Wire.read(); // ??
  }
  return value;
}

char soMoSe_getTemperatureValue(byte addr) {
  signed char value = 0;
  Wire.beginTransmission(addr);
  Wire.write(byte(0x74));
  Wire.endTransmission();
  delay(1);
  Wire.requestFrom(addr, (byte)1);    // request 1 byte from slave device
  if (1 <= Wire.available()) {        // should get improved
    value = Wire.read();
  }
  return value;
}

void setup() {
  Serial.begin (115200);
  for (auto &r : relayPin){
     pinMode(r, OUTPUT);
     delay(500); // wozu???
  }
  Serial.println("Feuchtigkeitssensor");
  setupI2C();
  // Connecting to the wifi network
  Serial.print ("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  // Waiting for the response of wifi network
  while (WiFi.status() != WL_CONNECTED) {
    delay (1000);
    Serial.print('.');
  }
  Serial.println();
  Serial.println("WLAN Verbindung hersgestellt");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());           // Getting the IP address
  Serial.println("Type the above IP address into browser search bar");
  
  server.on("/",      handlePage);          // send root page - in this sketch a JSON
  server.on("/humidity",      handlePage);  // special case here: also this page serves the full JSON
  server.on("/temperature",   handlePage);  // special case here: also this page serves the full JSON
  server.onNotFound(handleNotFound);        // show a typical HTTP Error 404 page
  server.begin();                           // Starting the server
}

void loop() {
  server.handleClient();               // call the webserver
}
//

für den Server legst einen neuen tab "server" an und kopierst das rein:

// Advice: check your generated HTML output if it is valid HTML: https://validator.w3.org
// *** HOME *** 
void handlePage() {
  String message;
  message.reserve(5000);

  // process relay1=0  ... needs some programming as the user starts counting with 1 instead of 0
  for (size_t i = 0; i < circuits; i++) {
    String parameter = "relay";
    parameter.reserve(8);
    parameter += i + 1; // dirty
    if (server.hasArg(parameter)) {
      int action = server.arg(parameter) == "1" ? HIGH : LOW;  // edit next day
      digitalWrite(relayPin[i], action);
    }
  }
  if (server.hasArg("relayall")) {
    int action = server.arg("relayall") == "1" ? HIGH : LOW;
    for (auto &r : relayPin)
      digitalWrite(r, action);
  }

  // generate output
  int hum = soMoSe_getAveragedSensorValue(0x01);
  int temp = soMoSe_getTemperatureValue(0x01);
  float humwert = ((float)hum / 256) * 100;
  message = "{\"Bodenfeuchtigkeit\":";
  message += hum;
  message += ",\"BodenfeuchtigkeitProzent\":";
  message += humwert;
  message += ",\"Bodentemperatur\":";
  message += temp;
  for (size_t i = 0; i < circuits; i++) {
    message += ",\"statusR";
    message += i + 1;     // Dirty: i beginnt mit 0, daher addieren wir hier für die Ausgabe eine 1. Besser man gewohnt sich an, dass man mit 0 beginnt!
    message += "\":";
    message += digitalRead(relayPin[i]);
  }
  message += "}";
  server.send(200, "application/json", message);
}

// Output a "404 not found" page. It includes the parameters which comes handy for test purposes.
void handleNotFound() {
  Serial.println(F("D52 handleNotFound()"));
  String message;
  message.reserve(5000);
  message += F("404 - File Not Found\n"
               "URI: ");
  message += server.uri();
  message += F("\nMethod: ");
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += F("\nArguments: ");
  message += server.args();
  message += F("\n");
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}
//

I2C kann ich nicht testen.
Der Server funktioniert so einwandfrei und hat auch nur mehr ein viertel der Zeilen und kann noch kürzer werden, wenn du akzeptierst, dass Programmierer mit 0 zu zählen beginnen.

  • die Resourcen /humidity und /temperature geben so wie bei dir das volle JSON aus. Man kann aber relativ leicht nach dem Muster jeweils separate Resourcen zur Verfügung stellen und nur den entsprechenden Wert ausgeben was meines Erachtens logischer wäre.
  • was jetzt auch klappt, man kann die Parameter auch kombiniert übergeben, z.B. ein /?relay1=0&relay3=0, will man das nicht, kann man ein break in der for Schleife setzen.

Guten Morgen Noiasca,

vielen Dank für deine Mühe und das bereitsstellen deiner Überarbeitung. Ich sehe es nicht als selbstversändlich an, dass du mir hier eine Lösung auf dem "Silbertablet" servierst. Danke für den Support!

Deine Lösung mit der Bilblothek für den Server ist natürlich um Welten besser, hat aber einfach meine "Möglichkeiten" im Umgang mit dem ESP32 und dem Zusammenbauen eines Sketches überstiegen und ich war froh ein irgendwie laufendes Programm aus diversen "Codeschnipseln" erstmal zum "Starten" zu bekommen.

Das ist also eine Menge sehr guter Input, den ich gerne umsetzen möchte.

Aktuelle Situation:
Nach dem Anschließen des Sensors und des Ralaisboards im Livebetrieb, hat es wie du bereits beschrieben und vermutet hast dann doch nicht funktioniert. Die I2C Pins (14,12) habe ich eher nach der Anordnung gewählt, da ich alle Anschlüsse an dem ESP auf einer Seite haben wollte. (Die Anordnung im Schaltschrank auf einem Breadboard war so günstiger!)

Der dann erfolgte Wechsel zurück auf die default I2C Pins hat das Problem sofort gelöst, so das der ESP wie gewünscht mit der Konfiguration aus Sensor + Pullup + Relaisboard gestartet ist und der Fehler nicht mehr auftritt!

Nun habe ich natürlich auch den überarbeiteten Sketch geladen und die Befehle an den Webserver geschickt.

Funktionieren tun die Abfragen für den Sensor (humidity,temperature), der Parameter "Relayall" und der Defaultaufruf der IP..Hier werden die Relaypins wie gewünscht geschaltet. Das was ich leider nicht hinbekomme sind die Befehle für die einzelnen Relays. Wenn ich IP/?relay1=0 eingebe, wird die JSON Antwort zurückgegeben, doch der pin nicht entsprechend geschaltet. Genauso natürlich für den Wert 1 und die anderen Relays, welche in dem Array definiert sind.

Wo liegt der Fehler hier bei mir, was habe ich übersehen?

Viele Grüße und vielen Dank

Da hab ich gepfuscht.

Tausch die Zeile 13 im Server aus, da sind die Anführungszeichen zu viel.
Wir wollen den Inhalt des mühevoll zusammengesetzten Parameters abfragen ("relay1"), und nicht den Parameter "parameter".

Also:

int action = server.arg(parameter) == "1" ? HIGH : LOW;

btw:
bezüglich der Pins muss man fairerweise sagen, dass @HotSystems den ersten Hinweis darauf gegeben hat. Du kannst dich für seinen Tipp mit einem Like/Herzchen unter seinem Beitrag bedanken.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.