Problema con assegnamenti struct

Buonasera,
sto scrivendo del codice per far funzionare una lavastoviglie con Arduino. Ci sono 8 programmi ognuno dei quali ha caratteristiche diverse (prelavaggio sì o no, numero di risciacqui, suddivisione del lavaggio principale ecc. ecc.), ma siccome tutti si riferiscono ad una struttura comune ho ddeciso di creare una struct chiamata Cycle
Ora, il problema è che non riesco ad attribuire ai termini della struct i valori che desidero. Prendiamo l'esempio di cycleArray[0], è un programma dove scarica per 1 minuto, carica per 1.5 minuti (tempi indicativi, sono gestiti da pressostato), lava per 10 minuti e scarica per 1 minuto. Totale 13.5 minuti, o 810000 millisecondi.
Ma per qualche motivo (sicuramente banale, ma mi ci sono incartato) la scrittura

cycleArray[0].prewashDuration1 = 10;

non funziona. Infatti se vado a stampare questa voce mi restituisce 0 anzichè 10. Dove sbaglio?

Inoltre se nel loop vado a scrivere

void loop(){
     calculateTime(0);
}

mi viene restituita soltanto la somma dei tempi già espressi (intendo 1,1.5 e 1, totale 3.5), a conferma che questo "assegnamento" non funziona
Qui di seguito trovate il codice completo (è un file header), se riusciste ad aiutarmi ve ne sarei grato

#ifndef cycleproperties_h
#define cycleproperties_h

#define numOfPrograms 8
#define K 60000 //convert from minutes to millis
#define heatK 2.5 //increase of temperature every minute
#define inletWaterTemp 10 //°C
/*

  PROGRAM CYCLES ORDER
  1: RINSE AND HOLD
  2: INTENSIVE 70°C
  3: NORMAL 65°C
  4: ECO 55°C
  5: 1h 65°C
  6: GLASSWARE 45°C
  7: QUICK 45°C
  8: PLATEWARMER

*/

typedef struct Cycle {

  byte startPhase = 0;

  bool heatedPrewash = 0;
  byte prewashTemp = inletWaterTemp ;
  byte prewashDuration1 = 0; //in minutes
  byte prewashDuration2 = 0;

  byte washTemp = inletWaterTemp;
  byte washTime1 = 0; //in minutes //cold wash
  byte washTime2 = 0; //in minutes //wash at 45°C
  byte washTime3 = 0; //in minutes //wash at temp 2 (eg. 55°C)
  byte washTime4 = 0; // in minutes //wash at final temp (eg. 65°C)
  bool secondHeating = 0; //reheat water yes or no
  byte secondHeatingTemp = inletWaterTemp;
  bool thirdHeating = 0;
  byte thirdHeatingTemp = inletWaterTemp;

  bool withRinse1 = 0;
  bool heatedRinse1 = 0;
  byte rinse1Duration = 0;

  bool withRinse2 = 0;
  bool heatedRinse2 = 0;
  byte rinse2Duration = 0;

  bool heatedRinse3 = 0;
  byte rinse3Duration = 0;
  bool rinse3Temp = inletWaterTemp;

  byte dryingDuration = 0;

  byte endPhase = 27;
};

Cycle cycleArray[numOfPrograms];

void assignParameters() {

  //PREWASH / RINSE AND HOLD / SOAK PROGRAM
  cycleArray[0].startPhase = 0;
  cycleArray[0].heatedPrewash = false;
  cycleArray[0].prewashDuration1 = 10;//minutes
  cycleArray[0].endPhase = 6;//last phase run before ending the cycle (prewash only)




  //1h 65°C
  cycleArray[4].startPhase = 6;//first phase of the cycle (prewash skipped)

  cycleArray[4].washTemp = 45;
  cycleArray[4].washTime1 = 2; //cold water
  cycleArray[4].washTime2 = 4; //at 45°C
  cycleArray[4].secondHeating = true;
  cycleArray[4].secondHeatingTemp = 65;
  cycleArray[4].washTime3 = 1; //at 65°C

  cycleArray[4].withRinse1 = true;
  cycleArray[4].heatedRinse1 = true;
  cycleArray[4].rinse1Duration = 5; //minutes

  cycleArray[4].heatedRinse3 = true;
  cycleArray[4].rinse3Temp = 55;
  cycleArray[4].rinse3Duration = 2; //minutes

  cycleArray[4].dryingDuration = 5;

  cycleArray[4].endPhase = 27;//last phase run before ending the cycle (no drying)



  //QUICK 45°C
  cycleArray[6].startPhase = 6;//first phase of the cycle (prewash skipped)

  cycleArray[6].washTemp = 45;
  cycleArray[6].washTime2 = 2;//at 45°C

  cycleArray[6].withRinse1 = true;
  cycleArray[6].rinse1Duration = 4;//minutes

  cycleArray[6].heatedRinse3 = true;
  cycleArray[6].rinse3Temp = 50;//minutes

  cycleArray[6].endPhase = 25;//last phase run before ending the cycle (no drying)

}



