Funktion um Temperaturkuve darzustellen

Im Rahmen meines informationstechnologischen Projekts an der technischen Hochschule Köln erstelle ich ein Umweltkontrollsystem auf Basis eines Arduino Unos.

Dieser ist in der Lage für jeden Tag in jedem Monat eines Jahres einen zufälligen Max. und Min. Wert zu generieren und diesen in einem Arry abzuspeichern. Diese ganzen Arrys ergeben dann meine Datenbank.

Außerdem ist er in der Lage Temperaturen auszulesen und diese auch in Arrys abzuspeichern.

Also haben wir nun eine Ist-Temperator, eine TagesMax-Temperatur (Soll), eine TagesMin-Temperatur (Soll). Außerdem sind wir in der Lage die Zeit auszulesen, wann gemessen wurde (quasi wie späht ist es).

Was ich als nächstes versuche ist eine Funktion aufzustellen, die diese TagesMax-Temperatur und TagesMin-Temperatur als Parameter aufnimmt und aus ihnen eine mathematische Funktion aufstellt die den Temperaturverlauf am Tag beschreibt. Hierfür nehme ich einfach an, dass die TagesMin-Temperatur kurz vor Sonnenaufgang erreicht wird und die TagesMax-Temperatur 12 Stunden später. So sollte sich eine einigermaßen schöne kurve ergeben die der Arduino nutzen kann um zu schauen, zu welcher Uhrzeit es wie warm sein sollte.
Die beiden Parameter aggieren hierbei logischerweiße als Extrema. Als return wird dann ein errechneter Temperaturwert (Soll) zurück gegeben.
Ich war leider nie der große Mathecrack ... daher suche ich hier nach konstruktiven Vorschlägen. Diese können auch gerne ganz von meinen Vorstellungen abweichen, sofern die Datenbank so wie sie ist beibehalten wird.

Hier mein bisheriger Quelltext (abgespeckt auf vier Monate im Jahr und ohne auslesen des Temperaturwertes)

int MaxTemp[4]={26,28,28,25};
int MinTemp[4]={20,20,19,11};

int SollMax[30];
int SollMin[30];

int TempMaxJan[30],    TempMinJan[30],
    TempMaxFeb[30],    TempMinFeb[30],
    TempMaxMaer[30],   TempMinMaer[30],
    TempMaxApr[30],    TempMinApr[30];
     

void generator(int TempMax, int TempMin, int Monat1);
void linker(int Monat2);


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

  for (short j=0; j<=3; j++) {
    generator(MaxTemp[j],MinTemp[j],j);   //<-- Hier wird die Datenbank erstellt
   } 
}


void loop() {
  
  int i;
  
  Serial.println("-Welchen Monat moechten sie gerne einsehen?");  
  
  while(Serial.available()==0); 
  int eingabe=Serial.parseInt();
  
  linker(eingabe);  //<-- siehe weiter unten

  Serial.println("Max.  Min.");  //<-- Zur Kontrolle ob generiert wurde 
  for (i=0; i<30; i++) {
    Serial.print(SollMax[i]);
    Serial.print("    ");
    Serial.println(SollMin[i]);
  }
}

void generator(int TempMax, int TempMin, int Monat1) {
  short i;

  switch (Monat1) {
    case 0:
      for (i=0; i<30; i++) {
        TempMaxJan[i]=random(TempMax*0.8,TempMax);
        TempMinJan[i]=random(TempMin,TempMin*1.2); }
        break; 

    case 1:
      for (i=0; i<30; i++) {
        TempMaxFeb[i]=random(TempMax*0.8,TempMax);
        TempMinFeb[i]=random(TempMin,TempMin*1.2); }
        break; 
    
    case 2:
      for (i=0; i<30; i++) {
        TempMaxMaer[i]=random(TempMax*0.8,TempMax);
        TempMinMaer[i]=random(TempMin,TempMin*1.2); }
        break; 

    case 3:
      for (i=0; i<30; i++) {
        TempMaxApr[i]=random(TempMax*0.8,TempMax);
        TempMinApr[i]=random(TempMin,TempMin*1.2); }
        break; 
  }
}

void linker(int Monat2) {   
  short i;
  
  switch (Monat2) {
    case 1:
      Serial.println("-Januar");
      for (i=0; i<30; i++) {
        SollMax[i]=TempMaxJan[i];
        SollMin[i]=TempMinJan[i]; }
    break;  

    case 2:
      Serial.println("-Februar");
      for (i=0; i<30; i++) {
        SollMax[i]=TempMaxFeb[i];
        SollMin[i]=TempMinFeb[i]; }
    break;  

    case 3:
      Serial.println("-Maerz");
      for (i=0; i<30; i++) {
        SollMax[i]=TempMaxMaer[i];
        SollMin[i]=TempMinMaer[i]; }
    break;  

    case 4:
      Serial.println("-April");
      for (i=0; i<30; i++) {
        SollMax[i]=TempMaxApr[i];
        SollMin[i]=TempMinApr[i]; }
    break;  
  }
}

Weitere Fragen werden natürlich sehr gerne beantwortet!

Wieso zufällige Werte für die 2*365 Tagesmaxima/Minima ?
Und wie zufällig sollen sie denn bitteschön sein? ( Eine beliebige Zahl zwischen -30 und +60 ? )

Wie möchtest du den "Soll-Tagesverlauf" interpolieren?

Hierfür nehme ich einfach an, dass die TagesMin-Temperatur kurz vor Sonnenaufgang erreicht wird und die TagesMax-Temperatur 12 Stunden später. So sollte sich eine einigermaßen schöne kurve ergeben die der Arduino nutzen kann um zu schauen, zu welcher Uhrzeit es wie warm sein sollte.

Bis auf die erste ("Min kurz vor Sonnenaufgang") sind deine anderen Annahmen ("Max 12 Stunden nach Sonnenaufgang", "schöne Kurve", "nutzbar durch Arduino") ziemlich fragwürdig.

