Barometischer Luftdruck- Tendenz dazu

Hallo, ich suche einen "einfachen" Weg mir eine Luftdrucktendenz zu programmier. Einen Tagesverlauf des Luftdruck zu erstellen ist nicht so schwierig, aber wie bastel ich mir eine 3Std. Tendenz? Es sollte im Groben so ablaufen: Taste drücken, aktuellen (Start)Luftdruck merken, Zeit merken. Nach 3 Std, (End)Luftdruck merken, Zeit merken, Differenz berechnen. Das bekomme ich alles hin. Nur wie komme ich auf die 3Std? Millis möchte ich nicht zählen, die können überlaufen. Gefällt mir nicht. Mir stehen Std, Min und Sek zur Verfügung. Ich könnte die 3 Std. über "Modulo" zu fassen bekommen, das funktioniert ohne Probleme. Nur wenn ich um 16:00h die Taste drücke, dann geht das nicht mehr auf. Ich könnte die Minuten zählen, ändert sich die Minute, 1 hochzählen. Wenn ich 180 habe, Stempel setzen. Erscheint mir aber etwas umständlich. Hat da jemand einen Tip? Gruß und Dank Andreas

Ich hatte mir mal eine Temperatur-tendezanzeige gebastelt.

Der Code ist schon älter, daher sicherlich verbesserungsfähig.
Es gibt im System eine globale Variable GT_akt, die die aktuelle gefilterte Temperatur enthält.
und in der loop eine 1 sek Zeitscheibe, in der die Funktion Tendenzerkennung() aufgerufen wird.

Die Funktion ist so:
Nach Ablauf von einer Minute (bei dir 3h) liest die Funktion 5 Werte und bildet daraus einen Mittelwert. (weil die Funktion nur einmal pro Sekunde aufgerufen wird, haben die 5 Werte jeweils 1 sek Abstand. Damit sollen Störer eliminiert werden)
Dieser Mittelwert wird mit dem Mittelwert von vor 1 Minute (3h) verglichen
innerhalb Toleranzband: konstant, oberhalb:steigend, unterhalb fallend. (ich habe nur diese drei Zustände der Tendenz, die mit Pfeilen auf Display angezeigt werden. man kann es natürlich auch numerisch auswerten)

Das funktioniert ganz gut und ist sicherlich leicht an deine Zwecke anzupassen.

/*******************************************************************************************
** Funktion Tendenzerkennung                                                              **
** wertet die Steigung der Temperatur GT aus und setzt entsprechend                       **
** den Wert von GT_Tendenz                                                                **
** Zur Berechnung wird ein Durchschnittwert Avg gebildet, auf diesen mit dem Abstand      **
** "Band" eine obere und untere Grenze (OG, UG) gebildet, mit der nach einer Minute die	  **
** Temperatur verglichen wird. Um schwingen zu vermeiden, wird OG und UG mit einer 	  **
** Hysterese beaufschlagt.      							  **
**       										  **
** input: void                                                                            **
** output: void (nothing)                                                                 **
** Genutzte globale Variablen: GT_akt, GT_Tendenz                                         **
*******************************************************************************************/

void Tendenzerkennung(){
  static double _GT_Avg, _GT_Avg_alt;   
  static unsigned long timer1=0;
  static int i = 0;
  #define Anz_Vergleichswerte 5   // aus wie vielen Werten soll jeweils der Mittelwert gebildet werden
  #define Band 0.3                           // Toleranzband: innerhalb wird die Änderung als gleich bewertet.
  
   if (millis()> timer1 )    // Aufruf erst wieder nach 60000ms
   {  _GT_Avg = _GT_Avg + GT_akt;    // Summe über "Anz_Vergleichswerte" Werte für Mittelwertbildung
      i++;
      if (i >= Anz_Vergleichswerte){         
         timer1  = millis()+60000;               // timer neu setzen für Wiederaufruf in 60sek 
        _GT_Avg = _GT_Avg / Anz_Vergleichswerte; // Mittelwertbildung
        i = 0;          
        if (_GT_Avg > _GT_Avg_alt + Band){     // Vergleich des Mittelwertes mit dem von vor 60sec.
          GT_Tendenz = 2;
        } else if (_GT_Avg < _GT_Avg_alt - Band){
          GT_Tendenz = 0;
        } else {
          GT_Tendenz = 1;
        }
        _GT_Avg_alt = _GT_Avg;                 // Speichern des akuelle Wertes
        _GT_Avg = 0;                            // Rücksetzen
      }
   }      
}  // end funktion Tendenzerkennung

SkobyMobil: aber wie bastel ich mir eine 3Std. Tendenz? Es sollte im Groben so ablaufen: Taste drücken, aktuellen (Start)Luftdruck merken, Zeit merken. Nach 3 Std, (End)Luftdruck merken, Zeit merken, Differenz berechnen.

