Go Down

Topic: difficoltà a gestire le modalità su un progetto x cronotermostato  (Read 922 times) previous topic - next topic

fabpolli

Io non la metterei li, ovvero se deve dipendere dalla modalità automatica allora DEVE essere la funzione che la gestisce a gestire il caso ovvero sono in manuale la temperatura l'ho detta io ok, la funzione manuale mi dice la temperatura, sono in antigelo la funzione mi dirà a che temperatura interventire, sono in automatica bene la funzione cerca la soglia se la trova restituisce la relativa temperatura altrimenti restituisce il mantenimento. Non sono in nessuna modalità (???) non faccio nulla manco prova ad accendere o spegnere, anche se questo punto non ha senso un cronotermostato dovrà sempre essere in una modalità tra quelle definite quindi alla peggio in antigelo.
Tra le altre cose la funzione automatica potresti farla anche così:
Code: [Select]

automatica()
{
  valoreRestituito = 15; //La soglia minima da mantenere
  if(...ricerca temperatura desiderata...)
  {
    valoreRestituito = ...valore trovato...
  }
  return valoreRestituito;
}

dove la return può essere omessa se valoreRestituito è globale, il senso è che imposatto comunque un valore prefissato risparmi l'else finale

droidprova

mi sa che non ho tanto capito.... :'(

Standardoil

Guarda, ti dico come farei io:
Userei la libreria timealarm.h, che mi toglie tutti i casini di gestione dei tempi
Una volta al minuto faccio leggere la temperatura, e la confronto con il setpoint del termostato
La timealarm mi gestisce i "momenti" quando cambiate il setpoint
Il modo automatico /manuale mi blocca gli eventi della timealarm e mi permette di regolare il setpoint
Il tuo approccio è complicato, macchinoso, prolisso e usa troppi "magic number"
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

fabpolli

Non conosco la libreria suggerita da Standardoil che in effetti potrebbe "far tutto lei" e risolverti i problemi, in ogni caso provo a spiegarmi meglio visto che prima non sono stato chiaro... a livello logico il tutto si riduce più o meno a
Code: [Select]

float tempDaMantenere;

void setup()
{
...
}

void loop()
{
  switch(modalità)
  {
    case ANTIGELO:
       settaLaTemperaturaInAntigelo();
    break;
    case AUTO:
      settaLaTemperaturaInAutomatico();
    break;
    case MANUALE:
      settaLaTemperaturaInManuale();
    break;
    case TUTIGLIALTRICASICHEVUOI:
       settaLaTemperaturaIn...();
    break;
  }
  accendiSpegni();
}

void accendiSpegni()
{
  if(tempAttuale - isteresi < tempDaMantenere)
  {
     ...accendi...
  }
  else
  {
     ...spegni...
  }
}

void settaLaTemperaturaInAntigelo()
{
  tempDaMantenere = 10;
}

void settaLaTemperaturaInAutomatico()
{
   ...tutti i tuoi calcoli vari ed eventuali per determinare la temperatura...
   tempDaMantenere = ...risultato dei tuoi calcoli...;
}

void settaLaTemperaturaInManuale()
{
  tempDaMantenere = ...temperatura ricevuta ma matenere...;
}



la parte accendispengi non è completa è solo per chiarire che solo quello deve fare ovvio che non basta l'if/else che ho indicato.
valuta tu che strada perseguire, la tua, quella di Standardoil o altre

Standardoil

Guarda, solo pochi appunti, copiando e incollando dal tuo codice, vedi un po i miei commenti
void accensione()
Code: [Select]

{
    if (t_read <= t_acc - EEPROM.get(addr + 11, t_h))
    {
        digitalWrite(rele, HIGH);
    }
    else if (t_read >= t_acc +  t_h) // se la leggi una volta, non hai bisogno di ripetere la lettura
    {
        digitalWrite(rele, LOW);
    }
}

magari dai uno sguardo al reference per la EEPROM.get().........
Code: [Select]

  //MOD ANTIGELO
  if (EEPROM.read(addr + 2) == 1) {     // condizione modalità antigelo
    t_acc = EEPROM.get(addr + 7, t_set_gelo);
  }

non ti sei stancato di fare tutti questi eeprom.get?
fai una tabella
Code: [Select]

float setpoint[6] // o qualunque numero che ti serve

poi in un ciclo leggi dalla eeprom
Code: [Select]

for (byte i=0; i<6; i++){
   setpoint[i]=EEPROM.get(addr+i*4); // mi sembra sia a passi di 4, controlla
}

Se sei scomodo ad usare setpint[numero] puoi fare
Code: [Select]

#define t_h setpoint[3] // vedi se ci ho pigliato col calcolo, comunque il concetto è di usare un nome al posto di un elemento di array
#define e via cosi'..........

anche per i giorni e per le ore
una noiosa e barbosa sequenza di if else if, dai, un minimo di fantasia
Code: [Select]