/*                FUNCTIONS AND TIME CALCULATION                  */

long timeToHeat(byte temp) {
  return (K * (temp - inletWaterTemp) / heatK);
}


long timeArray[27] = {K, 1.5 * K , cycleArray[progIndex].prewashDuration1 * K, cycleArray[progIndex].heatedPrewash * timeToHeat(cycleArray[progIndex].prewashTemp), cycleArray[progIndex].prewashDuration2 * K, //prewash
                      K, 1.5 * K, cycleArray[progIndex].washTime1 * K, timeToHeat(45), cycleArray[progIndex].washTime2 * K, cycleArray[progIndex].secondHeating * timeToHeat(cycleArray[progIndex].secondHeatingTemp - 45 ),
                      cycleArray[progIndex].washTime3 * K, cycleArray[progIndex].thirdHeating * timeToHeat(cycleArray[progIndex].thirdHeatingTemp - cycleArray[progIndex].secondHeatingTemp),
                      cycleArray[progIndex].washTime4 * K, 2.5 * K, //mainwash
                      1.5 * K, cycleArray[progIndex].rinse1Duration * K, K, //first rinse
                      1.5 * K, cycleArray[progIndex].rinse2Duration * K, K, //second rinse
                      1.5 * K, timeToHeat(cycleArray[progIndex].rinse3Temp), cycleArray[progIndex].rinse3Duration * K, K, //third and final rinse
                      cycleArray[progIndex].dryingDuration * K, K //drying
                     };


long calculateTime(byte progIndex) {
  long totalTime = 0;
  
  assignParameters();


  for (int i = cycleArray[progIndex].startPhase; i < cycleArray[progIndex].endPhase; i++) {
    totalTime += timeArray[i];
    Serial.println("Time array value pos ");
    Serial.print (i);
    Serial.print ("= ");
    Serial.println(timeArray[i]);
  }
  Serial.println(totalTime);
  return totalTime;

}




#endif

Sospetto la "moltiplicazione" all'interno di timeArray[ ]. Se uno di questi parametri è zero (o non definito), i risultati tendono a zero. Verificare che ogni parametro rientri nei valori previsti.

long timeArray[27] = {K, 1.5 * K , cycleArray[progIndex].prewashDuration1 * K, cycleArray[progIndex].heatedPrewash * timeToHeat(cycleArray[progIndex].prewashTemp), cycleArray[progIndex].prewashDuration2 * K, //prewash
                      K, 1.5 * K, cycleArray[progIndex].washTime1 * K, timeToHeat(45), cycleArray[progIndex].washTime2 * K, cycleArray[progIndex].secondHeating * timeToHeat(cycleArray[progIndex].secondHeatingTemp - 45 ),
                      cycleArray[progIndex].washTime3 * K, cycleArray[progIndex].thirdHeating * timeToHeat(cycleArray[progIndex].thirdHeatingTemp - cycleArray[progIndex].secondHeatingTemp),
                      cycleArray[progIndex].washTime4 * K, 2.5 * K, //mainwash
                      1.5 * K, cycleArray[progIndex].rinse1Duration * K, K, //first rinse
                      1.5 * K, cycleArray[progIndex].rinse2Duration * K, K, //second rinse
                      1.5 * K, timeToHeat(cycleArray[progIndex].rinse3Temp), cycleArray[progIndex].rinse3Duration * K, K, //third and final rinse
                      cycleArray[progIndex].dryingDuration * K, K //drying
}

