Excel für Füllstandsberechnung nutzen

Richtig!
Der Messwert muss dann in die Zeile "Aktuelle Füllhöhe" eingefügt werden. Kann man das mit dem Arduino realisieren?

Und kann man anschließend die Werte aus der Excel Tabelle im z.B. WebIf Anzeigen lassen?

newpv:
Der Messwert muss dann in die Zeile "Aktuelle Füllhöhe" eingefügt werden. Kann man das mit dem Arduino realisieren?

Vielleicht. Aber es ergibt keinen Sinn.
Eine Excel-Datei kannst Du ja nur auf dem PC (oder Tablet) ansehen. Also müsstest Du eine gemeinsame Ablage für die Datei haben oder sie hin- und hertragen.
Deshalb für den Datentransport CSV nutzen und dann (am PC) in das Excel importieren.

Und kann man anschließend die Werte aus der Excel Tabelle im z.B. WebIf Anzeigen lassen?

Nicht trivial. Du müsstest dann ja die berechneten Werte aus Excel wieder zum Arduino schicken falls der die Webseite erzeugt.

Du solltest Dir mal eine Skizze machen, aus der hervorgeht, welches Datum wo entsteht bzw. verarbeitet und schließlich angezeigt wird.

Ich stimme Walter zu. In so einem Fall sind kritzeln und Listen machen angesagt.

Gruß

Gregor

Hallo,

Du kannst doch sicher in Excell ein Macro machen um die relevanten Daten aus der Tabelle "Messwerte" in die Tabelle "Berechnen" zu kopieren. Auch in Excell gibts eine Möglickeit das mit "Basic" auf Knopfdrück zu automatisieren.

Mal eine ganz andere Frage warum machst Du die Berechnung nicht im Arduino, so wie ich das sehe hast Du doch gar keine Messreihen.

Und kann man anschließend die Werte aus der Excel Tabelle im z.B. WebIf Anzeigen lassen?

was ist WebIf ?

Heinz

@TO: Was hast du eigentlich vor? Ich glaube du hast die falsche Vorstellung der Lösung und ich bin davon überzeugt, das es viel bessere Lösungen für deine Aufgabenstellung gibt.
Was willst du also machen?
Eine Volumenberechnung von einer Zisterne?
Oder / auch ein Logging des Füllstands? Wenn ja über welche Zeit mit welchem Intervall?
Oder ganz was anderes?
Ich glaube nicht, das Excel zu der Lösung gehört. Das ist viel zu umständlich.

Erzähl mal was dein Ziel ist.

Lieben Gruß,
Chris

Mein Ziel ein Reale Füllstandsanzeige, da die Zisterne nicht Rund ist sondern die Form aus dem Bild hat...

Habe mir bereits die Berechnung in Excel erstellt, deshalb wollte ich es in Excel machen, da es aber so nicht funktioniert, werde ich die Berechnung nun mit Hilfe der Excel Tabelle im Arduino Programm schreiben...das geht ja auch, man benötigt halt nur die "math.h" dann geht es auch mit Pi usw.

Mal eine Frage wie muss "ARCCOS" lauten? Wäre es so richtig "acos()"?

Log brauche ich erstmal nicht! Möchte erstmal "nur" eine Berechnung des Füllstands und eine Temperaturanzeige über WebIf und LCD Display haben.

Fange alles erst per Serielleausgabe an...wenn die Werte ok sind geht es mit dem Display weiter, dann WebIf und am Ende kommen ggf. noch Bilder als Hintergrund vom WebIf je nach Füllstand. Aber alles nach und nach...

Und wenn das alles läuft kommt evtl. noch ein Durchfluss Zähler, aber das ist zuweit in der Zukunft

Ah ja - hurra!
Jetzt sehen wir doch schon viel klarer.

Dein Weg ist dann auch der richtige:
Excel-Formel in C++ Code auf dem Arduino umsetzen, mit Testwerten füttern und berechneten Füllstand seriell ausgeben. Display und Webseite kommen später.
Sieht wie ein Plan aus!

Was acos() angeht: Ja!

Darf ich frecherweise fragen, wo Du später die aktuelle Füllhöhe herbekommst? Im Plan fehlt noch das Kapitel "Sensorik".