Nimm doch einfach den Temeraturverlauf des Vortags und korrigiere durch die Differenz zwischen Aktueller Temperatur und der Temperatur vor 24h.

Ein Arduino Uno mit 2kB RAM ist übrigens eine ziemlich ungeschickte Plattform für solch eine "Datenbank".

Hierfür nehme ich einfach an, dass die TagesMin-Temperatur kurz vor Sonnenaufgang erreicht wird

Diese Annahme ist meines Wissen nach falsch. Normalerweise wird die TagesMin-Temperatur (kurz) NACH Sonnenaufgang erreicht, denn das System (Sonneneinstrahlung ... Lufterwärmung ... bzw. Abkühlung) ist etwas träge. Dasselbe gilt wohl auch für die Tageshöchsttemperatur, wobei diese natürlich noch von etlichen anderen Fakorten (Wolkendecke etc.) abhängig ist.

michael_x:
Wieso zufällige Werte für die 2*365 Tagesmaxima/Minima ?
Und wie zufällig sollen sie denn bitteschön sein? ( Eine beliebige Zahl zwischen -30 und +60 ? )

Wie zufällig diese Werte sein sollen, kann man in der Funktion "generator" sehen. Dort wird die Funktion random mit den Grenzen MaxTemperatur eines Monats (Obergrenze) und MaxTemperatur eines Monats *0.8 (Untergrenze). Sehr zufällig sind die Werte in der Tat nicht, da random immer wieder die selben Zufallszahlen generiert, jedoch unterscheiden sich die Werte untereinander in den jeweiligen Schleifen für die Monate. Das reicht mit vollkommen aus.

Bis auf die erste ("Min kurz vor Sonnenaufgang") sind deine anderen Annahmen ("Max 12 Stunden nach Sonnenaufgang", "schöne Kurve", "nutzbar durch Arduino") ziemlich fragwürdig.

Dann hab ich mich wohl schlecht ausgedrückt, sorry.

Anders gesagt, die Funktion die ich schreiben möchte soll eine mathematische Funktion dritten grades (y=ax^3+bx^2 +cx+d) aufstellen, dessen graphischer verlauf ähnlich einer Sinusfunktion ist. In diesem Sinusgraphen wäre der Tiefpunkt mein Sonnenaufgang (sagen wir x1=6 Uhr) und der Hochpunkt der Moment am Tag, an dem die Sonne am nahsten zur Erde steht (sagen wir x2=12 Uhr). Somit hätte man genug Informationen um zum Beispiel nach dem gaußsches Eliminationsverfahren eine Funktion aufzustellen. Diese wären:

f(6)=TempMinWert (wobei 6 für 6 Uhr steht)
f(12)=TempMaxWert (wobei 12 für 12 Uhr steht)
f'(6)=0
f'(12)=0

Wie bereits gesagt, bin ich leider leider kein mathecrack ... aber soweit ich mich erinnern kann, reichen vier Angaben einer Funktion dritten Grades um diese zu beschreiben. Nur wie bringe ich das dem Mr Uno nur bei ...

Diese Annahme ist meines Wissen nach falsch. Normalerweise wird die TagesMin-Temperatur (kurz) NACH Sonnenaufgang erreicht, denn das System (Sonneneinstrahlung ... Lufterwärmung ... bzw. Abkühlung) ist etwas träge. Dasselbe gilt wohl auch für die Tageshöchsttemperatur, wobei diese natürlich noch von etlichen anderen Fakorten (Wolkendecke etc.) abhängig ist.

Danke uxomm, ich glaube da war mal was ^^

Oh_Ce:
Hierfür nehme ich einfach an, dass die TagesMin-Temperatur kurz vor Sonnenaufgang erreicht wird und die TagesMax-Temperatur 12 Stunden später.

Wenn Du sonst keine Daten (z.B. vom DWD) vorliegen hast, dürfte es ziemlich gut geraten sein, dass die Tagestiefsttemperatur statisch gesehen bei Sonnenaufgang liegt.

Aber zu raten, dass die Tageshöchsttemperatur 12 Stunden nach Sonnenaufgang liegt, dürfte statistisch ziemlich daneben liegen. Statistisch gesehen wird die Tageshöchsttemperatur wohl eher ca. 2 Stunden nach dem Tageshöchststand der Sonne erreicht.

Im übrigen verstehe ich bei Deinem Projekt nur Bahnhof.

Warum sollte ein "Umweltkontrollsystem" irgendwelche "zufälligen Max. und Min. Werte generieren" wollen? Willst Du die Umwelt kontrollieren oder ein Roulettesystem entwickeln?

Außerdem brauchst Du die voraussichtlichen Tageshöchst- und Tiefsttemperaturen des nachfolgenden Tages nicht zu raten: Für Deutschland gibt zum Beispiel der Deutsche Wetterdienst DWD täglich Wettervorhersagen heraus, die bei den Höchst- und Tiefsttemperaturen des kommenden Tages (meistens) relativ genau zutreffen.

Im übrigen folgt der Tagestemperaturverlauf keiner konstanten mathematischen Funktion, sondern der Temperaturverlauf hängt immer vom Wetter ab: Es gibt Tage, da ist es morgens wärmer als abends. Es gibt Tage, da ist es nachts wärmer als tagsüber. Dass es bei Sonnenaufgang am kühlsten und gegen 14 Uhr am wärmsten ist, mag im statistischen Mittel zutreffen, aber das Wetter folgt nicht einfach mathematischen Kurven.

Es handelt sich wahrscheinlich nur um eine Test-Funktion um die Datenbank mit Daten zu füllen. Sehr praktisch bei solchen Langzeit Sachen. Dann muss nicht erst eine Messreihe machen um die Auswertung zu testen.

@Jurs

Da gebe ich dir recht. Die Aussage, dass die Tagesmaximaltemperatur 12 Stunden nach Sonnenaufgang erreicht wird, war ein kleiner Denkfehler ... es sollte statt 12 Stunden ca 6 Stunden stehen (also so um die Mittagszeit). Ich hatte mich aber auch in meinem zweiten Post korrigiert :slight_smile:

