NEWS
Füllstandsmessung per Pegelsonde.
-
@Eisbaeeer Ja - ich hatte zwischenzeitlich auch den Bootloader nochmal neu gebraten, weil ich sicher gehen wollte, dass optiboot drauf ist (kleiner).
Im Moment hab ich das gelöst, indem ich per #ifndef HAS_DISPLAY... die ganzen Serial-Ausgaben und Aufrufe abgeklemmt habe.
Der Sketch ist aktuell bei mir jetzt 28428 Bytes groß bis 0x7000 = 28672 habe ich also noch gut 200 Bytes platz...
-
@ltathome Ich habe noch ein wenig experimentiert mit dem Code:
wenn man die Ermittlung der Uptime z.B. so macht und das Zusammenbauen des Strings nicht doppelt (an mehreren Stellen), dann kommt man mit der Code-Size runter (Fragmente):
... int secs = 0, mins = 0, hours = 0; int days = 0; char uptime[25]; ... void set_uptime() { secs++; secs = secs % 60; if (secs == 0) { mins++; mins = mins % 60; if (mins == 0) { hours++; hours = hours % 24; if (hours == 0) { days++; days = days % 10000; // Nach 9999 Tagen zurück auf 0 (das sind 27 Jahre....) } } } sprintf(uptime, "%4dd %2dh %2dm", days, hours, mins); } ... // System /* String upsum; upsum = String(days); upsum = String(upsum + "d "); upsum = String(upsum + hours); upsum = String(upsum + "h "); upsum = String(upsum + mins); upsum = String(upsum + "m"); upsum.toCharArray(buff, 25); */ client.publish("Zisterne/Uptime", uptime);
-
@ltathome machst du einen pull-request?
-
@Eisbaeeer kann ich gerne machen, wenn man mir sagt wie - bisher habe ich auschließlich gecloned. Damit ich mit meinen sonstigen Anpassungen (4-zeiliges Display) den Stand nicht verhunze, setz ich das nochmal ganz sauber separat auf.
-
@ltathome
Wäre cool. Du könntest z.B. über#define 4rowdisplay // 4x20 display oder 2x16 display
#if 4rowdisplay
... Code für 4 zeiliges Display
#endif
#if 2rowdisplay
... Code für 2 zeiliges Display
#endif
Das ganze konfigurierbar machen.
Einen Pull-request machst du ganz einfach aus dem fork heraus. Da gibt es einen Button.
Ich kann dir da gerne behilflich sein.
Gruß EisbaeeerP.S. du kannst den Stand gar nicht verhundsen. Erstens muss ich den pull-request vorher bestätigen und zweitens gibt es in github eine versionierung. Also nur zu!
-
@Eisbaeeer said in Füllstandsmessung per Pegelsonde.:
na dann ....Ich hätte den Code für 4x20 fertig. Ich sehe da noch ein Problem - aber vllt. liegt das auch an meiner Unwissenheit....
Ich habe dein Repo gecloned, in der IDE Zisterne.ino geöffnet - und dann mosert die IDE, dass sie gerne ein Verzeichnis "Zisterne" hätte, legt das Verzeichnis an und schiebt das File darein, der anschließende Compile mosert dann über ein fehlendes progress.h, was ich dadurch gelöst habe, dass ich das ebenfalls in den Ordner "zisterne" verschoben habe.
Dies nur als Vorwarnung - welchen Button meinst du? was ist jetzt das korrekte vorgehen? und sollen wir das "irgendwie" per Chat lösen? wir spammen hier den Thread voll....
-
Das wäre die Version mit den Anpassungen (jetzt korrigiert):
-
Hallo Leute,
ich bin nun auch mal dazu gekommen meine Zisterne mit der Pegelsonde zu überwachen, zumindest wollte ich heute alles zusammenbauen... Offensichtlich hab ich die Schaltung falsch aufgebaut. Mein Sonnoff SV ist gestorben. Den will bzw. wollte ich nutzen um ein elektronisches Ventil zu öffnen wenn der Füllstand zu hoch wird. Seht ihr den Fehler? Ungewollte Brücken auf der Rückseite sind nicht vorhanden. Schwarz ist immer Minus, Rot immer Plus
Vielen Dank im Voraus
-
Wenn keine Module eingesteckt sind, sind dann alle Spannungen da wo sie sein sollen?
-
Danke für das Feedback. Gemessen habe ich schon mal und bin der Meinung dass alles passt. Aber wie gesagt, der Sonoff ist tot, also muss ich einen Fehler haben. Ich messe heute Abend noch mal und zeichne ne Werte in meine Bilder ein.
Vielen Dank
-
Ist die Masse der 3,3 Volt die selbe (also verbunden) wie bei den 24 Volt?
-
Hi, zum Messen werde ich heute nicht mehr kommen. Aber die Masse der 3.3V Leitung geht direkt auf die Header vom Sonoff, das ist quasi die passende Masse für 3.3V. Sie geht also nicht direkt auf die Masse der 24V Zuleitung. Hoffe ist einigermaßen verständlich ausgedrückt
MfG BoBeRzE
-
Ich kenne jetzt den Sonoff nicht so genau, aber wenn die beiden Massen nicht das selbe Potential haben, wäre das ein Grund warum es nicht funktioniert.
-
Ich hatte zwar früher in der Ausbildung auch elektronische Schaltungen aber das Wissen ist nur noch zu Bruchteilen vorhanden
Der Sonoff bietet drei GPOs inkl. VCC (3.3V) und GND. Betrieben wird der Sonoff mit mit 24V. Ob ich jetzt einen Temp-Sensor daran betreibe oder einen ADS1115 sollte doch keinen Unterschied machen. Das Einzige auf was geachtet werden muss ist, dass an den analogen Eingängen vom ADS1115 nicht mehr als 3.3V anliegen weil der ADS1115 selber nur mit 3.3V versorgt wird. Sicherlich wird intern irgendwann wieder alles auf die Masse vom 24V Netzteil geführt, sollten also das selbe Potential haben.
Ich vermute das irgendwo eine Überspannung vorliegt. Deswegen hat es mir ja den Sonoff zerschossen.
Am Eingang vom Sonoff kommen 24V an, dieser wandelt intern auf 3.3V für den ADS1115. Das Modul welches Strom zu Spannung (nachfolgend ItoU-Module) rechnet ist ebenfalls mit 24V (P1 - VCC) versorgt. Vom ItoU-Module P1 (+) geht es auf Plus von der Pegelsonde. Minus von der Pegelsonde geht auf Plus (P2 +) vom ItoU-Module. P2 (-) geht auf P1 (GND). P1 (VOUT) geht an A0 vom ADS1115.
Hoffe man kann den Schaltungsverlauf etwas nachvollziehen.
Danke
-
@BoBeRzE Nur eine Idee. Könnte es sein, dass du sekundärseitig (3.3V Seite) einen Kurzschluss produziert hast und damit den Spannungsregler über den Jordan geschossen hast?
Wie ist denn die Belegung auf dem 3x3 Pfostenstecker auf dem Sonoff?
Weitere Idee, Pins sind von oben gesehen, ist mir auch schon passiert, dass ich von unten die falschen verdrahtet habe (wäre auch wieder Masse auf 3.3V, dann Tot).
Wenn du ein Labornetzteil hast, die 24V mit den Strombegrenzer einstellen, dass der nächste Sonoff beim Test nicht kaputt geht. Aber immer vorher nochmals alles kontrollieren. So wie mein Vorredner schon sagte, alle Punkte durchmessen, ohne gesteckte Module. Dann das Sonoff, nochmals messen. Dann den A/D Wandler, nochmals messen. Dann den Pegelwandler ...
Stückweise voranarbeiten. Fehlersuche kann auch spaß machen
Viel Erfolg beim Suchen!
Grüße Eisbaeeer -
Danke für die Hinweise. Das mit dem "spiegelverkehrt" habe ich bedacht. Ich werde aber alle Punkte noch mal durchgehen wenn ich zuhause bin. Ein neues Modul ist schon bestellt und sollte die Woche kommen. Wäre schön wenn ich das nicht gleich wieder grille
Ich melde mich.
Mir fällt gerade ein wichtiges Detail ein... Der Aufbau vom "Strom zu Spannungs-Wandler" bzw. die daran angeschlossenen Pegelsonde passt aber wie ich beschrieben habe, oder? Habe diesen Part zuletzt verdrahtet und zwischendurch immer mal die Komponenten am Strom gehabt. Da lief noch alles. Nicht das in diesem Part der Fehler steckt.
Vielen Dank
EDIT1: Ein Netzteil mit Strombegrenzer habe ich leider nicht.
EDIT2: Habe jetzt mal an folgenden Punkten Spannung gemessen:Für mich ist das soweit i.O.
Kann jemand ggf. nochmal was zur Verkabelung von der Pegelsonde mit dem "Strom zu Spannungs-Modul" schreiben? Irgendwie glaube ich dass da der Fehler liegt...
-
Soderle - morgen oder Sonntag - wenn das Wetter mitspielt, kalibriere ich das Teil mit voller Zisterne.
Im Code ist das maximale Volumen hinterlegt - das wird bei maximalem analogen Wert erreicht - soweit klar.
Zwei Fragen:- Gemäß Spez. kann der Nano 5V am Analogen Eingang - ich würde das Poti für den maximalen Wert also auf "Knapp drunter" einstellen, wenn die Sonde bei voller Zisterne ganz unten ist. Der Analoge Maximalwert müsste doch dann recht dicht an 1023 sein und nicht rund 25% niedriger (wie im Code) oder?
- Im Code wird der Prozentsatz aus dem analogen Wert ermittelt, indem mit 0,132 multipliziert wird und dann auf 100 gekappt. Das erschliest sich mir nicht. Der Prozentsatz x ist doch:
x = 100% / maximaler Analoger Wert * analoger Messwert
oder habe ich einen denkfehler?
Und wo bekomme ich die schöne Visualisierung aus dem Thread weiter oben her?
Warum ist der maximale Wert nicht per se bei 1023?
Das müsste doch der gewünschte wert für eine maximale Auflösung sein und dem maximalen
EDIT: nachdem ich heute kalibriert hab und nur auf 1,4V kam, habe ich mir die Mühe gemacht und den ganzen Thread nochmal gelesen..
Ich habs jetzt auch verstanden:- den maximalen Wert erreicht man nur, wenn die Sonde auch die volle Nenntiefe versenkt ist - logisch - bei ner 5m Sonde und 2,50 max Tiefe (6,5cbm - Zisterne) passiert das nie.
- Die 5v-Story stehen ebenfalls im Thread weiter vorne - sowei auch das geklät - ich werde morgen nochmal mit beiden Jumpern gesteckt testen - dann müsste ich deutlich dichter an die 5V
Nur das Thema Multiplikation mit 0,132 leuchtet mir immer noch nicht ein.
-
Hallo Leute,
i
ch wollte nochmal nachfragen ob mir jemand bei meinem Problem helfen kann. Einen neuen Sonoff SV habe ich schon liegen, will den aber nicht gleich wieder zerstörenZur besseren Veranschaulichung habe ich euch mal die derzeitige Schaltung gezeichnet.
Vielleicht kann da einer schneller den Fehler finden.Vielen Dank
BoBeRzE
EDIT: Ich habe jetzt noch mal Schritt für Schritt alles aufgebaut und gemessen. Die oben gezeigte Schaltung funktioniert. Mein Problem ist also gelöst. Wer weiß wie ich mir da zwischendurch den Fehler eingefangen habe und den ersten Sonnoff gegrillt habe. Vielleicht kann jemand mit dem Schaltbild etwas anfangen.
Vielen Dank
-
Hallo,
ich habe meine Pegelsonde jetzt in der Zisterne versenkt, die Platine in den Gartenschuppen eingebaut und mittels WLAN meldet die Baugruppe mir jetzt via MQTT den Inhalt. Streut halt ein wenig. Ich musste in meinem ESP8266 den vollen Wert für 5600 Liter bereits auf 254 stellen, so dass mir ESPEasy das korrekt umrechnet. Mit 1023 komme ich da natürlich jetzt auf einen Wert von ca. 22500 Liter. Aber der Wert wird sauber angezeigt, Sendeintervall auf 3600 Sekunden gestellt. Damit ergibt sich dann folgende Anzeige:Ich musste am ESP8266 noch den Pin D0 auf Masse legen, um den Sleepmodus auszuschalten. Heute Nacht war der ESP8266 "eingeschlafen" und in Ermangelung der Verbindung zwischen D0 und RST nicht wieder aufzuwecken. Man kann das sicher auch automatisieren, aber da die Baugruppe eh mit 5V aus einem Netzteil versorgt wird, ist das bei mir egal.
Hier noch ein Foto der Installation:
-
@opossum Darf ich nochmal fragen, woher ich die "tolle Zisterne" haben könnte?
Ich habe mein Teil jetzt seit ein paar Tagen auch "produktiv" - ich habe aber am Code noch deutlich umgebaut, da ich mir die Möglichkeit schaffen wollte, über ein Relais bei Erreichen eines Minimums oder Maximums zu schalten (< Minimal: Umschalten auf Hauswasser, Bei > maximal zurückschalten auf Zisterne. Zwei unterschiedliche Werte, weil das sonst erstens "flattert" und es keinen Sinn macht, selbst bei nur "minimal" über Minimum wieder zurückzuschalten. Und weil ich dann schon mal dran war, habe ich das sowohl über einen Taster, als auch per mqtt realisiert. Ich kann also per Taster (PIN D2) und mqtt das Relais (PIN D3) umschalten zwischen Automatik, Hauswasser und Zisterne. Die Schwellwerte lassen sich ebenfalls per mqtt setzen. Jetzt muss ich nur noch an der Hauswasserpumpe an das Umschaltventil ran um das ans Relais anzuschließen - die bisherige Schwimmerumschaltung klappt nicht sauber - und vor allem muss ich für manuelle Eingriffe jedesmal in den Keller..
/*------------------------------------------------------------------------------------------------------------------------------------------------------------------ Program: Füllstandsmessung mit Pegelsonde Description: Dieses Programm misst die analolge Spannung an einem Port, welche von einem Drucksensor 0-5m Meßhöhe und 4-20mA Stromschnittstelle erzeugt wird. Voraussetzung ist ein Meßwandler, welcher die 24V Versorgungsspannung an den Drucksensor liefert und 0-3,3V analoge Spannung ausgibt. Dienste: DHCP, wenn vorhanden, sonst wird eine feste IP mit 192.168.1.21 vergeben. Hardware: Arduino Nano ATmega 328P W5100 Netzwerk shield LCD Display I2C HD44780 Pin-Ports: A0 = Analog IN A4 = SDA A5 = SCL Date: 20191013 Modified: Initial Version 1.0 - DHCP error routine 20191017 - Fixed uptime_d 20191019 Version 1.1 - Dichte Berechnung hinzugefügt Version 1.2 - LCD wechselt jetzt alle 30 Sek. zwischen Uptime und Analog Messwert 20191024 - Fixed MQTT uptime_d char array 20191028 Version 1.3 - MQTT Port definierbar - MQTT User Password authentication 20200110 Version 1.4 - Array für die Beruhigung des Messwertes eingefügt Author: Eisbaeeer, https://github.com/Eisbaeeer Author: Ethernet part: W.A. Smith, http://startingelectronics.com progress bar - CC BY-SA 3.0 : skywodd, https://www.carnetdumaker.net/articles/faire-une-barre-de-progression-avec-arduino-et-liquidcrystal/ LICENSE: MIT License -------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ // Include some libraries #include <Ethernet.h> #include <SPI.h> #include <Wire.h> #include <hd44780.h> // main hd44780 header #include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip #include <Wire.h> #include <LiquidCrystal_I2C.h> #define twenty_x_four // 4x20 display #ifdef twenty_x_four const int LCD_COLS = 20; const int LCD_ROWS = 4; const int LCD_NB_COLUMNS = 20; #endif #ifdef sixteen_x_four const int LCD_COLS = 16; const int LCD_ROWS = 4; const int LCD_NB_COLUMNS = 16; #endif #include "progress.h" #define MODE_PIN 2 #define MODE_ZISTERNE 0 #define MODE_HAUSWASSER 1 #define MODE_AUTO 2 #define MODE_COUNT 10 bool setmode = false; const char *modes[] = {"Zisterne", "Hauswasser", "Auto"}; int mode_count = MODE_COUNT; int mode = MODE_AUTO; int old_mode = MODE_AUTO; int pin_stat; int old_stat; #define VALVE_PIN 3 #define VALVE_ZISTERNE LOW #define VALVE_HAUSWASSER HIGH int valve = VALVE_ZISTERNE; int new_valve = VALVE_ZISTERNE; int reason = 0; const char *valves[] = {"Zisterne", "Hauswasser"}; const char *reasons[] = {"manuelle Steuerung", "Automatik voll", "Automatik leer"}; // ############################################################################################################################## // ---- HIER die Anpassungen vornehmen ---- // ############################################################################################################################## // Hier die maximale Füllmenge des Behälters angeben. Dies gilt nur für symmetrische Behälter. const float max_liter = 6500; // Analoger Wert bei maximalem Füllstand (wird alle 30 Sekungen auf dem LCD angezeigt oder in der seriellen Konsole mit 9600 Baud. const int analog_max = 715; // Dichte der Flüssigkeit - Bei Heizöl bitte "1.086" eintragen, aber nur wenn die Kalibrierung mit Wasser erfolgt ist! // Bei Kalibrierung mit Wasser bitte "1.0" eintragen const float dichte = 1.0; // IP Adresse und Port des MQTT Servers const char *mqttserver = "iobroker.server.intern"; const int mqttport = 1883; // Wenn der MQTT Server eine Authentifizierung verlangt, bitte folgende Zeile aktivieren und Benutzer / Passwort eintragen const char *mqttuser = "mqttiobroker"; const char *mqttpass = "passwort"; // IP Adresse, falls kein DHCP vorhanden ist. Diese Adresse wird nur verwendet, wenn der DHCP-Server nicht erreichbar ist. IPAddress ip(192, 168, 1, 21); // MAC-Addresse bitte anpassen! Sollte auf dem Netzwerkmodul stehen. Ansonsten eine generieren. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0A }; char buf[40]; // ############################################################################################################################## // AB hier nichts mehr ändern! // (Ausser ihr wisst, was ihr tut) // ############################################################################################################################## // #define USE_SERIAL Serial // No more delay unsigned long startMillis; // some global variables available anywhere in the program unsigned long hstartMillis; // some global variables available anywhere in the program unsigned long currentMillis; const unsigned long sekunde = 1000; // one seconds const unsigned long hsekunde = 500; //Half second unsigned long pinMillis; unsigned long lastMillis = 0; int secs = 0, mins = 0, hours = 0, days = 0; char uptime[25]; float percent; float liter; float limit_low = 500; float limit_high = 1000; boolean LCD_Page; // Analog IN int analogPin = A0; const int messungen = 60; // Anzahl Messungen int myArray[messungen]; // Array für Messwerte float analog = 0.0; // Durchschnittswert int pointer = 0; // Pointer für Messung // MQTT global vars #include <PubSubClient.h> unsigned int send_interval = 10; // the sending interval of indications to the server, by default 10 seconds #define MQTT_KEEPALIVE 60; boolean mqttconnected = false; // MQTT definitions void MqttCallback(char *topic, byte *payload, unsigned int length); EthernetClient ethClient; PubSubClient mqttclient; // (mqttserver, mqttport, MqttCallback, ethClient); #define MQTT_ID "Zisterne" char pl[30]; // Declare subs void Mqttpublish(); void defaultEthernet(void) { Ethernet.begin(mac, ip); // initialize Ethernet device } void Uptime() { secs++; secs = secs % 60; if (secs == 0) { mins++; mins = mins % 60; if (mins == 0) { hours++; hours = hours % 24; if (hours == 0) { days++; days = days % 10000; // Nach 9999 Tagen zurück auf 0 (das sind 27 Jahre....) } } } sprintf(uptime, "%4dd %2dh %2dm", days, hours, mins); if (secs == 0) { // Every Minute //USE_SERIAL.print(F("Uptime: ")); //USE_SERIAL.println(uptime); // MQTT reconnect timeout //Mqttpublish(); } if (secs % send_interval == 0) { // Alle 30 Sekunden LCD_Page = !LCD_Page; Mqttpublish(); // MqttSub(); } if (mins == 0 && secs == 0) { // Jede Stunde //USE_SERIAL.println(F("ONE HOUR")); } } void ReadAnalog() { // read the analog value and build floating middle myArray[pointer++] = analogRead(analogPin); // read the input pin // myArray[pointer++] = 352; pointer = pointer % messungen; // Werte aufaddieren for (int i = 0; i < messungen; i++) { analog = analog + myArray[i]; } // Summe durch Anzahl - geglättet analog = analog / messungen; percent = min(100 * analog / analog_max, 100); float calc = max_liter / analog_max; // calculate percent calc = calc * dichte; // calculate dichte liter = min(analog * calc, max_liter); // calculate liter /* //USE_SERIAL.print(F("Analog: ")); //USE_SERIAL.println(analog); //USE_SERIAL.print(F("Prozent: ")); //USE_SERIAL.println(percent); //USE_SERIAL.print(F("Liter: ")); //USE_SERIAL.println(liter); */ } void setup() { // USE_SERIAL.begin(9600); // for debugging /*-------------------------------------------------------------- LCD init --------------------------------------------------------------*/ lcd.init(); int status; status = lcd.begin(LCD_COLS, LCD_ROWS); if (status) { // non zero status means it was unsuccesful status = -status; // convert negative status value to positive number // begin() failed so blink error code using the onboard LED if possible hd44780::fatalError(status); // does not return } // initalization was successful, the backlight should be on now // Print a message to the LCD lcd.print("Zisterne"); lcd.setCursor(0, 1); lcd.print("Version 1.4"); lcd.setCursor(0, 3); lcd.print("github/Eisbaeeer"); delay(2000); setup_progressbar(); /*-------------------------------------------------------------- Milliseconds start --------------------------------------------------------------*/ startMillis = millis(); //initial start time /*-------------------------------------------------------------- Ethernet init --------------------------------------------------------------*/ if (Ethernet.begin(mac) == 0) { //USE_SERIAL.println(F("Failed config using DHCP")); // DHCP not working, switch to static IP defaultEthernet(); if (Ethernet.hardwareStatus() == EthernetNoHardware) { //USE_SERIAL.println(F("Eth shield not found")); } else if (Ethernet.linkStatus() == LinkOFF) { //USE_SERIAL.println(F("Eth cable not conn")); } } // USE_SERIAL.print(F("IP: ")); // USE_SERIAL.println(Ethernet.localIP()); // start MQTT client MqttConnect(mqttuser, mqttpass); /*------------------------------------------------------------------- * Setup Pins for Valve and mode-setting */ pinMode(MODE_PIN, INPUT_PULLUP); pinMode(VALVE_PIN, OUTPUT); pin_stat = old_stat = digitalRead(MODE_PIN); } void MqttConnect(char *user, char* pass) { mqttclient.setClient(ethClient); mqttclient.setServer(mqttserver, mqttport); mqttclient.setCallback(MqttCallback); mqttconnected = mqttclient.connect(MQTT_ID, user, pass); if (mqttconnected) { // USE_SERIAL.println("Connected to Mqtt-Server"); mqttclient.subscribe("Zisterne/cmd/Mode"); mqttclient.subscribe("Zisterne/cmd/Limit"); // USE_SERIAL.println("subscribing to Zisterne/cmd/Mode"); } } void MqttCallback(char *topic, byte *payload, unsigned int length) { char *payloadvalue; char *payloadkey; payload[length] = '\0'; payloadkey = (char *)&payload[0]; // USE_SERIAL.println(payloadstring); if (strcmp(topic, "Zisterne/cmd/Mode") == 0) { if (strcmp(payloadkey, "0") == 0 || strcmp(payloadkey, "Zisterne") == 0) { mode = MODE_ZISTERNE; } else if (strcmp(payloadkey, "1") == 0 || strcmp(payloadkey, "Hauswasser") == 0) { mode = MODE_HAUSWASSER; } else if (strcmp(payloadkey, "2") == 0 || strcmp(payloadkey, "Auto") == 0) { mode = MODE_AUTO; } } else if (strcmp(topic, "Zisterne/cmd/Limit") == 0) { int eq = 0; for (int i = 0; i < length; i++) { if (payload[i] == '=') { eq = i; break; } } if (eq > 0) { payload[eq++] = 0; payloadvalue = (char *)&payload[eq]; if (strcmp((char *)payload, "Low") == 0 || strcmp((char *)payload, "low") == 0) { limit_low = atoi(payloadvalue); } if (strcmp((char *)payload, "High") == 0 || strcmp((char *)payload, "high") == 0) { limit_high = atoi(payloadvalue); } } } } void CheckEthernet() { if (Ethernet.hardwareStatus() != EthernetNoHardware) { /*-------------------------------------------------------------- check ehternet services --------------------------------------------------------------*/ switch (Ethernet.maintain()) { case 1: //renewed fail //USE_SERIAL.println(F("Error: renewed fail")); break; case 2: //renewed success //USE_SERIAL.println(F("Renewed success")); //print your local IP address: //USE_SERIAL.print(F("My IP address: ")); //USE_SERIAL.println(Ethernet.localIP()); break; case 3: //rebind fail //USE_SERIAL.println(F("Error: rebind fail")); break; case 4: //rebind success //USE_SERIAL.println(F("Rebind success")); //print your local IP address: //USE_SERIAL.print(F("My IP address: ")); //USE_SERIAL.println(Ethernet.localIP()); break; default: //nothing happened break; } } } void loop() { /*-------------------------------------------------------------- remove delay (half second) --------------------------------------------------------------*/ mqttclient.loop(); pin_stat = digitalRead(MODE_PIN); pinMillis = millis(); if (pin_stat == LOW) { if (pinMillis - lastMillis > 200) { //USE_SERIAL.println("Impuls Low"); lastMillis = pinMillis; mode_count = MODE_COUNT; if (!setmode) { setmode = true; old_mode = mode; //sprintf(buf, "Enter Settings-Mode %d (%s)", mode, modes[mode]); //USE_SERIAL.println(buf); } else { mode--; if (mode < 0) { mode = 2; } //sprintf(buf, "Mode change to %d (%s)", mode, modes[mode]); //USE_SERIAL.println(buf); } } } /*-------------------------------------------------------------- remove delay (one second) --------------------------------------------------------------*/ currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started) if (currentMillis - startMillis >= sekunde) { // Hier eine Sekunde warten startMillis = currentMillis; /****************************************************************************************** 1 Sekunden Takt *****************************************************************************************/ // Hier die Funktionen im Sekundentakt // ################################### CheckEthernet(); Uptime(); ReadAnalog(); if (setmode) { mode_count--; if (mode_count <= 0) { //sprintf(buf, "leaving Settings-Mode - change from %d to %d (%s)", old_mode, mode, modes[mode]); //USE_SERIAL.println(buf); old_mode = mode; setmode = false; } } if (!setmode) { if (mode == MODE_ZISTERNE) { new_valve = VALVE_ZISTERNE; reason = 0; } else if (mode == MODE_HAUSWASSER) { new_valve = VALVE_HAUSWASSER; reason = 0; } else if (mode == MODE_AUTO) { if (liter >= limit_high) { new_valve = VALVE_ZISTERNE; reason = 1; } if (liter <= limit_low) { new_valve = VALVE_HAUSWASSER; reason = 2; } } } /*----------------------------------------------------------- * Wenn Ventil umzuschalten ist */ if (new_valve != valve) { valve = new_valve; digitalWrite(VALVE_PIN, valve); //sprintf(buf, "Set Valve to %s (%s)", valves[valve], reasons[reason]); //USE_SERIAL.println(buf); } // print out to LCD if (!setmode) { draw_progressbar(percent); } write_lcd(); } } /****************************************************************************************** Ende Loop * **************************************************************************************** Beginn Unterprogramme ******************************************************************************************/ void write_lcd(void) { char LCDbuff[20]; if (!setmode) { // Zeile 1 lcd.setCursor(6, 0); dtostrf(liter, 4, 0, LCDbuff); lcd.print(LCDbuff); lcd.print(" Liter"); #ifdef sixteen_x_four if ( LCD_Page == false ) { // Zeile 3 lcd.setCursor(0, 2); lcd.print("Uptime"); // Zeile 4 lcd.setCursor(0, 3); lcd.print(uptime); } else { // Zeile 3 lcd.setCursor(0, 2); lcd.print("Messwert Analog"); // Zeile 4 lcd.setCursor(0, 3); lcd.print(analogRead(analogPin)); } #endif #ifdef twenty_x_four // Zeile 3 lcd.setCursor(0, 2); lcd.print("Uptime"); // Zeile 3 lcd.setCursor(7, 2); lcd.print(uptime); // Zeile 4 lcd.setCursor(0, 3); if (mode == 2) { lcd.print("Auto: "); } else { lcd.print("Manuell: "); } lcd.setCursor(10, 3); lcd.print(valves[valve]); // Zeile 4 // lcd.setCursor(16, 3); // lcd.print(analogRead(analogPin)); #endif } else { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Ventilsteuerung "); lcd.setCursor(0, 1); lcd.print("Bisher: "); lcd.setCursor(10, 1); lcd.print(modes[old_mode]); lcd.print(" "); lcd.setCursor(0, 2); lcd.print("Neu: "); lcd.setCursor(6, 2); lcd.print(modes[mode]); lcd.setCursor(0, 3); lcd.print(mode_count); } } void Mqttpublish(void) { if (mqttclient.connected()) { dtostrf(analog, 5, 2, buf); mqttclient.publish("Zisterne/Analog", buf); dtostrf(liter, 5, 0, buf); mqttclient.publish("Zisterne/Liter", buf); dtostrf(limit_low, 1, 0, buf); mqttclient.publish("Zisterne/LiterLow", buf); dtostrf(limit_high, 1, 0, buf); mqttclient.publish("Zisterne/LiterHigh", buf); dtostrf(percent, 5, 0, buf); mqttclient.publish("Zisterne/Prozent", buf); if (mode == 2) { mqttclient.publish("Zisterne/Modus", "Auto"); } else { mqttclient.publish("Zisterne/Modus", "Manuell"); } dtostrf(mode, 1, 0, buf); mqttclient.publish("Zisterne/Mode", buf); dtostrf(valve, 1, 0, buf); mqttclient.publish("Zisterne/Valve", buf); mqttclient.publish("Zisterne/Ventil", valves[valve]); // System mqttclient.publish("Zisterne/Uptime", uptime); } else { MqttConnect(mqttuser, mqttpass); } } void draw_progressbar(byte percent) { lcd.clear(); /* Affiche la nouvelle valeur sous forme numérique sur la première ligne */ lcd.setCursor(0, 0); lcd.print(percent); lcd.print(F(" % ")); // N.B. Les deux espaces en fin de ligne permettent d'effacer les chiffres du pourcentage // précédent quand on passe d'une valeur à deux ou trois chiffres à une valeur à deux ou un chiffres. /* Déplace le curseur sur la seconde ligne */ lcd.setCursor(0, 1); /* Map la plage (0 ~ 100) vers la plage (0 ~ LCD_NB_COLUMNS * 2 - 2) */ byte nb_columns = map(percent, 0, 100, 0, LCD_NB_COLUMNS * 2 - 2); // Chaque caractère affiche 2 barres verticales, mais le premier et dernier caractère n'en affiche qu'une. /* Dessine chaque caractère de la ligne */ for (byte i = 0; i < LCD_NB_COLUMNS; ++i) { if (i == 0) { // Premiére case /* Affiche le char de début en fonction du nombre de colonnes */ if (nb_columns > 0) { lcd.write(1); // Char début 1 / 1 nb_columns -= 1; } else { lcd.write((byte) 0); // Char début 0 / 1 } } else if (i == LCD_NB_COLUMNS - 1) { // Derniére case /* Affiche le char de fin en fonction du nombre de colonnes */ if (nb_columns > 0) { lcd.write(6); // Char fin 1 / 1 } else { lcd.write(5); // Char fin 0 / 1 } } else { // Autres cases /* Affiche le char adéquat en fonction du nombre de colonnes */ if (nb_columns >= 2) { lcd.write(4); // Char div 2 / 2 nb_columns -= 2; } else if (nb_columns == 1) { lcd.write(3); // Char div 1 / 2 nb_columns -= 1; } else { lcd.write(2); // Char div 0 / 2 } } } }