Meine Empfehlung dazu:
ESP8266 und epaper Display.
Oder auch ESP32, den braucht es aber nicht wirklich, der 8266 reicht dafür auch 100x aus.

Die ESPs haben WLAN gleich mit an Board, damit kannste dann auch kabellos loggen wenn du willst.
Das epaper Display braucht nur kurz Strom, wenn sich die Anzeige ändern soll.
Dann kannste auch nur alle 5 oder 15min messen und bei Bedarf loggen.
Und in der Zwischenzeit kannst du das alles wieder in den Tiefschlaf versetzen. Das ganze funktioniert auch mit Solarzelle als Stromversorgung.
Du kannst auch ein OLED oder LCD oder TFT Display benutzen, aber die brauchen dauernd Strom.
Wenn du loggen und auswerten willst kann ich dir volkszaehler.org sehr empfehlen.

Lieben Gruß,
Chris

wno158:
Darf ich frecherweise fragen, wo Du später die aktuelle Füllhöhe herbekommst?

Natürlich, die Füllhöhe soll über einen Ultraschallsensor kommen!

@themanfrommoon
Danke für den Hinweis, aber in der Ecke habe ich eh LAN, wo der Arduino hin kommt. Habe einen Uno r3 Clone...

Ich habe ja bereits angefangen die Formel zur Berechnung zu schreiben. Jetzt hänge ich aktuell bei der Wurzel!
Wie kann ich diese Berechnen?

Zu faul zum googeln?
https://www.google.com/search?ie=UTF-8&client=ms-android-vf-de-revc&source=android-browser&q=arduino+wurzel

newpv:
...Jetzt hänge ich aktuell bei der Wurzel!
Wie kann ich diese Berechnen?

Sachma, was passiert beim Druck auf F1? Schon mal etwas von einer Online-Hilfe oder einem Handbuch gehört? Sowas kann man lesen, man kann darin nachschlagen ...

Gruß :wink:

Gregor

Hallo,
ich habe mal die Formeln von Excel in Arduino geschrieben, leider kommen da falsche Ergenisse heraus, woran liegt es?

// Tank Füllstandsanzeige v1.0
#include <math.h> //Mathe Bibliothek
#define PI 3.1415926535897932384626433832795

void setup()
{
  Serial.begin(9600); // Serielle Schnittstelle intialisieren
}