Das mit den Zufallswerten musst du so verstehen. Ich möchte gleich zu beginn des Programmablaufs eine Datenbank generieren. Wieso diese erst generieren und nicht gleich eintippen? Wäre mir erstens zu viel arbeit und zweitens zu leicht gelöst. Daher muss diese erst generiert werden. Jedoch braucht der Arduino ja irgendwelche Richtwerte/Grenzen an denen er sich beim generieren orientieren kann. Diese gebe ich ihm gleich zu beginn des Programmablaufs (siehe Quelltext). Anhand dieser Richtwerte/Grenzen, wird dann die Datenbank gefüllt.

By the way. Bitte in den Code blicken. Vielleicht verstehst du dann auch mehr als Bahnhof. Dieser verrät einiges und ist relativ leicht gehalte. Sind einfach nur einige Schleifen die rechnen und Werte übergeben.

Oh_Ce:
By the way. Bitte in den Code blicken. Vielleicht verstehst du dann auch mehr als Bahnhof. Dieser verrät einiges und ist relativ leicht gehalte. Sind einfach nur einige Schleifen die rechnen und Werte übergeben.

Ja klar blicke ich Deinen Code:

Du definierst riesige Integer-Arrays für jeweils 30 Tage pro Monat (übrigens: Es gibt auch Monate, die haben 31 Tage, und der Februar hat 28 oder 29 Tage), und läßt so eine Art Roulettezahlengenerator laufen, um die Arrays mit fiktiven "Temperaturen" zu füllen.

Dazu gibt es noch eine "linker()" Funktion, die die generierten Zufallszahlen eines Monats in andere Arrays umzukopiert, z.B. für Januar:

for (i=0; i<30; i++) 
{
        SollMax[i]=TempMaxJan[i];
        SollMin[i]=TempMinJan[i]; 
}

Abgesehen davon, dass Du bei 12 Monaten zu je 30(?) Tagen mit je 2 Tageswerten Min/Max bereits 720 Integer-Werte hast, die von den 2048 Bytes Deines UNO-RAMs bereits 1440 Bytes RAM verbrauchen, erschließt sich für mich der tiefere Sinn noch immer nicht.

Oh_Ce:
Anders gesagt, die Funktion die ich schreiben möchte soll eine mathematische Funktion dritten grades (y=ax^3+bx^2 +cx+d) aufstellen, dessen graphischer verlauf ähnlich einer Sinusfunktion ist.

Davon kann ich in Deinem Code so rein gar nichts entdecken.

Und von der Beschreibung her kann ich nicht sehen, was die Funktion approximieren soll: Die Temperaturkurve eines einzelnen Tages? Das wären dann pro Jahr 365 verschiedene Approximationsfunktionen mit unterschiedlichen Parametern für a, b, c, und d, die dann mehr oder weniger genau den Temperaturverlauf dieses einen Tages beschreiben, für den die Approximation berechnet wurde.

Und warum? Die Temperaturen folgen üblicherweise dem Wetter und nicht irgendwelchen mathematischen Kurven?!

Abgesehen davon, dass Du bei 12 Monaten zu je 30(?) Tagen mit je 2 Tageswerten Min/Max bereits 720 Integer-Werte hast, die von den 2048 Bytes Deines UNO-RAMs bereits 1440 Bytes RAM verbrauchen, erschließt sich für mich der tiefere Sinn noch immer nicht.

Das ist in der Tat so, daher hab ich das ganze ja auch auf 4 Monate runter gespeckt. Das mit den 12 Monaten war mein erster Gedanke zu Projektbegin. 4 Monate tun es aber genau so gut.

Du definierst riesige Integer-Arrays für jeweils 30 Tage pro Monat (übrigens: Es gibt auch Monate, die haben 31 Tage, und der Februar hat 28 oder 29 Tage), und läßt so eine Art Roulettezahlengenerator laufen, um die Arrays mit fiktiven "Temperaturen" zu füllen.

Danke für den hilfreichen Hinweiß ... es ist mir bewusst, dass auch die Tagesanzahl der Monate nicht der realität entsprechen. Garnicht schlimm für mich. Ich hab hier absichtlich die variaton der Tage in den Monaten raus gelassen um das ganze etwas unkomplexer darzustellen.

Quote from: Oh_Ce on Today at 04:20 pm

Anders gesagt, die Funktion die ich schreiben möchte soll eine mathematische Funktion dritten grades (y=ax^3+bx^2 +cx+d) aufstellen, dessen graphischer verlauf ähnlich einer Sinusfunktion ist.

Davon kann ich in Deinem Code so rein gar nichts entdecken.

Richtig ... ließ bitte nochmal .... "die Funktion die ich schreiben möchte". Genau dafür suche ich hier ja die Hilfe :wink: ich bin selber nicht in der Lage solch eine Funktion zu schreiben.

Was ich als nächstes versuche ist eine Funktion aufzustellen, die diese TagesMax-Temperatur und TagesMin-Temperatur als Parameter aufnimmt und aus ihnen eine mathematische Funktion aufstellt die den Temperaturverlauf am Tag beschreibt

Der Graph hätte nur 2 Stützstellen (lineares Polynom), woher kommen die Werte für eine Funktion dritter Ordnung ?
Ich verstehe wohl die Frage nicht wirklich.

Oh_Ce:
Richtig ... ließ bitte nochmal .... "die Funktion die ich schreiben möchte". Genau dafür suche ich hier ja die Hilfe :wink: ich bin selber nicht in der Lage solch eine Funktion zu schreiben.

Und warum möchtest Du das machen, wenn Du offenbar

  • weder ausreichende Mathematikkenntnisse
  • noch ausreichende Programmierkenntnisse
    dafür hast?

Warum das?

Warum belegst Du nicht erstmal Vorlesungen wie "Mathematik I" und "Mathematik II" an einer Uni und ggf. gleich noch einen "EDV Grundkurs C/C++-Programmierung", damit Du wenigstens ein paar der notwendigen theoretischen Grundlagenkenntnisse hast?

