zambretti forecast

Ciao a tutti,

sto cercando di mettere a punto un pezzo di codice che dovrà occuparsi di generare delle previsioni meteo a breve termine(12 H) , alla base di questo calcolo c'è il metodo zambretti ideato il secolo scorso. Bene vi mostro il codice (che in una versione più semplice funziona già bene su altro mio progetto) ma che sto cercando di migliorarlo con l'altra teoria delle previsioni: quella del cambiamento pressione ogni 3h.

Allego file e poi specifico il problema.

zambretti_forecast.ino (25.2 KB)

l'algoritmo per funzionare ha bisogno che ogni 3 ore i dati vengano campionati con questa logica:

inizio fascia 1: leggo ogni 10 minuti e per 3 volte la pressione , poi dopo circa 3 ore rileggo altri 3 valori. Faccio le rispettive medie e poi determino la tendenza della pressione. Bene ho difficoltà a gestire in un modo migliore i momenti precisi in cui effettuare le letture. Al momento ho scritto pezzo blocco ma oltre a essere brutto è pure non funzionante:

// previsione delle h. 3:00
  if (now.hour() * 60 + now.minute() + now.second() > 0 && now.hour() * 60 + now.minute() + now.second() <= 2) pressureArray[0] = p_icon; // lettura  00:00
  if (now.hour() * 60 + now.minute() + now.second() > 10 && now.hour() * 60 + now.minute() + now.second() <= 12) pressureArray[1] = p_icon; // lettura  00:10
  if (now.hour() * 60 + now.minute() + now.second() > 20 && now.hour() * 60 + now.minute() + now.second() <= 22) pressureArray[2] = p_icon; // lettura  00:20

  if (now.hour() * 60 + now.minute() + now.second() > 160 && now.hour() * 60 + now.minute() + now.second() <= 162) pressureArray[3] = p_icon; // lettura  02:40
  if (now.hour() * 60 + now.minute() + now.second() > 170 && now.hour() * 60 + now.minute() + now.second() <= 172) pressureArray[4] = p_icon; // lettura  02:50
  if (now.hour() * 60 + now.minute() + now.second() > 178 && now.hour() * 60 + now.minute() + now.second() <= 180) pressureArray[5] = p_icon; // lettura  02:58

  // previsione delle h. 6:00
  if (now.hour() * 60 + now.minute() + now.second() > 182 && now.hour() * 60 + now.minute() + now.second() <= 184) pressureArray[0] = p_icon; // lettura 03:00
  if (now.hour() * 60 + now.minute() + now.second() > 190 && now.hour() * 60 + now.minute() + now.second() <= 192) pressureArray[1] = p_icon; // lettura 03:10
  if (now.hour() * 60 + now.minute() + now.second() > 200 && now.hour() * 60 + now.minute() + now.second() <= 202) pressureArray[2] = p_icon; // lettura 03:20

  if (now.hour() * 60 + now.minute() + now.second() > 340 && now.hour() * 60 + now.minute() + now.second() <= 342) pressureArray[3] = p_icon; // lettura 05:40
  if (now.hour() * 60 + now.minute() + now.second() > 350 && now.hour() * 60 + now.minute() + now.second() <= 352) pressureArray[4] = p_icon; // lettura 05:50
  if (now.hour() * 60 + now.minute() + now.second() > 358 && now.hour() * 60 + now.minute() + now.second() <= 360) pressureArray[5] = p_icon; // lettura 05:58

  // previsione delle h. 9:00
  if (now.hour() * 60 + now.minute() + now.second() > 362 && now.hour() * 60 + now.minute() + now.second() <= 364) pressureArray[0] = p_icon; // lettura 06:00
  if (now.hour() * 60 + now.minute() + now.second() > 370 && now.hour() * 60 + now.minute() + now.second() <= 372) pressureArray[1] = p_icon; // lettura 06:10
  if (now.hour() * 60 + now.minute() + now.second() > 380 && now.hour() * 60 + now.minute() + now.second() <= 382) pressureArray[2] = p_icon; // lettura 06:20

  if (now.hour() * 60 + now.minute() + now.second() > 520 && now.hour() * 60 + now.minute() + now.second() <= 522) pressureArray[3] = p_icon; // lettura 08:40
  if (now.hour() * 60 + now.minute() + now.second() > 530 && now.hour() * 60 + now.minute() + now.second() <= 532) pressureArray[4] = p_icon; // lettura 08:50
  if (now.hour() * 60 + now.minute() + now.second() > 538 && now.hour() * 60 + now.minute() + now.second() <= 540) pressureArray[5] = p_icon; // lettura 08:58

  // previsione delle h. 12:00
  if (now.hour() * 60 + now.minute() + now.second() > 542 && now.hour() * 60 + now.minute() + now.second() <= 544) pressureArray[0] = p_icon; // lettura 09:00
  if (now.hour() * 60 + now.minute() + now.second() > 550 && now.hour() * 60 + now.minute() + now.second() <= 552) pressureArray[1] = p_icon; // lettura 09:10
  if (now.hour() * 60 + now.minute() + now.second() > 560 && now.hour() * 60 + now.minute() + now.second() <= 562) pressureArray[2] = p_icon; // lettura 09:20

  if (now.hour() * 60 + now.minute() + now.second() > 700 && now.hour() * 60 + now.minute() + now.second() <= 702) pressureArray[3] = p_icon; // lettura 11:40
  if (now.hour() * 60 + now.minute() + now.second() > 710 && now.hour() * 60 + now.minute() + now.second() <= 702) pressureArray[4] = p_icon; // lettura 11:50
  if (now.hour() * 60 + now.minute() + now.second() > 718 && now.hour() * 60 + now.minute() + now.second() <= 720) pressureArray[5] = p_icon; // lettura 11:58

  // previsione delle h. 15:00
  if (now.hour() * 60 + now.minute() + now.second() > 722 && now.hour() * 60 + now.minute() + now.second() <= 724) pressureArray[0] = p_icon; // lettura 12:00
  if (now.hour() * 60 + now.minute() + now.second() > 730 && now.hour() * 60 + now.minute() + now.second() <= 732) pressureArray[1] = p_icon; // lettura 12:10
  if (now.hour() * 60 + now.minute() + now.second() > 740 && now.hour() * 60 + now.minute() + now.second() <= 742) pressureArray[2] = p_icon; // lettura 12:20

  if (now.hour() * 60 + now.minute() + now.second() > 880 && now.hour() * 60 + now.minute() + now.second() <= 882) pressureArray[3] = p_icon; // lettura 14:40
  if (now.hour() * 60 + now.minute() + now.second() > 890 && now.hour() * 60 + now.minute() + now.second() <= 892) pressureArray[4] = p_icon; // lettura 14:50
  if (now.hour() * 60 + now.minute() + now.second() > 898 && now.hour() * 60 + now.minute() + now.second() <= 900) pressureArray[5] = p_icon; // lettura 14:58

  // previsione delle h. 18:00
  if (now.hour() * 60 + now.minute() + now.second() > 902 && now.hour() * 60 + now.minute() + now.second() <= 904) pressureArray[0] = p_icon; // lettura 15:00
  if (now.hour() * 60 + now.minute() + now.second() > 910 && now.hour() * 60 + now.minute() + now.second() <= 912) pressureArray[1] = p_icon; // lettura 15:10
  if (now.hour() * 60 + now.minute() + now.second() > 920 && now.hour() * 60 + now.minute() + now.second() <= 922) pressureArray[2] = p_icon; // lettura 15:20

  if (now.hour() * 60 + now.minute() + now.second() > 1060 && now.hour() * 60 + now.minute() + now.second() <= 1062) pressureArray[3] = p_icon; // lettura 17:40
  if (now.hour() * 60 + now.minute() + now.second() > 1070 && now.hour() * 60 + now.minute() + now.second() <= 1072) pressureArray[4] = p_icon; // lettura 17:50
  if (now.hour() * 60 + now.minute() + now.second() > 1078 && now.hour() * 60 + now.minute() + now.second() <= 1080) pressureArray[5] = p_icon; // lettura 17:58

  // previsione delle h. 21:00
  if (now.hour() * 60 + now.minute() + now.second() > 1082 && now.hour() * 60 + now.minute() + now.second() <= 1084) pressureArray[0] = p_icon; // lettura 18:00
  if (now.hour() * 60 + now.minute() + now.second() > 1090 && now.hour() * 60 + now.minute() + now.second() <= 1092) pressureArray[1] = p_icon; // lettura 18:10
  if (now.hour() * 60 + now.minute() + now.second() > 1100 && now.hour() * 60 + now.minute() + now.second() <= 1102) pressureArray[2] = p_icon; // lettura 18:20

  if (now.hour() * 60 + now.minute() + now.second() > 1240 && now.hour() * 60 + now.minute() + now.second() <= 1242) pressureArray[3] = p_icon; // lettura 20:40
  if (now.hour() * 60 + now.minute() + now.second() > 1250 && now.hour() * 60 + now.minute() + now.second() <= 1252) pressureArray[4] = p_icon; // lettura 20:50
  if (now.hour() * 60 + now.minute() + now.second() > 1258 && now.hour() * 60 + now.minute() + now.second() <= 1260) pressureArray[5] = p_icon; // lettura 20:58

  // previsione delle h. 24:00
  if (now.hour() * 60 + now.minute() + now.second() > 1262 && now.hour() * 60 + now.minute() + now.second() <= 1264) pressureArray[0] = p_icon; // lettura 21:00
  if (now.hour() * 60 + now.minute() + now.second() > 1270 && now.hour() * 60 + now.minute() + now.second() <= 1272) pressureArray[1] = p_icon; // lettura 21:10
  if (now.hour() * 60 + now.minute() + now.second() > 1280 && now.hour() * 60 + now.minute() + now.second() <= 1282) pressureArray[2] = p_icon; // lettura 21:20

  if (now.hour() * 60 + now.minute() + now.second() > 1420 && now.hour() * 60 + now.minute() + now.second() <= 1422) pressureArray[3] = p_icon; // lettura 23:40
  if (now.hour() * 60 + now.minute() + now.second() > 1430 && now.hour() * 60 + now.minute() + now.second() <= 1432) pressureArray[4] = p_icon; // lettura 23:50
  if (now.hour() * 60 + now.minute() + now.second() > 1438 && now.hour() * 60 + now.minute() + now.second() <= 1440) pressureArray[5] = p_icon; // lettura 23:58