void loop()
{
  // Aktueller Füllstand
  int Fuellstand = 1000; // Füllhöhe im mm

  // Zylindervolumenberechnung
  int Zylinderraduis = 875; // Zylinder Gesamt Raduis in mm
  int Zylinderhoehe = 2380; // Zylinder Länge/Höhe Gesamtgröße in mm
  int Zylinderverlust = 95; // Zylinder Überlaufverlust Höhe in mm
  int Zylinderfuellhoehe = (Fuellstand / 2); // Aktuelle Füllhöhe (Radius) in mm

  int VZ1 = ((PI * sq(Zylinderraduis) * Zylinderhoehe) / 1000000); // Zylindervolumengesamt ohne Überlauf im dm³
  int VZ2 = (sq(Zylinderraduis) * Zylinderhoehe * (acos(1 - Zylinderverlust / Zylinderraduis)) * sqrt((Zylinderverlust / Zylinderraduis) * ((2 - Zylinderverlust) / Zylinderraduis))) / 1000000; // Zylindervolumen Überlaufverlust im dm³
  int VZ3 = VZ1 - VZ2; // Maximal Nuztbares Volumen im dm³
  int VZ4 = (sq(Zylinderraduis) * Zylinderhoehe * (acos(1 - Zylinderfuellhoehe / Zylinderraduis)) * sqrt((Zylinderfuellhoehe / Zylinderraduis) * ((2 - Zylinderfuellhoehe) / Zylinderraduis))) / 1000000; // Zylindervolumen des aktuellen Füllstand im dm³

  // Kugelvolumenberechnung
  int Kugelraduis = 835; // Kugel Radius vorhandene Fläche in mm
  int Kugelhoehe = 380; // Kugel Gesamthöhe in mm
  int Kugelverlust = 95; // Kugel  Überlaufverlust Höhe in mm
  int Kugelfuellhoehe = (Fuellstand / 2); // Aktuelle Füllhöhe (Radius) in mm

  int RK1 = (sq(Kugelraduis) + sq(Kugelhoehe)) / (2 * Kugelhoehe); // Radius der Kugel
  int VK1 = ((PI / 3) * sq(Kugelhoehe) * (3 * RK1 * Kugelhoehe)) / 1000000; // 1/2 Kugelvolumengesamt ohne Überlauf in dm³
  int VK2 = VK1 * 2; // Kugelvolumengesamt ohne Überlauf in dm³
  int VK3 = ((PI / 3) * sq(Kugelverlust) * ((RK1 * RK1 * RK1) - Kugelverlust)) / 1000000; // 1/2 Kugelvolumen Überlaufverlust im dm³
  int VK4 = VK3 * 2; // Kugelvolumen Überlaufverlust gesamt im dm³
  int VK5 = VK2 - VK4; // Kugel maximales Wasservolumen
  int VK6 = (((PI / 3) * sq(Kugelfuellhoehe)) * ((RK1 * RK1 * RK1) - Kugelfuellhoehe))) / 10000000; // Aktueller Füllstand 1/2 Kugel im dm³
  int VK7 = VK6 * 2; // Aktueller Füllstand Kugel


  // Gesamtwerteberechnung
  int Tankvolumengesamt = VZ1 + VK2; // Gesamtvolumen des Tanks im dm³
  int Tankvolumennutzbar = VZ3 + VK5; // Nutzbares Tankvolumen im dm³
  int Tankinhalt = VZ4 + VK7; // Aktueller Tankinhalt nach Füllstand im dm³
  int Tankinhaltprozent = Tankinhalt / Tankvolumennutzbar; // Aktueller Tankinhalt nach Füllstand in %

  // Die 4 Helligkeitswerte, Berechnung der Helligkeitswerte, Relais und die Endschalterzustände zu Testzwecken an den PC übertragen
  static unsigned long lastprint;
  if (millis() - lastprint > 3000) // Testausgabe alle 3s
  {
    lastprint = millis();
    Serial.print ("Füllhöhe im mm:"); Serial.println(Fuellstand); // Füllhöhe im mm
    Serial.print ("Gesamtvolumen des Tanks im dm³:"); Serial.println(Tankvolumengesamt); // Gesamtvolumen des Tanks im dm³
    Serial.print ("Nutzbares Tankvolumen im dm³:"); Serial.println(Tankvolumennutzbar); // Nutzbares Tankvolumen im dm³
    Serial.print ("Aktueller Tankinhalt nach Füllstand im dm³:"); Serial.println(Tankinhalt); // Aktueller Tankinhalt nach Füllstand im dm³
    Serial.print ("Aktueller Tankinhalt nach Füllstand in %:"); Serial.println(Tankinhaltprozent); // Aktueller Tankinhalt nach Füllstand in %
    Serial.print ("VZ1:"); Serial.println(VZ1);
    Serial.print ("VZ2:"); Serial.println(VZ2);
    Serial.print ("VZ3:"); Serial.println(VZ3);
    Serial.print ("VZ4:"); Serial.println(VZ4);
    Serial.print ("RK1:"); Serial.println(RK1);
    Serial.print ("VK1:"); Serial.println(VK1);
    Serial.print ("VK2:"); Serial.println(VK2);
    Serial.print ("VK3:"); Serial.println(VK3);
    Serial.print ("VK4:"); Serial.println(VK4);
    Serial.print ("VK5:"); Serial.println(VK5);
    Serial.print ("VK6:"); Serial.println(VK6);
    Serial.print ("VK7:"); Serial.println(VK7);
  }
}

Es liegt an der leider falschen Annahme, das alles in normalen "int" rechnen zu können.
Hier geht es los:

 int VZ1 = ((PI * (Zylinderraduis * Zylinderraduis) * Zylinderhoehe) / 1000000); // Zylindervolumengesamt ohne Überlauf im dm³

Alleine Zylinderraduis * Zylinderraduis ist bei einem Startwert von 875 schon 765625 und damit etwas über dem maximal positivem int von 32767.

Und wie kann man das Lösen?

Die härteste Tour wäre, alle Deine Werte auf float umzustellen. Das ist auf den Arduinos etwas laufzeit-intensiv, aber Du hast ja keine Schleusenkammer, sodaß sich der Wert nicht sooo schnell ändert.