Anyway: Deine kubische Funktion f(x)=ax^3+bx^2+cx+d hat 4 unbekannte Koeffizienten (a, b, c, d) und daher benötigst Du vier Gleichungen, um das Gleichungssystem zu lösen. Die zu erfüllenden Gleichungen ergeben sich aus folgenden vier Vorgaben:
1.) Tiefsttemperatur bei Sonnenaufgang
2.) Steigung der Kurve bei Tiefsttemperatur = 0
3.) Höchsttemperatur bei (Zeit des höchsten Sonnenstands+2h)
4.) Steigung der Kurve bei Höchsttemperatur = 0

Gesuchte Funktion: f(x)=ax^3+bx^2+cx+d
Steigung der gesuchten Funktion: f'(x)=3ax^2+2bx+c (erste Ableitung der gesuchten Funktion)

Unter der Annahme:
Lokale Zeit Deutschland UTC+1h (entsprechend 15° östlicher Länge
und dass Du die Berechnung für eine Position auf Längengrad 10° vornehmen möchtest, liegt der höchste Sonnenstand um 20 Minuten nach der lokalen Mittagszeit von 12:00 Uhr, also bei 12:20.
Annahme: Datum 21.03. (Frühlingsanfang) mit Sonnenaufgang also um 06:20 Uhr.
und zur Zeitberechnung Verwendung von "Minuten seit Mitternacht"
ergeben sich folgende Gleichungen:

Für x= 380 (06:20 Uhr = 380 Minuten nach Mitternacht)
1.) Tiefsttemperatur = a* 380^3+b380^2+c380+d
2.) 0 = 3a380^2+ 2b380+c

Für x=740 (12:20 Uhr = 740 Minuten nach Mitternacht)
3.) Höchsttemperatur = a* 740^3+b740^2+c740+d
4.) 0 = 3a740^2+ 2b740+c

Bei bekannter Tiefst- und Höchsttemperatur sind das 4 Gleichungen mit 4 Unbekannten (a,b,c,d), d.h. es gibt eine eindeutige Lösung.

Auflösen und fertig ist "die Gleichung des Tages", bei der Du dann eine Zeitangabe ("Minuten nach Mitternacht") in diese Gleichung einsetzen und damit eine Temperatur ausrechnen kannst.

rudirabbit:
Der Graph hätte nur 2 Stützstellen (lineares Polynom), woher kommen die Werte für eine Funktion dritter Ordnung ?

Aus den Bedingungen, dass es bei "Höchsttemperatur" und "Tiefsttemperatur" in der Kurve eine waagerechte Tangente gibt (Steigung = 0). Dadurch bekommst Du ein Gleichungssystem aus vier Gleichungen mit vier Unbekannten. Zwei Gleichungen basieren auf den Temperaturwerten, und zwei Gleichungen auf der bekannten Steigung (=0) bei diesen Funktionswerten. Das reicht zur Lösung aus.

Allerdings ist mir unklar, was er dann eigentlich mit der Lösung machen möchte. Den tatsächlichen Temperaturverlauf des Tages bekommt er aus nur zwei ermittelten Temperaturen, zu denen der Zeitpunkt auch nur "geraten" ist, jedenfalls nicht. Das gibt keine Mathematik der Welt her. Er kann zwar eine Funktion ermitteln, aber alles was die an Temperaturen zu bestimmten Zeitpunkten ausrechnen kann, wären "Lügenwerte", die mehr oder weniger zutreffen können. Oder auch nicht.

Denn tatsächlich weiß er über den Temperaturverlauf des Tages nichts, wenn er nur zwei Temperaturwerte hat. Und ausrechnen kann er sich die Werte nachträglich auch nur insoweit, als die gemachten Annahmen (z.B. für den Zeitpunkt der Tiefst-/Höchsttemperatur) tatsächlich zutreffen, einschließlich der Annahme, der Verlauf würde einer kubischen Parabel folgen.

1.) Tiefsttemperatur bei Sonnenaufgang
2.) Steigung der Kurve bei Tiefsttemperatur = 0
3.) Höchsttemperatur bei (Zeit des höchsten Sonnenstands+2h)
4.) Steigung der Kurve bei Höchsttemperatur = 0

Dies ist wohl der Knackpunkt, wenn man das verstehen soll.

jurs wäre ein guter Mathelehrer, oder ist er einer :wink: jedenfalls kann er sehr gut erklären.

Warum belegst Du nicht erstmal Vorlesungen wie "Mathematik I" und "Mathematik II" an einer Uni und ggf. gleich noch einen "EDV Grundkurs C/C++-Programmierung", damit Du wenigstens ein paar der notwendigen theoretischen Grundlagenkenntnisse hast?

Keine Sorge die Grundkenntnisse sitzen. Mir fällt es nur nicht so leicht mich kurz und trotzdem gut auszudrücken. Sorry nochmal an dieser Stelle.

Tip top danke für die ausführliche Umschreibung :slight_smile: ich war gerade noch nebenbei zufällig das selbe auf Papier am lösen und habe mal versucht das Ergebnis anzuhängen.

Allerdings ist mir unklar, was er dann eigentlich mit der Lösung machen möchte.

Die Lösung, sprich ein Temperaturwert der errechnet und returnt wird soll dann mit einem vom Sensor gemessenm Wert verglischen werden, wobei der Sensor sich in einem Gewächshaus befindet dessen Umwelt wir dann kontrollieren und regeln.

Den tatsächlichen Temperaturverlauf des Tages bekommt er aus nur zwei ermittelten Temperaturen, zu denen der Zeitpunkt auch nur "geraten" ist, jedenfalls nicht