Willst Du eine 3-Stunden-Tendenz nur mit einer zeitlichen Auflösung von 3 Stunden ermitteln?

Üblicherweise wird eine 3-Stunden-Tendenz mindestens stündlich, meist aber mit höherer zeitlicher Auflösung ermittelt.

Dieser Minimalstandard (stündlich) würde bedeuten, dass Du immer zur vollen Stunde den aktuellen Luftdruck speicherst, und zwar immer den aktuellen Wert und für drei Stunden rückwirkend. Der aktuelle Wert minus der Wert vor drei Stunden wäre die 3-Stunden-Tendenz. In dem Fall dann immer für eine Stunde derselbe Wert, bis zur nächsten vollen Stunde neu gerechnet wird.

Statt zur vollen Stunde kannst Du die Tendenz aber auch in kürzeren Zeitabständen ermitteln, z.B. vierstelstundenweise oder zehnminütlich. Speichern müßtest Du dann immer die letzten 3 Stunden, also bei 10-Minuten-Werten 3*6 = 18 Werte. Und alle 10 Minuten speicherst Du einen neuen Wert und ermittelst als Tendenz den Wert "jetzt" minus den Wert "vor 3 Stunden".

Am einfachsten geht so etwas mit einer Datenstruktur namens "Ringpuffer", in die man neue Werte reinschieben und die ältesten Werte auslesen kann.

Millis möchte ich nicht zählen, die können überlaufen. Gefällt mir nicht.

Mit millis() kannst du alle Zeitintervalle bis zu 49 Tagen machen. Auch wenn der Arduino schon jahrelang ohne Unterbrechung läuft. Zum Abspeichern in einer Log-Datei ist natürlich ein echtes Datum schöner, zum Zählen sicher nicht. Ausser du denkst an die kommende Sommerzeit-Umschaltung und willst heimlich ein 2 Stunden Intervall in deiner 3 Stunden-Aufstellung haben. Das gefällt mir nicht.

BTW. Millis läuft nach 49 Tagen über und es ist trotzdem zu handeln wenn du unsigned long nutzt denn wenn du bei unsined long 4.294.967.295 +1 REchnest bist du bei 0 und wenn du 0-1 rechnset bistt du bei 4.294.967.295. Deswegen ist das Handling recht easy. Ich würden einen Taktmeker erzeugen alle 60s. Die Takte hochzählen nach 180 Takten deine Berechnung so hast du die sicherheit das es maximal 1s beim überlauf deneben geht also 2h:59min:59s oder 3h:00min:01s Das denke ist auch genau genug. Gruß Der Dani

Hallo, ihr drei die TemperaturTendenz ist ja nicht schlecht, wie das geht ist mir schon klar. Nur sie arbeitet mit "Millis"- möchte ich aber nicht. Millis werden hier ziemlich oft benutzt, aber der Überlauf nur sehr selten abgefangen. Ich glaube ich muss mich damit mal beschäftigen, damit ich weiß was bei einem Überlauf zu beachten ist. Viel Dank für Deine Mühe.

Den Wert der letzten 3ten Stunde speichern und mit dem aktuellen zu vergleichen wäre wohl ein wenig falsch. Ich dachte an ein "gemittel", aber der Gedanke mit dem "Kreislauf" (Ringpuffer, kenne ich nicht) ist nicht schlecht. Man hätte zu jeder Zeit den aktuellen 3 Stunden Wert. Das muss ich mir mal anschauen. Diese 3Std Rechnerei würde dann ja entfallen, ich bräuchte dann ja nur einen Intervall (10min, 15min, 1Std.) abzufangen. Gruß und Dank Andreas

Hallo, das mit den Millis kaufe ich euch noch nicht ab, das muss ich mir einmal anschauen. Eine "Taktgeber" habe ich ja, die 0-Min und die 0-Sek. Die bräuchte ich nur hochzählen. Nachdem ich aber jurs seinen Beitrag gelesen habe, bin ich mir nicht mehr so sicher ob ich das überhaupt brauche. Diese "Ringpuffer" Geschichte gefällt mir immer mehr. Gruß und Dank Andreas

Du kannst auch gern mit einem kleineren Zähler spielen: Ein Byte läuft schon bei 255 über.

 255+1 = 0 
 255+2 = 1
  1-255 = 2

Wenn du das byte jede Sekunde eins hochzählst, kannst du schön zugucken:

#define INTERVALL 60  //   Wir machen einen Minutenzyklus auf der Basis des bmillis Sekundentakts 
byte bmiilis;  // der überlaufende Zähler
void sekundentakt()
{
   static byte alt;
    if ( bmillis - alt >= INTERVALL )
    {
         alt = bmillis;
         // jede Minute:
         Serial.print( " sec = " ); Serial.println( millis() / 1000);
         Serial.print( "bmillis = "); Serial println(bmillis);
    }
}

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