Ansonsten würde ich versuchen, die Formeln so umzustellen und zusammenzufassen, dass Du alle Werte, die sich nie ändern (weil sich die Geometrie des Tanks ja auch nicht ändert), außerhalb berechnest und dann nur noch ein wenig beim Einrechnen der aktuellen Füllhöhe zu tun hast.

PI sollte übrigens in der math.h schon als M_PI definiert sein.

Moin,

Nutze die Zahlen und Variablen gut aus.
Was heisst das?
Du musst nicht unbedingt SI konform rechnen, du kannst auch mit anderen Einheiten rechnen damit zu z.B. rechenintensive float Operationen vermeiden kannst.
Dazu schreibe bitte mal die Formel auf und die zu erwartenden min-max Werte aller Eingabeparameter.
Dann schaust du dir an welche Zahlen dabei rauskommen.
Und dann schaust du dir an welche Variablen es für deinen Controller gibt und wie große deren Wertebereich sind.
Du dann baust du es so, dass es passt.

Daruf kann aber auch jeder selber kommen.

PI sollte übrigens in der math.h schon als M_PI definiert sein.

Bei Arduino ist auch PI schon definiert.
Und wenn man schon die Funktion sq(Zylinderraduis) aufruft, sollte man natürlich mit dem double (oder float) Ergebnis weiterrechnen.

Selbst bei einer Schleusenkammer wäre eine float-Rechnung noch schnell genug :slight_smile:

Und außerdem:

int VZ1 = ((PI * sq(Zylinderraduis) * Zylinderhoehe) / 1000000); // Zylindervolumen

Das ist eine Konstante, die nicht bei jedem loop-Durchlauf ausgerechnet werden muss, sondern die du aus deiner Excel Tabelle abschreiben könntest. Oder zumindest einmal in setup, weil der Compiler leider kein SQRT kann. (Nur als Beispiel)

Formeln:

VZ1 = PI*r²*h1 = 5724,57dm³
VZ2 = (r²*l*(ARCCOS(1-h2/r)-(1-h2/r)*WURZEL(h/r*(2-h2/r)))) = 120,90dm³
VZ3 = VZ1 - VZ2 = 5603,67
VZ4 = V=(r²*l*(ARCCOS(1-h3/r)-(1-h3/r)*WURZEL(h3/r*(2-h3/r)))) = min. 1,00dm³ - max. ca. 2736dm³

RK1 = (a²+ h²)/(2*h) = 1107,40dm³
VK1 = (PI/3)*h²*(3*r-h) = 444,92dm³
VK2 = VK1 * 2 = 889,84
VK3 = (PI/3)*h²*(3r-h) = 30,50dm³
VK4 = VK3 * 2 = 61,00dm³
VK5 = VK2 - VK4 = 828,84dm³
VK6 = PI/3*h²*(3r-h) = min. ca. 0,00dm³ - max. ca.1850,45dm³
VK7 = VK6 * 2 = min. 0,00dm³ - max. 3700,90dm³

@michael_x
Mit den Konstanten hast du recht. Die könnte man doch unter VOID SETUP setzen oder? Konstant sind:
VZ1, VZ2, VZ3, RK1, VK1, VK2, VK3, VK4, VK5

newpv:
@michael_x
Mit den Konstanten hast du recht. Die könnte man doch unter VOID SETUP setzen oder? Konstant sind:
VZ1, VZ2, VZ3, RK1, VK1, VK2, VK3, VK4, VK5

Bin zwar nicht Michael, aber: Ja.

Konstant sind:
VZ1, VZ2, VZ3, RK1, VK1, VK2, VK3, VK4, VK5

Wenn Du nun drauf bestehst, mit exakt diesen Variablen zu arbeiten, würde das schon weiterhelfen (allerdings auch diesmal in float statt int).

  int Tankvolumengesamt = VZ1 + VK2; // Gesamtvolumen des Tanks im dm³
  int Tankvolumennutzbar = VZ3 + VK5; // Nutzbares Tankvolumen im dm³
  int Tankinhalt = VZ4 + VK7; // Aktueller Tankinhalt nach Füllstand im dm³

Von diesen sind die ersten beiden ebenfalls konstant. Tankvolumengesamt brauchst Du für die Funktion selbst nirgendwo - die Prozentangabe speist sich ja aus dem nutzbaren Volumen.