avete idee su come fare?

Grazie mille

Un primo problema è che trasformi le ore in minuti ma poi aggiungi i secondi così come sono... O trasformi tutto in secondi oppure dividi i secondi per 60.
Oppure non considerare i secondi...

Poi non ti conviene fare il conto e metterlo in una variabile e confrontare quella? Così se devi cambiare il conto modifichi solo una riga invece di qualche decina.

Grazie ci provo...

Ero interessato anche io all'algoritmo Zambretti per un mio prossimo progettino, ma non ho ancora approfondito.
Fammi sapere come si comporta e se ci azzecca!!

Per quanto riguarda il salvataggio delle pressioni con la schedulazione di cui hai bisogno, tieni conto che quando si parla di tempo con calcolatori elettronici è sempre una pessima idea fare i conti con il tempo in formato "human readable" ovvero ore, minuti, secondi, perché si complica inutilmente la gestione ed i calcoli.

E' molto più efficiente rappresentare il tempo nel formato Unix Timestamp, ovvero il numero di secondi trascorsi dal 01/01/1970 00:00:00
La conversione in formato human readable, andrebbe usata solo quando è necessario rappresentare il tempo a beneficio delle persone (ma guarda un po' ;D :smiley: 8)) come ad esempio monitor, seriale, display lcd etc etc.

In altre parole, ti basta un'unica variabile unsigned long che confronti con il valore attuale unix time (dipende dalla libreria RTC che stai usando, ma sicuro c'è la funzione per estrarre il valore unix time) per fare tutto quello che è necessario.
Nel tuo caso specifico, hai bisogno solo di definire 2 intervalli di tempo fissi: uno di 10 minuti (600 secondi) e l'altro di 3 ore (10800 secondi) che scandiscono i momenti delle acquisizioni.
Un giorno intero dura 86400 secondi e facendo l'operazione modulo** (unix_time % 86400)** quando il risultato è == 0 significa che sono le ore 00:00:00 del giorno.