Richtig. Ich möchte aber auch garnicht den tatsächlichen Temperaturverlauf simulieren, sondern einen begrenzt zufälligen Temperaturverlauf (begrenzt in dem Sinne, weil es Grenzen gibt zwischen denen diese zufallszahlen generiert werden. Soooooo zufällig sind diese also garnicht nicht). Dass das Ganze nicht der Realität entspricht, verstehe ich. Es reicht für unser Projekt jedoch vollkommen aus. Also nehmen wir an, dass der Temperaturverlauf nur abhängig vom Sonnenverlauf ist. Außerdem nehmen wir an, dass für jeden Tag im Januar z.b. immer zur selben Zeit die Sonne untergeht und auch zur selben Zeit wieder aufgeht. Lediglich von Monat zu Monat varieren wir etwas. Entspricht auch nicht der realität, klar, reicht uns aber aus.

Um also nochmal zurück zu kommen, was die Funktion können soll, konnte ich jetzt auf Papier zusammenfassen. Jedoch nur was die mathematik angeht. Wie bring ich das jetzt nur dem Arduino bei? O.O

Meine ersten Gedanken wären sowas wie

int kurven_check(int Max, int Min) {

int x1=6; //Sonnenaufgang
int x2=12; //kürzester Abstand zur Sonne
int a,b,c,d;
int x; //aktuelle Uhrzeit

}

Jedoch wie ich programmiere, was passieren soll und wie was errechnit wird, weiß ich leider nicht.
Ich habe hier die Zeitangabe absichtlich in Stunden gelassen, da es reicht, stündliche Werte zu übergeben. Ich weiß auch nicht ob dem Uno die Rechnerei mit Minutenzahlen so leicht fällt, da diese, wenn man sie immer ab Mitternacht misst, doch sehr groß werden könnten.

Es gibt doch sicher den ein oder anderen, der seinen Arduino auch mal ordentlich hat rechnen lassen ^^ und vielleicht kann mir dieser Jemand ein paar Tipps geben, wie man das lösen kann. Vielleicht gibt es ja eine Biblio. die man sich includen könnte. Wäre jedoch nicht das non plus Ultra, da ich es doch gerne selber tippen würde.

Vielleicht kann mir jurs ja nochmal aushelfe? Danke übrigends!

Sorry an die, die es lesen möchte. Die Qualli musste leider runter ...

Ich hab auch gleich die Funktion mal plotten lassen. Gefällt mir auch noch nicht so ganz ... nach dem Erreichen des Hochpunktes fällt die Temperatur zu schnell und erreicht lauf der Funktion noch vor 24h den Nullpunkt, was sowieso garnicht hätte sein sollen ... da muss ich wohl noch einiges überdenken.

Oh_Ce:
Keine Sorge die Grundkenntnisse sitzen. Mir fällt es nur nicht so leicht mich kurz und trotzdem gut auszudrücken. Sorry nochmal an dieser Stelle.

Tip top danke für die ausführliche Umschreibung :slight_smile: ich war gerade noch nebenbei zufällig das selbe auf Papier am lösen und habe mal versucht das Ergebnis anzuhängen.

Wie löst Du denn ein lineares Gleichungssystem mit 4 Gleichungen und 4 unbekannten auf Papier?

Auf Anhieb fallen mir da erstmal nur zwei Methoden ein:

  • Einsetzungsverfahren
  • Gausssches Eliminationsverfahren

Auf Computer wird meist das Gausssche Eliminationsverfahren verwendet, ggf. mit kleinen Modifikationen, mit denen vermieden wird, dass durch extrem kleine Gleitkommawerte dividiert werden muss, was zu recht großen Fehlern führen kann.

Oh_Ce:
Wie bring ich das jetzt nur dem Arduino bei? O.O

Ein großes Problem löst Du üblicherweise dadurch, dass Du es zuerst mal auf mehrere kleine Probleme aufteilst.

Die Teilprobleme wären dabei:

  • Zeit des Sonnenaufgangs und Zeitpunkt des Sonnenhöchststands berechnen
  • Aus der vorgegebenen Tiefst-/Höchsttemperatur und den Zeitpunkten: 4 Gleichungen mit 4 Unbekannten aufstellen
  • Gleichungssystem lösen mit Hilfe des Gausschen Eliminationsverfahrens

Oh_Ce:
Ich weiß auch nicht ob dem Uno die Rechnerei mit Minutenzahlen so leicht fällt, da diese, wenn man sie immer ab Mitternacht misst, doch sehr groß werden könnten.

Da der Tag 1440 Minuten hat, ist "Minuten seit Mitternacht" immer eine Zahl im Bereich 0 bis 1439.
Damit kann ein Arduino sehr gut rechnen.

Aber wenn Dir das lieber ist, kannst Du stattdessen auch in Stunden rechnen, aber dann ist die Zeitangabe immer eine Gleitkommazahl. Z.B. 6:30 Uhr wäre 6,5 h, oder 6:15 Uhr wäre 6,25 h, oder 6:20h wäre 6,333h.

Ob Du Zeiten in ganzzahlige "Minuten seit Mitternacht" umrechnest oder in eine gebrochen Rationale Zahl "Stunden seit Mitternacht", ist dem Arduino egal. Hauptsache ist, dass die Tageszeit im Gleichungssystem in einer einzigen Zahl angegeben wird.

Oh_Ce:
Vielleicht gibt es ja eine Biblio. die man sich includen könnte. Wäre jedoch nicht das non plus Ultra, da ich es doch gerne selber tippen würde.

Musst Du mal schauen, was es da gibt, als einfachen C-Algorithmus für das Gausssche Eliminationsverfahren. Muss ja nur für 4x4 Matrizen sein (4 Gleichungen / 4 Unbekannte).

Eine Library für Matrixrechnung auf dem Arduino habe ich im Playground gesehen:
http://playground.arduino.cc/Code/MatrixMath
Davon kann man bestimmt irgendwas verwenden.

Große Genauigkeitsanforderungen scheinst Du ja nicht zu haben, oder?
Also beispielsweise bei der Sonnenaufgangszeit?
Wenn man sich beispielsweise für Deinen Ort 24 Werte für das ganze Jahr ausrechnet, jeweils Sonnenaufgangszeit und Sonnenhöchststand für die erste und zweite Monatshälfte.