non postare due volte la stessa domanda.

Usa U o UL dopo la costante numerica, così:

#define K 60000UL //convert from minutes to millis

U sta per unsigned di default è int, mentre UL sta per unsigned long.
Se arduino è basato su una MCU AVR 8-bit il tipo int è si grande 16 bit ma non può contenere il valore 60000. unsigned int o uint16_t può al al massimo contenere 65535 tutti i 16 bit accesi.

Provato con il simulatore online e nel mio caso non serve specificare U, L o altro. Il compilatore è così smart che deduce il tipo in base al numero di cifre. Però con:

#define K 4294967295 

Da errore a compile time perché non trova una print(long long int), l'errore non c'è aggiungendo U.
Ciao.

@Mattia9914: in conformità al REGOLAMENTO, punto 13, il cross-posting è proibito (anche tra lingue diverse) per cui, il tuo post duplicato nella sezione Inglese del forum è stato chiuso ed in seguito verrà cancellato.

Ti prego, per il futuro, di evitare di aprire più post sullo stesso argomento in sezioni differenti del forum. Grazie.

Guglielmo

@xfpd : pur essendo tu un vecchio utente del forum, NON riesco a trovare il tuo post di presentazione, per cui, cortesemente, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiederei di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie.

Guglielmo

Qual è esattamente la tua accusa?

—> presentazione

@xfpd: Moderiamo i termini ... NON c'è alcuna "accusa", mica siamo in un tribunale ...

... sei venuto a scrivere nella sezione Italiana del forum, tale sezione ha delle sue "regole" che sono scritte nel REGOLAMENTO relativo a tale sezione, una di queste è che, sia per buona educazione, sia per quanto spiegato al punto 16.7, si richiede una "presentazione" ... e aspettiamo, come per tutti, anche la tua. Molto semplice :slight_smile:

Guglielmo

Mi scuso sig. Guglielmo per il cross post, solitamente pubblico sulla sezione inglese ma vedendo che nessuno aveva risposto ho deciso di pubblicare su quella italiana

@Maurotec ti ringrazio molto, non mi sono accorto che int contiene al massimo 2^15-1, proverò appena possibile ad inserire U e vedere cosa ottengo.
Per curiosità, mi confermi che U necessita di 2 byte mente UL di 4, giusto? So cercando di ottimizzare il codice dove possibile, non avendo una grande esperienza mi sto limitando all'uso di codice non bloccante e variabili non inutilmente grandi

Basta che vai nel reference di Arduino, sezione "Data Type" e vedi la lunghezza di tutte le variabili che supporta ... gli "interi" sono a 16 bit, i "long" sono a 32 bit, tutto indipendentemente che siano segnati o meno.

Guglielmo

Accolgo con favore la conformità della 16.7, ma perché ricevo questa richiesta quando la 16.2 viene violata ogni minuto di ogni giorno in ogni argomento che potrei visualizzare, senza un pubblico travestimento? Rispetto la conoscenza, che non va confusa con il pagamento di una quota di istituto privilegiato o di chi si conosce. Chi mi ha accusato del 16.2 e cosa ti ha portato a riferirmi al 16.7? Che cosa vorresti sapere? Accolgo con favore la conformità se si applica a tutti, altrimenti è mirata e non valida.

Prego, ma non è detto che sia questo il problema, tieni conto che il compilatore usato da arduino si evolve non solo anche la toolchain inclusa la libreria avr-libc si evolve. Al link trovi il file stdint.h usato da arduino per avr-8bit.

Ti consiglio di trovare questo file nel tuo computer e usarlo come riferimento. Ti consiglio di usare i tipi predefiniti uint16_t ecc che agevolano il porting verso altre piattaforme a 32-bit.

Le operazioni tra variabili qualche volta forniscono risultati non aspettati, per cui io non mi fido di me stesso e in questi casi voglio vedere il risultato delle operazioni così da avere conferma.

Riguardo ai tipi standard questi parlano e si descrivono da soli, es:

int_least16_t