Ho abbozzato un esempio, che magari riciclo nel mio progetto per rendere l'idea.
L'ho messo su tinkercad cosi è simulabile

fratt:
O trasformi tutto in secondi oppure dividi i secondi per 60.
Poi non ti conviene fare il conto e metterlo in una variabile e confrontare quella? Così se devi cambiare il conto modifichi solo una riga invece di qualche decina.

Concordo pienamente, o si converte tutto in secondi o in minuti, e a meno che non ci sia qualche altra controindicazione (comunque non visibile da un solo spezzone di codice) potrebbero bastare i minuti, da calcolare quando i secondo sono a zero (spero non abbia "delay()" in giro da qualche parte...).

Tra l'altro il codice è ben poco leggibile, ossia io sostituirei tutta quella lista di if con una cosa del tipo:

// Minuti delle 8 fasce di misurazione e relativi 6 intervalli
unsigned int evt[8][6] = {
  {0, 10, 20, 160, 170, 178},
  {180, 190, 200, 340, 350, 358},
  ...eccetera...
};
...
  // Ammetto 2 secondi di margine (sufficienti??)
  if (now.second() <= 2 ) {
    unsigned int t0 = now.hour() * 60 + now.minute();    
    unsigned int fascia = -1;
    unsigned int p = -1;

    for (int f=0; f<8; ++f) {
      for (int i=0; i<6; ++i) {
        if (t0==evt[f][i]) {
          fascia = f;
          p = i;
          break;
        }
      }
    }
    pressureArray[p] = p_icon;
...

x cotestatnt: bhe considerato che con lo zambretti forecast si parla di previsioni brevi (12H) e circonstanziate al luogo di rsidenza con margine di raggio di 20 km, direi che ci prende. Io nel mio codice ho inserito il principio delle 3 finestre che restituiscono la tendenza della pressione: discesa, costante, aumento al campionamento ogni tre ore che è un altro caposaldo della meteorologia. Inoltre è risaputo che le previsioni delle h. 09:00 del mattino, sono le migliori . Appunto per questo che intendo campionare ogni 3 ore a partire dalle 00:00.
Chiudo dicendo che il campionamento di 3 letture ad inizio fascia e 3 a fine fascia con relative medie è essenziale per scongiurare errori nelle letture sballate (capita a volte anche con buoni sensori)

Tornando al mio problema, non riesco a seguire del tutto il bellissimo codice di docdoc ma approfondisco il suggerimento del Unix Timestamp.
Intanto grazie e procedo con le prove....
Ciao

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.