Ich bin mir auch nicht sicher, ob Du mit einer Parabel 3. Ordnung als Approximation überhaupt hinkommst: Denn so eine Parabel hat ja nur einen einzigen Wendepunkt. Ich vermute mal, dass man damit allenfalls die Temperatur für einen halben Tag halbwegs approximieren kann, und zwar jeweils vom Minumum (Sonnenaufgang) bis Maximum (2h nach Sonnenhöchststand). Und für die Zeit dazwischen müßte man nochmal appromimieren, von Maximum (2h nach Sonnenhöchststand) bis Minimum (Sonnenaufgang des nachfolgenden Tages). Also nicht 365 Gleichungen pro Jahr, sondern 730 Gleichungen pro Jahr, die gelöst und deren Koeffizienten berechnet werden müßten. Also pro Tag:

  • eine Gleichung von Sonnenaufgang bis Sonnenhöchststand +2h
  • eine Gleichung von Sonnenhöchststand +2h bis Sonnenaufgang am Folgetag
    Sonst wirst Du mit einer Parabel 3. Ordnung nichts.

Wie löst Du denn ein lineares Gleichungssystem mit 4 Gleichungen und 4 unbekannten auf Papier?

Nach dem gaussschen Eliminationsverfahren hatte ich das gelöst. Aus dem TagesMax 28°C und dem TagesMin 15°C ergab sich folgende Funktion: y=-(26/576)*x^3+(52/36)*x^2-(74,75/6)*x+47,5
Diese beschreibt ausreichend den Temperaturverlauf zwischen kur vor Sonnenaufgang und kurz nach Sonnenhochpunkt. Leider nicht mehr.

Ich bin mir auch nicht sicher, ob Du mit einer Parabel 3. Ordnung als Approximation überhaupt hinkommst: Denn so eine Parabel hat ja nur einen einzigen Wendepunkt. Ich vermute mal, dass man damit allenfalls die Temperatur für einen halben Tag halbwegs approximieren kann, und zwar jeweils vom Minumum (Sonnenaufgang) bis Maximum (2h nach Sonnenhöchststand). Und für die Zeit dazwischen müßte man nochmal appromimieren, von Maximum (2h nach Sonnenhöchststand) bis Minimum (Sonnenaufgang des nachfolgenden Tages). Also nicht 365 Gleichungen pro Jahr, sondern 730 Gleichungen pro Jahr, die gelöst und deren Koeffizienten berechnet werden müßten. Also pro Tag:

  • eine Gleichung von Sonnenaufgang bis Sonnenhöchststand +2h
  • eine Gleichung von Sonnenhöchststand +2h bis Sonnenaufgang am Folgetag
    Sonst wirst Du mit einer Parabel 3. Ordnung nichts.

Vor dem Problem stehe ich im Moment richtig. Ich hoffe, das wird dem Arduino nicht zu viel aber ich werde es versuchen über zwei Gleichungen zu lösen.

Ein großes Problem löst Du üblicherweise dadurch, dass Du es zuerst mal auf mehrere kleine Probleme aufteilst.

Die Teilprobleme wären dabei:

  • Zeit des Sonnenaufgangs und Zeitpunkt des Sonnenhöchststands berechnen
  • Aus der vorgegebenen Tiefst-/Höchsttemperatur und den Zeitpunkten: 4 Gleichungen mit 4 Unbekannten aufstellen
  • Gleichungssystem lösen mit Hilfe des Gausschen Eliminationsverfahrens

Das hab ich soweit per Hand schon geschafft. Wie bringe ich dem Arduino jedoch bei Gleichungen zu speichern geschweige davon damit zu rechnen und zu lösen? Ich geh mal davon aus, dass der Arduino selber nicht weiß wie er zu rechnen hat. Also müsste ich ihm die Rechenschritte die ich per Hand löse, ihm beibringen? oder geht das doch eleganter?

Da der Tag 1440 Minuten hat, ist "Minuten seit Mitternacht" immer eine Zahl im Bereich 0 bis 1439.
Damit kann ein Arduino sehr gut rechnen.

Aber wenn Dir das lieber ist, kannst Du stattdessen auch in Stunden rechnen, aber dann ist die Zeitangabe immer eine Gleitkommazahl. Z.B. 6:30 Uhr wäre 6,5 h, oder 6:15 Uhr wäre 6,25 h, oder 6:20h wäre 6,333h.

Ob Du Zeiten in ganzzahlige "Minuten seit Mitternacht" umrechnest oder in eine gebrochen Rationale Zahl "Stunden seit Mitternacht", ist dem Arduino egal. Hauptsache ist, dass die Tageszeit im Gleichungssystem in einer einzigen Zahl angegeben wird.

Thx! *Daumen hoch

Oh_Ce:
Das hab ich soweit per Hand schon geschafft. Wie bringe ich dem Arduino jedoch bei Gleichungen zu speichern geschweige davon damit zu rechnen und zu lösen? Ich geh mal davon aus, dass der Arduino selber nicht weiß wie er zu rechnen hat. Also müsste ich ihm die Rechenschritte die ich per Hand löse, ihm beibringen? oder geht das doch eleganter?

Mal ganz allgemein gesprochen, Du hast exemplarisch ein Gleichungssystem aus 4 Gleichungen mit den 4 Unbekannten a, b, c, d, z.B. alle 4 Gleichungen mit ihren Koeffizienten so untereinander aufgeschrieben:

  0 * a  +10 * b + 0 * c +12 * d =  -6
  4 * a  -5  * b - 2 * c - 8 * d = -17
  0 * a  -5  * b + 0 * c  -4 * d = -23
  4 * a  -10 * b + 0 * c  -16* d =   2

dann brauchst Du nicht "die Gleichungen" speichern, sondern Du speicherst "die Koeffizienten", und zwar einmal die Koeffizienten einer 4x4 Matrix in einem zweidimensionalen Array:

float mKoeff[4][4]={
 { 0, 10,  0, 12},
 { 4, -5, -2, -8},
 { 0, -5,  0,  -4},
 { 4,-10,  0,-16},
};