void loop() {
   static unsigned long sekunde;
    if ( millis() - sekunde >= 1000) 
   {   // jede Sekunde einmal 
            bmillis++;   // wir simulieren einen überlaufenden millis() Zähler mit dem wir Intervalle bis 255 sec realisieren 
           sekunde += 1000;  //  Wann sekunde oder millis() überläuft, ist genauso egal wie bei bmillis 
       
           sekundentakt();  // könnte auch mehrmals oder nur jede 2. sekunde drankommen ( ähnlich wie loop und millisekunden )
   }
}

SkobyMobil: Hallo, das mit den Millis kaufe ich euch noch nicht ab, das muss ich mir einmal anschauen.

Das ist schlicht Blödsinn, natürlich funktioniert das. Wobei das ehrlicherweise mit der oben von mir geposteten alten Funktion nicht sauber gelöst ist, aber wenn du es in der Form machst

if (millis() - Timestamp > intervall){
  Timestamp = millis();
  ...

dann geht das ohne Probleme beim Überlauf.

Es gibt übrigens noch eine andere Möglichkeit: du bildest einen digitalen Tiefpass (entspricht gleitendem Durchschnitt) avg = ((avg * Filterfaktor) + akt) / (Filterfaktor+1); die Zeitkonstante des Tiefpasses Tau = Filterfaktor * Abtastrate. Wenn du alle 10sek einen Wert mißt bist du einem Filterfaktor von 1000 bei etwa 3h. damit kannst du dann deine aktuellen Werte vergleichen.

Hallo, wenn man doch nicht immer die Fehler der anderen ausbügeln müßte…

Ist ja eine nette Spielerei. Und das soll mit überlaufenden Millis genau so einfach und sicher sein? Vielleicht sollte ich Millis einmal probieren.

Das mit der Luftdruck-Tendenz ist noch nicht so klar, ich habe noch nicht raus- bekommen wie die WetterFritzen es machen- und, ob der tatsächliche Luftdruck verwendet wird oder der errechnete NN-Luftdruck. Gruß und Dank Andreas

Hallo, ich kann am Arduino gerade mal eine LED blinken lassen- und Du kommst mit digitalem Tiefpass und Filter. Gruß, Dank und Spaß Andreas

SkobyMobil: Hallo, ich kann am Arduino gerade mal eine LED blinken lassen- und Du kommst mit digitalem Tiefpass und Filter. Gruß, Dank und Spaß Andreas

Dann solltest du vielleicht denen glauben, die einen Wissensvorsprung haben und schon zwei LEDs blinken lassen können. Weiterhin viel Spaß.

Hallo,
ich habe hier einmal Millis() gefummelt.
Das soll funktionieren? An 24Std/360Tg?

Mit einem Intervall von 2 Sek wird der Zähler um 1 inkrementiert.

long Timestamp = 1;
long intervall = 2000;
int Zaehler = 1;


void setup()    
{ 
  Serial.begin(19200);
}

void loop()

{  
if (millis() - Timestamp > intervall)  
 {
   
  Timestamp = millis();
  
if (Timestamp)
{
(Zaehler++);
} 
  Serial.print("Zaehler ");
  Serial.println(Zaehler);
  
  if (Zaehler == 12)
  {
  (Zaehler = 0);
 }
}}

Gruß und Dank
Andreas

SkobyMobil: ich habe hier einmal Millis() gefummelt. Das soll funktionieren? An 24Std/360Tg?

Nein. Die Intervallabfrage funktioniert 24/360 wenn Du Timestamp "unsigned long" deklarierst;

unsigned long Timestamp = 0;

Und diese Abfrage ist überflüssiger Ballast:

if (Timestamp)

Dieser Ausdruck ist immer true, wenn Timestamp ungleich Null ist.

Die Abfrage kannst Du Dir sparen, weil Du ja bereits im Codeblock für "if (millis() - Timestamp > intervall)" drin bist, und dieser Codeblock wird nur dann ausgeführt, wenn das Intervall abgelaufen ist.

Hallo, ich habe das mal geändert, macht Sinn. Andreas sagt, Danke schön.

Hallo, als Information:

Nach telefonischer Rückfrage, mit einem Meteorloge des DWD in Frankfurt; Für die Tendenz gültig: Die Werte für den Luftdruck werden am Sensor gemessen. Dieser Wert wird zu Grunde gelegt- also nicht verrechnet.

Die Werte werden immer zur vollen Stunde gemessen. Nicht nur in der BRD, sondern Welt weit. Wenn um 13:00h gemessen wird, beginnt die 1 Stunden Tendenz um 14:00h. Wenn die Tendenz um 14:22h angezeigt wird , benötigt oder sonst was- dann ist die Tendenz bezogen auf den Wert von 14:00h. Es werden immer die Werte, die zur vollen Stunde gemessen werden- zu Grunde gelegt. Es werden KEINE Zwischenwerte ausgewertet oder aufgezeichnet, hier nicht- wie auch Welt weit nicht. Gruß und Spaß Andreas