Ankündigung

Einklappen
Keine Ankündigung bisher.

Füllstandsmessung Tank (Zisterne) (gerne auf KNX)

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Fidelis
    antwortet
    DIY und KISS. Gefällt mir!

    Klar ist es chic, wenn man %-Werte ablesen kann. Aber ich frage mich, ob ich mich anders verhalten bzw. die daran möglicherweise hängende Automatisierung anders einstellen würde, wenn ich wüsste es sind aktuell 28% oder 78%. Wenn Wasser drin ist, kann es genutzt werden. Wenn kein Wasser drin ist, kann keins genutzt werden. Im Grunde also eine binäre Entscheidung... Wie verwendet ihr genauere Angaben als "leer / halbvoll / voll"?

    Zitat von Stargate Beitrag anzeigen
    bei Bier wollte man es vielleicht dann doch genauer wissen
    Und da kommt die in deinem Zitat angesprochene Webcam zum Einsatz. Die ermittelt mit Hilfe von KI wieviele Biere noch vorhanden sind und prognostiziert auf Basis des ermittelten Verbrauchs der letzten Tage / Stunden / Minuten den richtigen Zeitpunkt für den nötigen Nachschub. Oder ordert von mir aus direkt selber ne neue Kiste...

    Einen Kommentar schreiben:


  • Stargate
    antwortet
    Zitat von cycoso Beitrag anzeigen

    Wer kennt eine bezahlbare Lösung um den Höhenstand abzulesen? Die Werte auf KNX wären natürlich schön. Die Gesamthöhe ab Boden sind rund 2,30 m.
    Viega Ultraschallsensor kenne ich, der dann ein Anlogsignal ausgibt, aber das ist ejtzt nicht direkt Haustechnik/ KNX und benötgt ja auch Programmierumwege.

    Eine Unterwasserdrucksonde wäre evtl. eine Lösung, die andere eine Höhenstandslatte und Webcam :-)
    Also man darf gerne darüber lachen..

    Aber ich habe seit Jahren eine Lösung die aus einer PG-Verschraubung, einer "Messlatte" in Form von grauem Installationsrohr, ein
    bisschen "Füllstandselektronik", ausgeführt mit entsprechend 4 Elektroden, eine Masse, die anderen drei für "Voll" "Halb" und "Leer" bestehen gebaut.

    Als Messelektroden dient jeweils ein Stückchen Alurohr, ca. 20 mm lang, auf die entsprechenden Stellen am Rohr geschoben und mit den Leitungen
    im inneren des Rohrs verbunden. Verklebt und verschraubt. Das ganze dann zwei mal, für eben zwei grössere Regenwasserbehälter.

    Per 4-adriger Leitung geht es jeweils zur Füllstandselektronik im Schuppen, einem einreihigen Kleinverteiler und dem darin eingebauten Netzteil für
    die Füllstandselektronik bzw. von dort aus dann auf jeweils einen ganz einfach 4-fach Binäreingang. Visualisiert wird das ganze per ProServ.

    Es zeigt natürlich keinen prozentualen Füllstand an, braucht es aber auch gar nicht.

    Das teuerste daran war jeweils der 4-fach Binäreingang.

    Diese Lösung funktioniert hier seit Jahren perfekt.
    Ob die Behälter zu 20% oder zu 75% gefüllt sind interessiert mich nicht so brennend, wie gesagt mir reicht "Leer" "Halbvoll" und eben "Voll"

    Es ist ja auch "nur" Regenwasser, bei Bier wollte man es vielleicht dann doch genauer wissen



    Mit Ultraschallsensoren hatte ich das zuerst am Brennstofftank versucht - vollkommen unbefriedigend.
    An Wasserbehältern war das dann genau so zuverlässig.. (womit das Medium als Fehlerquelle vollkommen Egal ist)

    Bedenkt man was so ein Sensor kostet fand ich meine Lösung bisher ziemlich wirtschaftlich.




    Einen Kommentar schreiben:


  • Fidelis
    antwortet
    Ich verstehe deine Frage nicht. Es gibt im Handbuch genau einen Abschnitt: "5.4.1 Skalierung des Messwertes". Und du hast einen 4-20mA-Sensor. Alles andere sollte halbwegs selbsterklärend sein, hoffe ich. Wenn nicht, mach mal Screenshots, damit klar wird an welcher Stelle du festhängst.

    Einen Kommentar schreiben:


  • Spikey
    antwortet
    Zitat von Fidelis Beitrag anzeigen
    Wo siehst du keine Möglichkeit? Schnapp dir mal das Handbuch uns suche nach "Skalierung".
    bei Prozent?

    Einen Kommentar schreiben:


  • Fidelis
    antwortet
    Zitat von Spikey Beitrag anzeigen
    aber sehe keine Möglichkeit
    Wo siehst du keine Möglichkeit? Schnapp dir mal das Handbuch uns suche nach "Skalierung".

    Einen Kommentar schreiben:


  • Spikey
    antwortet
    Hallo zusammen,

    ich muss nochmals nachfassen, nachdem nun alles läuft und mein Regenfass nun zum ersten Mal gefüllt ist....

    Mein Regenfass hat eine Höhe von 185, ich habe eine Sonde von 0-2m. Bei 85% läuft sie dann logischerweise über. Kann ich das irgendwie mit dem MDT Autor trimmen? 85 müssen also 100% sein - aber sehe keine Möglichkeit.

    Wie löst ihr das. Ich möchte eigentlich eine "komplizierte" Logik im X1 vermeiden, da das Regenfass relativ gerade ist, wäre es auch linear.

    VG Spikey

    Einen Kommentar schreiben:


  • androidin
    antwortet
    Zitat von Techi Beitrag anzeigen


    Bei mir stimmt der Index 2 als 0% schon (200mm Wasserhöhe), weil bei mir bedingt durch die Pumpenansaugung (Schlauch mit schwimmenden Ball) immer min. ca. 20cm in der Zisterne stehen bleiben.
    Ich kann das darunter ja nicht verwenden, somit sind bei mir die 0% wenn die Zisterne noch 200mm Wasserhöhe hat.
    Schon klar, aber oben im Code sagst du ja
    Code:
    // index to table for lowest level in zistern where water
    // can still be pumped. Below pump cant reach the water
    const percent_0_index = 2 // eg, 2 is 976l
    ​
    Und wenn man den Codeschnipsel übernimmt, dann kann das (wie bei mir) eben falsch sein, weil bei mir ist percent_0_index = 1 ;-)

    Einen Kommentar schreiben:


  • Techi
    antwortet
    Zitat von androidin Beitrag anzeigen

    ...
    Dabei ist aufgefallen, dass wahrscheinlich bei dieser Zeile:
    die 2 ersetzt werden muss mit percent_0_index.
    ...

    Bei mir stimmt der Index 2 als 0% schon (200mm Wasserhöhe), weil bei mir bedingt durch die Pumpenansaugung (Schlauch mit schwimmenden Ball) immer min. ca. 20cm in der Zisterne stehen bleiben.
    Ich kann das darunter ja nicht verwenden, somit sind bei mir die 0% wenn die Zisterne noch 200mm Wasserhöhe hat.

    Einen Kommentar schreiben:


  • androidin
    antwortet
    Den original Code. Weiter hatte ich den thread gar nicht gelesen gehabt 😉 einen Durchschnitt zu bilden halte ich bei meiner Sonde für nicht nötig. Der ausgegebene Wert ist meist gleich. Ich lasse ihn mir alle Stunde über ntfy auf mein Handy drücken. Ab und an (selten) schwankt der Wert.

    Einen Kommentar schreiben:


  • StefanWE
    antwortet
    Hallo androidin, danke für deine Info. Welchen Code hast du optimiert? Den Ursprünglichen von Techi oder meinen mit der spline Funktion?

    Einen Kommentar schreiben:


  • Fidelis
    antwortet
    Das kommt auf das Messprinzip "der Sonde" an.
    • Wenn die Sonde "die Wassersäule" misst, wie du es beschreibst, dann meinst du vermutlich eine Sonde, die einen Differenzdruck misst. Also den Unterschied zwischen dem Wasserdruck an ihrem Einbauort und dem Luftdruck der freien Umgebung. Dann kann die Sonde prinzipbedingt nur alles Wasser messen, das sich über ihr befindet. Also in dem Fall auch bis in den Dom hinein.
    • Wenn die Sonde bspw. mit Ultraschall den Wasserspiegel vermisst, dann hängt die Sonde bzw. der Messkopf oberhalb des Wassers und misst die Entfernung bis zur Wasseroberfläche. So eine Sonde misst prinzipbedingt alles Wasser, das sich unter ihr befindet. In diesem Fall also nicht bis in den Dom hinein.
    In den meisten Fällen scheinen hier Sonden eingesetzt zu werden, die den Wasserdruck messen und deshalb relativ nah am Boden des Tank installiert werden.

    Einen Kommentar schreiben:


  • androidin
    antwortet
    Zitat von Techi Beitrag anzeigen
    percent = (percent * (y - literingTable[2][1])).toFixed(0) * 1;
    Hi,

    ich habe den Code mit angepasster Litering-Table übernommen, allerdings jeden Schritt nachvollzogen, da ich auch mehr Werte in der Litering-Table habe und eine Sonde von 0-5m. Ich habe von meinem Hersteller einen Graph bekommen und deswegen habe ich um die nichtlinearen Phasen mehr Punkte angegeben. Ansonsten funktioniert der Code relativ gut. Vielen Dank dafür.

    Dabei ist aufgefallen, dass wahrscheinlich bei dieser Zeile:
    Zitat von Techi Beitrag anzeigen
    percent = (percent * (y - literingTable[2][1])).toFixed(0) * 1;
    die 2 ersetzt werden muss mit percent_0_index.

    Bei mir hat in meinem NodeRed auch das toFixed(0) statement nicht funktioniert. Deshalb hab ich das weggelassen und mit folgender Zeile umgeschrieben:
    percent = Math.round(percent * 10) / 10;


    ​Vielleicht hilft es dem ein oder anderen.

    Nur mal eine Verständnisfrage: die Sonde misst die Wassersäule, richtig? Ich stelle mir nur vor, wenn die Sonde unter dem Dom liegt und Wasser im Dom stehen würde, würde dann die Sonde dann trotzdem die Höhe der Wassersäule richtig ausgeben, also bis in den Dom hinein?

    Einen Kommentar schreiben:


  • Techi
    antwortet
    Das mit Splines zu machen gefällt mir auch gut.
    Toll das auch mal andere Ideen dazu kommen.


    Einen Kommentar schreiben:


  • StefanWE
    antwortet
    Ah prima. Danke. den hatte ich nicht mehr in Erinnerung. Funktioniert nun prima. Ich habe von Graf die 4800l Zisterne. Auch Unförmig. Meine Arbeitskollegin hat dein Script überarbeitet und die Berechnung der geraden umgebaut.

    Code:
    // zistern litering table (got from manufacturer GRAF)
    // first column = fillheight in mm
    // second column = liter
    const literingTable = [
        [0, 0],
        [100, 135],
        [200, 320],
        [300, 550],
        [400, 825],
        [500, 1120],
        [600, 1450],
        [700, 1800],
        [800, 2160],
        [900, 2530],
        [1000, 2895],
        [1100, 3245],
        [1200, 3580],
        [1300, 3885],
        [1400, 4160],
        [1500, 4430],
        [1600, 4585],
        [1700, 4720],
        [1800, 4780],
    ];
    //var msg;
    var msg2;
    var msg3;
    var msg4;
    // pressure Sensor parameters
    const max_height = 4;   // 4m
    const max_mA = 20;      // mA at max_height
    const min_mA = 4;      // mA at zero height
    // index to table for lowest level in zistern where water
    // can still be pumped. Below pump cant reach the water
    const percent_0_index = 2   // eg, 2 is 976l
    //const lowest_level_Tindex = 2;
    
    // Main starts here
    var y;
    var measured_mA = msg.payload; // get mA value from Sensor as input
    var measured_mA_mean;
    measured_mA_mean = context.get('measured_mA_mean');
    if (context.get('Startup') == 341487) {
        context.set("Startup", 0)
        measured_mA_mean = measured_mA;
    }
    measured_mA_mean = (measured_mA_mean * 2 + measured_mA) / 3;
    context.set('measured_mA_mean', measured_mA_mean);
    if (measured_mA < min_mA) {
        // if its below allowed range, then exit
        node.warn("Error ! Input Value below 4mA")
        return;
    }
    
    // both possible: measured_mA_mean or measured_mA
    spline(measured_mA_mean)
    
    // calculates based on linear relationship. alternative below
    var high_mm = (max_height * 1000 / (max_mA - min_mA) * (measured_mA_mean - min_mA));
    
    //var x = Math.round(high_mm);
    var x = high_mm;
    
    //search for fitting table area, getting index into table as i
    for (var i = 0; i < literingTable.length; i++) {
        if (literingTable[i][0] > x) break; // if "end entry" found, then exit
    }
    i = i - 1;  // correct index to "start entry"
    
    // check if index was inside table and not the last entry
    if (i < literingTable.length - 1) {
        // was inside table
        // get values from table
        var x1 = literingTable[i + 0][0];
        var y1 = literingTable[i + 0][1];
        var x2 = literingTable[i + 1][0];
        var y2 = literingTable[i + 1][1];
        // and calculate the value in between = lineare interpolation
        y = (y1 + ((x - x1) / (x2 - x1) * (y2 - y1)));
    }
    else {
        // was the last entry,
        // so return last entry as fixe value from table
        // no calcuation needed
        y = literingTable[i + 0][1]
    }
    // calculate percentage from table index 2 as 0% to last table index as 100%
    var percent = 100 / (literingTable[literingTable.length - 1][1] - literingTable[percent_0_index][1]);
    percent = Math.round(((percent * (y - literingTable[percent_0_index][1])) * 1) * 1e0) / 1e0;
    if (percent < 0) {
        percent = -1;
    }
    y = Math.round(y);
    msg.payload = [
        [   // first value
            {   // influxdb2 fields
                "menge": y
            },
            {   // influxdb2 tags
                "typ": "inhalt",
                "einheit": "liter",
                "quelle": "drucksensor",
                "ort": "zisterne"
            }
        ],
        [   // second value
            {   // influxdb2 fields
                "menge": percent
            },
            {   // influxdb2 tags
                "typ": "inhalt",
                "einheit": "prozent",
                "quelle": "drucksensor",
                "ort": "zisterne"
            }
        ]
    ];
    return [msg];
    
    /**
     *  alternative function for hillheight (y) und fillvolume (x) using spline.
     * @param {float} pressure sensor input or 'cleaned' sensor input using measured_mA_mean
     */
    function spline(pressure) {
        // normalized needed for spline interpolation
        const normalized_pressure = (pressure - min_mA) / (max_mA - min_mA);
    
        // spline interpolation for x:
        var interval = -1; // Initialize with an invalid value
        for (var i = 0; i < literingTable.length - 1; i++) {
            if (normalized_pressure >= literingTable[i][0] && normalized_pressure <= literingTable[i + 1][0]) {
                interval = i;
                break; // if "end entry" found, then exit
            }
        }
    
        // Errorhandling
        if (interval === -1) {
            interval = normalized_pressure < literingTable[0][0] ? 0 : literingTable.length - 2;
        }
    
        // find value between two entries
        const x1 = literingTable[interval][0];
        const y1 = literingTable[interval][1];
        const x2 = literingTable[interval + 1][0];
        const y2 = literingTable[interval + 1][1];
    
        //non-linear interpolation
        const t = (normalized_pressure - x1) / (x2 - x1);
        const a = 2 * y1 - 2 * y2 + 1;
        const b = -3 * y1 + 3 * y2;
        const c = y1;
        
        // fill height in mm
        var y = a * Math.pow(t, 3) + b * Math.pow(t, 2) + c * t;
    
        // fill volume (1800 based on max_fillheight) in mm
        var x = (Math.PI * y^2 * (3* (1800/2) - y)) / 3;
    
        // return what you need.
        return y; // or x
    }
    ​
    Ich kann leider mit der Berechnung nichts anfangen, das ist mir zu hoch. Aber ggf. kann jemand anderes das mal bewerten oder es hilft.

    Einen Kommentar schreiben:


  • TheOlli
    antwortet
    In NodeRed kann man in einem function-node in Reiter „Start“ Code hinterlegen der nur einmalig beim Start ausgeführt wird.

    Einen Kommentar schreiben:

Lädt...
X