Und die Koeffizienten des Vektors auf der rechten Seite:

float vKoeff[4]={-6, -17, -23, 2};

Und gerechnet wird dann nicht "mit Gleichungen", sondern Berechnungen finden ausschließlich zwischen den Koeffizienten der Matrix und des Vektors statt, die über ihren Index im Array adressiert werden.

Und dazu wäre eine fertige Library für Matrix- und Vektorrechnung nicht schlecht. Und wenn möglich, gleich eine Library, die auch den Algorithmus für das Gausssche Eliminationsverfahren beherrscht.

Dann ist das einfach nur noch stures Number-Crunching und am Ende fällt ein Ergebnisvektor mit 4 Werten dabei heraus: Deine gesuchten Unbekannten für a, b, c und d in Deiner Gleichung.

Also was mathematisch eine "Matrix" ist, ist in der Programmiersprache C ein zweidimensionales Array.

Und was mathematisch ein "Vektor" ist, ist in der Programmiersprache C ein einfaches Array.

Matrix- und Vektorrechnung gehört eigentlich schon in der gymnasialen Oberstufe zu den Mathe-Themen.
Hier kann man es dann mal praktisch anwenden.

Wobei es fraglich ist, ob Du mit der Parabel 3. Ordnung wirklich so viel besser liegst als mit einer einfachen linearen Interpolation:
06:20 == 15°
14:20 == 28°
Anstieg (Steigung der Temperaturkurve als Gerade betrachtet) = 13°/8h = 1,625°/h

Also Temperatur von 10:20 ==> 15° + 4h*1,625°/h = 21.5°
So eine lineare Interpolation zwischen Sonnenaufgang/Tiefsttemperatur und der Höchsttemperatur bei Sonnenhöchststand+2h wäre deutlich einfacher zu berechnen.

Aber einen geraden (linearen) Temperaturverlauf als "Lügenwerte" zu interpolieren reicht Dir nicht?

Deine Lügenwerte sollen unbedingt als "Lügenwerte dritter Ordnung" berechnet sein?

Wobei es fraglich ist, ob Du mit der Parabel 3. Ordnung wirklich so viel besser liegst als mit einer einfachen linearen Interpolation:
06:20 == 15°
14:20 == 28°
Anstieg (Steigung der Temperaturkurve als Gerade betrachtet) = 13°/8h = 1,625°/h

Also Temperatur von 10:20 ==> 15° + 4h*1,625°/h = 21.5°
So eine lineare Interpolation zwischen Sonnenaufgang/Tiefsttemperatur und der Höchsttemperatur bei Sonnenhöchststand+2h wäre deutlich einfacher zu berechnen.

Aber einen geraden (linearen) Temperaturverlauf als "Lügenwerte" zu interpolieren reicht Dir nicht?

Deine Lügenwerte sollen unbedingt als "Lügenwerte dritter Ordnung" berechnet sein?

Lineare Interpolation war auch mein letzter Gedanken gestern Abend vor dem schlafen gehen und ich glaube ich werde auch zunächst diese Methode ausprobieren. Leichter zu errechnen ist es denke ich alle Male. Wichtig für uns ist einfach nur, dass sich etwas verändert (hier wäre das die SollTemperatur zu einer bestimmten Zeit) und dass darauf eine Aktion folgt (Wenn unter SollTemperatur -> aufheitzen Wenn über SollTemperatur -> abkühlen). Ob die Veränderung realitätsnah ist, spielt keine Rolle für meinen Prof.

Trotzdem nochmal ein großes Lob für die gute und ausführliche Beschreibung! Ich merke das ganze über zwei Funktionen dritter Ordnung zu lösen bedarf einer aufwendigen Programmierung und dabei würden sie nicht mal unbedingt effizienter arbeiten als eine lineare Interpolation hab ich das richig verstanden?

Oh_Ce:
Trotzdem nochmal ein großes Lob für die gute und ausführliche Beschreibung! Ich merke das ganze über zwei Funktionen dritter Ordnung zu lösen bedarf einer aufwendigen Programmierung

Nochmal kurz den Lösungsweg gegoogelt: Nein, wenn Du die von mir bereits erwähnte Library für Matrix-Mathematik verwendest, ist der Aufwand eigentlich mathematisch gesehen nicht besonders hoch. Nur handwerklich vom Programmieren her hätte man schon deutlich mehr zu tun als bei einer einfachen linearen Interpolation.

Wie eine Matrix datenmäßig in eine solche Form (2D-Array) gebracht wird, dass Computer damit rechnen können, hatte ich ja bereits in meinem letzten Posting gezeigt. Hier nun der Lösungsweg:

Du hast also ein Gleichungssystem dargestellt als "Matrix ist gleich Vektor", oder kurz:
M = V

Wenn Du diese Gleichung nun so umformen könntest, dass die Matrix links in die "Einheitsmatrix" umgewandelt dasteht, würde rechts Deine Lösung stehen. Die Einheitsmatrix ist ja bekanntlich die Matrix, bei der die Hauptdiagonale mit einsen besetzt ist und alle übrigen Koeffizienten sind null. Also die 4x4 Einheitsmatrix ist:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Übersetzt in das Gleichungssystem also
1a + 0b + 0c + 0d = z1
0a + 1b + 0c + 0d = z2
0a + 0b + 1c + 0d = z3
0a + 0b + 0c + 1d = z4

D.h. die Lösung wäre dann: a= z1, b=z2, c=z3, d=z4

Wie wandeln wir nun eine x-beliebige Matrix in die Einheitsmatrix um?
Das machen wir mit der "inversen Matrix". Die inverse Matrix M-1 ist so definiert:
Multipliziert man die inverse Matrix mit der ursprünglichen Matrix, dann ergibt sich als Produkt die Einheitsmatrix:

M-1 * M = Einheitsmatrix