byte timeset[7][4][2] // un array di 7 array di 4 tempi, ognuno con 2 elementi (ora e minuto)
// a proposito, perchè usavi float?
for (byte i=0; i<7;i++){
   for (byte j=0; j<4;j++){
      for (byte k=0; k<2; k++){
          timeset[i][j][k]=eeprom.get(addr+k+j*2+k*8); ricontrolla il calcolo degli indirizzi
      }
   }
}

e con 4 righe hai letto tutti i tempi dalla eeprom
sottinteso i e' il giorno della settimana
e poi fai un semplice test
Code: [Select]

giorno=now.dayOfTheWeek();// letto una volta sola
int minuto=now.hour()*60+now.minute(); // calcolato una volta sola
for (byte i=1; i<4;i++){
   if (timeset[giorno][i][0]*60+timeset[giorno][i][1]>minuto) {
   // ecco fatto l'accensione/ spegnimento, semplicemnete facendo scorrere degli indici invece che
   // facendo 7 per 4 uguale 28 test consecutivi
   }
}

 
come vedi con un po' di fantasia e poche righe ho eliminato interi blocchi dal tuo programma
assi' lo so che ci vanno le parentesi, ma non ti crederai di fare copia incolla, vero?
trarre ispirazione, non copiare
comunque: se ti fermi a pensare PRIMA di cominciare a programmare ci guadagni, molto!
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

droidprova

Grazie ragazzi!

x Standardoil: che dire, il tuo codice è poesia, mentre il mio è prosa dialettale, purtroppo sto imparando il C da solo e attraverso letture di libri e dispense online, la mancanza di un docente in carne  ed ossa si sente. Chiedere e ottenere risposte dal vivo non ha prezzo. Immaginavo che quei 28 test si potessero di ridurre ad una manciata di righe, ma onestamente e non per mancanza di fantasia, non avrei saputo proprio come farlo diversamente.

Comunque grazie, trarrò spunto e farò dei test con l'insegnamento che mi hai dato. Grazie

Standardoil

Prego...
Invece per quelli più  bravi di me, una domanda
Negli esempi e nella documentazione della eeprom.h non ne ho trovato traccia, ma sbaglio o alcuni anni fa c'era una discussione dove si diceva che "a breve, con la prossima release" si sarebbe potuto fare put e get anche di interi array?
Perché  qui sarebbe comodo....
E/o passare per una struct, ma ieri era tardi e non ci ho guardato dentro molto a fondo...
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

fabpolli

Con la versione attuale (2.0.0) nell'IDE 1.8.5 è possibile farlo non so con le versioni precedenti della libreria
Personalmente ho un progamma che fa:
Code: [Select]

EEPROM.put(EEPROM_PROGSETTINGS_START_ADDRESS, aTemperatureSettings);

e
Code: [Select]

EEPROM.get(EEPROM_PROGSETTINGS_START_ADDRESS, aTemperatureSettings);

dove aTemperatureSettings è definita così:
Code: [Select]

struct tempSettings{
  int timeStart;
  int temp;
};
struct tempSettings aTemperatureSettings[7][DAY_MAX_TEMP_CHANGES];

Standardoil

Sì, quella è una struct, sapevo che si poteva, anche se non ci ho "guardato dentro"
Il mio dubbio è un array...
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

fabpolli

Funziona uguale anche con un semplice array, matricei, ecc. con i medesimi metodi. Anche nel mio caso ho un array di struct

Standardoil

E quindi cosa fai, passi oggetto e dimensione in numero di elementi?
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

fabpolli

No passi solo l'indirizzo di partenza in cui scrivere e quello che vuoi scrivere il metodo della libreria fa questo:

Code: [Select]

EEPtr e = idx;
const uint8_t *ptr = (const uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e )  (*e).update( *ptr++ );

usando peraltro il metodo update che preserva la durata della memoria in quanto scrive il dato solo se differente da quello già memorizzato

Standardoil

Scusa, non capisco. Si vede che ieri ho mangiato troppo kebab...
Se tu passi un oggetto capisco, la sizeof restituisce la dimensione in byte dell'oggetto, ok, poi il ciclo esegue i varii update, tutto chiaro
Ma se passi un array, gli array sono passati per puntatore, la sizeof restituisce la dimensione del puntatore, non quella dello array, che poi c'è ancora da moltiplicare per la dimensione del singolo elemento...
Non capisco. Sono perplesso...
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

fabpolli

In effetti mi sono accorto che ho copiato solo il codice della funzione e non la sua firma:
Code: [Select]

template< typename T > const T &put( int idx, const T &t ){

Ciò che dici è assolutamente vero, se facesse la sizeof di un array passato per riferimento questa ritornerebbe la dimensione del puntatore, ma essendo un template il parametro passato per riferimento viene tipizzato e la sizeof restituisce la corretta dimensione

Standardoil

Questo è c++, vero?
Ecco, ho visto il "male"....
Sono dannato...
Prima legge di Nelson (che sono io): Non scambiare il fine con il mezzo: ricorda "cosa" devi fare, non "come" devi farlo

Non bado a studenti, che copino altrove

Tu hai problema-Io ti domando-Tu non mi rispondi: vuol dire che non ti serve più

Go Up