intero con segno almeno grande 16-bit, questo vuole dire che su una cpu 32-bit sceglierà in automatico il tipo di dato corretto. Stessa cosa nel caso di porting da cpu 32-bit a 8-bit.

Ciao.

su un arduino AVR.

ESP, MKR ecc. (architetture a 32 bit) hanno 4 byte per un int.

NON mi risulta ... qui da noi, se qulcuno ha evidenti lacune, per il suo bene glie le indichiamo e gli suggeriamo di studiare i pdf che vedi elencati al punto 16.1 e magari comprare anche il libro (che è in Italiano) che è sempre indicato al suddetto punto.

In altre parti non saprei ... :roll_eyes:

Guglielmo

Vero, vero, causa di innumerevoli casini quando ci si sposta da un'architettura all'altra ...
... per questo io non amo le definizioni standard e, includendo <stdint.h> cerco sempre di usare "uint8_t", "uint16_t", ecc. ecc. così da essere sicuro della lunghezza del campo :wink:

Guglielmo

Ma chi ti ha parlato del 16.2 ??? :open_mouth: :open_mouth: :open_mouth:

Il 16.7 spiega bene a cosa siamo interessati e se ti guardi le migliaia di altre presentazioni magari capisci, altrimenti ... se hai difficoltà con la lingua :roll_eyes:, magari conviene che frequenti altre sezioni del forum.

Guglielmo

@Maurotec ho sostituito a 60000 il valore 60000UL ma non ho ottenuto il risultato sperato
Sembra essere proprio un problema di inizializzazione dello struct, infatti a serial monitor ottengo

Time array value pos 
0= 60000
Time array value pos 
1= 90000
Time array value pos 
2= 0
Time array value pos 
3= 0
Time array value pos 
4= 0
Time array value pos 
5= 60000

cioè non mi prende l'assegnamento cycleArray[0].prewashDuration1 = 10, infatti la posizione 2 vale zero. Cosa devo fare?

long timeArray[27] = {K, 1.5 * K , cycleArray[progIndex].prewashDuration1 * K, cycleArray[progIndex].heatedPrewash * timeToHeat(cycleArray[progIndex].prewashTemp), cycleArray[progIndex].prewashDuration2 * K, //prewash
                      K, 1.5 * K, cycleArray[progIndex].washTime1 * K, timeToHeat(45), cycleArray[progIndex].washTime2 * K, cycleArray[progIndex].secondHeating * timeToHeat(cycleArray[progIndex].secondHeatingTemp - 45 ),
                      cycleArray[progIndex].washTime3 * K, cycleArray[progIndex].thirdHeating * timeToHeat(cycleArray[progIndex].thirdHeatingTemp - cycleArray[progIndex].secondHeatingTemp),
                      cycleArray[progIndex].washTime4 * K, 2.5 * K, //mainwash
                      1.5 * K, cycleArray[progIndex].rinse1Duration * K, K, //first rinse
                      1.5 * K, cycleArray[progIndex].rinse2Duration * K, K, //second rinse
                      1.5 * K, timeToHeat(cycleArray[progIndex].rinse3Temp), cycleArray[progIndex].rinse3Duration * K, K, //third and final rinse
                      cycleArray[progIndex].dryingDuration * K, K //drying
                     };

La dichiarazione e inizializzazione di timeArray avviene a compile time e io non vedo il valore della variabile progIndex che anche se dichiarata è inizializzata non varia il suo valore. Poi vedo che nella funzione assignParameters() da indice 0 passi a 4 e poi a 6.

Forse per snellire il codice hai eliminato qualcosa prima di postare.

PS: io ho provato al simulatore è l'assegnazione lavora e anche la struct è corretta.

Ciao.

Ho postato il codice per intero, nessun taglio
Nella assignParameters() ho messo solo quegli indici perchè non ho ancora steso tutti i programmi. La variabile progIndex è nel file principale ed è assegnata a zero
Se al simulatore funziona non so davvero cosa fare, sul Nano non funge
Per caso riusciresti a postare qui il codice della simulazione, magari ho fatto un errore banale che mi sfugge
Ho provato a copiare tutto nel file principale omettendo i file header creati ma anche così non funziona