Und wenn man auf beiden Seiten der Gleichung dasselbe macht, ist es dasselbe.
So wird aus
M = V
durch Multiplikation mit der inversen Matrix
M-1 * M = M-1 * V
Also steht auf der linken Seite vom Gleichheitszeichen die Einheitsmatrix.
Und wenn wir auf der rechten Seite Matrix mal Vektor ausmultiplizieren, haben wir die Lösung.

Glücklicherweise hat die von mir bereits erwähnte MatrixMath-Library alles notwendige dabei:

  • eine Funktion zum Invertieren einer Matrix: int MatrixInvert(float* A, int n);
  • eine Funktion zum Multiplizieren von Matrizen: void MatrixMult(float* A, float* B, int m, int p, int n, float* C);

Also mathematisch gesehen ist der Drops für mich gelutscht:

  • Gleichungssystem aus Matrix und Vektor aufstellen.
  • invertieren der Matrix mit Hilfe der MatrixMath Library
  • die inverse Matrix mit dem Vektor auf der rechten Seite multiplizieren und haben die Lösung
    (also die Koeffizienten a,b,c,d unserer Parabel dritter Ordnung)

Oh_Ce:
und dabei würden sie nicht mal unbedingt effizienter arbeiten als eine lineare Interpolation hab ich das richig verstanden?

Wenn die Grundannahmen zutreffen, könnte die Parabel 3.Ordnung besser sein. Also die Annahme, dass die Tiefsttemperatur kurz vor Sonnenaufgang herrscht. Das mag an klaren und sonnigen Sommertagen so sein. Aber wenn es z.B. im Winter +10 Grad hat und es rauscht ab Mitternacht eine Kaltfront heran: Dann hast Du um Mitternacht +10° und es wird von Stunde zu Stunde kälter, den ganzen Tag über, und um 23:59 Uhr des Tages hast Du nur noch +2°C, praktisch linear abnehmend. Wenn Du jetzt aber nur die beiden Temperaturwerte hast und annimmst, Du hättest um 07:00 Uhr (statt 23:59) die Tiefsttemperatur gehabt und Du hättest um 14:00 Uhr (statt 00:00) Höchsttemperatur gehabt, dann rechnest Du den ganzen Tag über voll falsche Temperaturen aus. Also je nach Wetterlage kann Deine Annahme über den Tagestemperaturverlauf zutreffen. Oder der tatsächliche Temperatur kann an manchen Tagenentgegengesetzt laufen wie Du es angenommen hast. Die Annahmen sind nur "statistisch vernünftig" und füren im statistischen Durchschnitt dazu, dass für eine gewisse Anzahl an (klaren und sonnigen) Tagen im Jahr, der tatsächliche Temperaturverlauf einigermaßen genau simuliert wird. Aber an etlichen anderen Tagen eben auch nicht, weil das Wetter bei Deinen Annahmen nicht mitspielen muss.

Deinen bisherigen Quellcode habe ich mir auch nochmal angesehen, dabei ist mir folgendes aufgefallen: Wenn Du sowieso mit Zufallsdaten für die täglichen Temperaturextrema arbeitest, und die Temperatur-Simulation dann nur für einen Tag berechnet und ausgegeben werden soll, dann brauchst Du beim Programmstart gar nicht komplett alle Temperaturwerte für ein ganzes Jahr generieren und zwischenspeichern (was erhebliche Mengen RAM verbraucht).

Es reicht, das alles in einer Schleife abzuarbeiten und immer nur EINEN TAG zur Zeit zu simulieren, für diesen Tag die Zufallstemperaturen zu erzeugen, die Simulationsformel zu berechnen, und die Formel anzuwenden um eine Tabelle auszugeben.

D.h. um eine Simulationsformel für einen Tag des Jahres zu bekommen und dessen Temperaturkurve im (angenommenen) Tagesverlauf zu berechnen, brauchst Du auch nur die Temperaturwerte dieses Tages zwischenspeichern, aber nicht die Temperaturwerte der übrigen 364 Tage des Jahres. Also den RAM effektiv nutzen, indem nur das in Variablen im RAM gehalten wird, was zu diesem Zeitpunkt zur Berechnung notwendig ist. Für den nächsten Tag würde man dann eben neue Werte entweder erfinden (random()) oder laden (z.B. von SD-Karte).

Immer schön RAM-Speicher sparen. Der UNO hat nur 2048 Bytes RAM. Einzelne Bytes, und nicht KiloBytes oder gar MegaBytes.

Es reicht, das alles in einer Schleife abzuarbeiten und immer nur EINEN TAG zur Zeit zu simulieren, für diesen Tag die Zufallstemperaturen zu erzeugen, die Simulationsformel zu berechnen, und die Formel anzuwenden um eine Tabelle auszugeben.

Das klingt sehr interessant. Ähnlich war ja auch meine Idee, nur habe ich dann das Problem, dass wenn man die Funktion random() aufruft, immer wieder die selbe Zufallszahl generiert wird. random() arbeitet soweit ich weiß nunmal mit Grenzen (zwischen diesen Grenzen wird dann die Zufallszahl generiert) und da für einen Monat immer wieder die selben Grenzen verwendet werden, wird immer wieder der selbe Max und Min Wert für einen Tag generiert (da random beim aufrufen immer nur eine Zahl generiert und dann wieder raus geht aus der Funktion. Beim nächsten mal aufrufen für den selben Monat aber einen anderen Tag, bleiben logischerweiße die Grenzen die selbe und random() generiert wieder die selben Max und Min Werte wie beim vorherigen Tag im selben Monat).

Wenn ich das umgehen kann, würde ich versuchen die "Datenbank" raus zu lassen. Dass die RAM knapp werden und der Arduino dann nicht mehr richtig rechnen mag, ist mir auch schon aufgefallen ... doof, dass ich leider beim Uno bleiben muss .... aber für jedes Problem gibt es ja eine Lösung :slight_smile:

Ich schau mal ob es da nicht die Möglichkeit gibt, "zufälligere" Zahlen zu generieren als mit random(). Ich meine mal etwas von RandomSeed() gelesen zu haben. Weiß aber nicht mehr so genau wie dieser arbeitet.