Millis va più lento del dovuto....codice da ottimizzare?

Concordo al 100%. Mi spiace dirlo ma il problema è alla radice, ossia nel fatto che purtroppo il codice è evidentemente "cresciuto" in modo troppo disordinato, aggiungendo volta in volta cose qui poi lì, fino ad arrivare ad un "frankenstein-code" sempre meno comprensibile e gestibile.

Servirebbe una revisione quasi completa, ma nel frattempo per sistemare almeno quel problema del ritardo potrebbe bastare aggiungere vari Serial.print() nei punti dove si toccano le variabili per le temporizzazioni e capire dove sia l'inghippo. E quindi far almeno camminare Frankenstein (che poi era il nome dello scienziato, non del mostro, ma vabbè...).

Concordo in pieno, però non lo possiamo fare noi il lavoro di debug con i vari Serial.print() perché non abbiamo l'hardware. L'alternativa ci sarebbe se fosse possibile isolare pezzi di codice per testarli, ma io ci ho capito poco, di quel poco ho pure il dubbio.

Credo che se il pulsante è LOW ogni tot ms viene incrementata una variabile usata nello swtich. Quindi l'utente decide di rilasciare il pulsante è rimane nel case selezionato dove c'è una temporizzazione con millis di due secondi, cioè se si resta per più di 2 secondi nello stesso case il timer scade e viene eseguita l'azione.

Ciao.

Certo che no, intendevo infatti dire che lo deve fare l'OP...

Probabile, ma comunque è tutta la gestione che è farraginosa e difficile da comprendere. In questi casi bisognerebbe ricominciare daccapo strutturando il codice ad iniziare dall'implementazione di una macchina a stati finiti. Ma comprendo anche che per l'OP non sia facile, per questo gli suggerivo di provare almeno a fare debug con la Serial e sistemare intanto il problema nell'immediato.

Inutile dire che mi trovo perfettamente d'accordo con i "colleghi".

Quando si ha in mente di sviluppare un progetto di una certa complessità è fondamentale strutturarlo in modo tale che sia chiaro e facile da interpretare anche per altre persone.
I commenti sono fondamentali, ma come è stato già suggerito non è da sottovalutare nemmeno il "naming" delle variabili e l'organizzazione stessa del software.

Quando si tratta di modellare delle macchine a stati finiti di una certa complessità è un attimo perdere il controllo del mezzo :grin:

Io ad esempio mi sono fatto una libreria proprio per questa ragione in modo da usare sempre lo stesso approccio e "nascondere" tutto il meccanismo necessario per far funzionare l'automa che farebbe soltanto confusione a lasciarlo "in chiaro".

In questo modo l'80% del lavoro si fa senza digitare una riga di codice perché di fatto si tratta soltanto di enumerare gli stati della macchina e le condizioni che attivano la transizione da uno stato all'altro.

E questo sarà il comportamento volutamente progettato in partenza, oppure è così solo perché in altro modo non si è riusciti a farlo (e magari si potrebbe operare in modo molto più semplice)?

EEPROM.get(pianta, valore_bagnato); // Da 1 a 8.
EEPROM.get(10+pianta, valore_asciutto); // Da 11 a 18.

Oppure:

EEPROM.get(pianta*2-1, valore_bagnato); // 1, 3, 5, 7, 9, 11, 13, 15.
EEPROM.get(pianta*2, valore_asciutto); // 2, 4, 6, 8, 10, 12, 14, 16.

Comunque in generale "millis che va più lento" è dovuto al riconoscimeno e aggiornamento in ritardo della variabile temporale rispetto all'esatto momento in cui scadrebbe il tempo. Se questo si ripete più volte periodicamente, il ritardo si accumula sempre di più.

void loop()
{

    delay(500); // simula tante operazioni in corso

    // qui possiamo arrivare con mezzo secondo di ritardo
    // rispetto all'esatto momento di scadenza
    if (millis() - t  >= 1000) // riconoscimento in ritardo
    {
        n++;
        Serial.println(n);
        delay(500); // simula tante operazioni interne
        t = millis(); // aggiornamento in ritardo
    }

    // sono passati due sec ma il programma pensa che ne sia passato solo uno

}

Per risolvere quel problema, bisogna mettere t+=1000 anziché t=millis() oppure, come faccio abitualmente, mettere t=millis() come prima cosa.

Non basta, due letture di millis anche ravvicinate possono dare un risultato differente, ma soprattutto si può arrivare tardi a valutare il timeout, e quel ritardo così non si recupera.

Per un aggiornamento periodico è indispensabile il t+=1000, a patto che il resto del programma non sia così ingolfato da bloccare l'esecuzione per un tempo superiore al periodo.

Quindi la domanda è: dove nel design del codice di simosere ci ingolfiamo, riconosciamo i tempi in ritardo e aggiorniamo altrettanto in ritardo?

1 Like

cipicchia.... ho molto da leggere e soprattuto da capire... grazie infinite....

ho fatto al volo due prove:

  • ho meesso lo stesso codice in un arduino mega e purtoppo il risultato è la stesso che ho con il nano che devo usare nel progetto
  • ho messo tutti i serial.print che potevo mettere(con il mega) e con il debug non ho riscontrato nessuna anomalia..... è tutto giusto...

ho solo fatto una piccola modifica nella nuova versione:

  • leggevo continuamente lo stato della batteria anche quando non serviva

allego la versione con debug se tante volte qualcuno può provarla....

//V.1.09
// prova sistemazione millis alleggerendo il calcolo ITOA del timer restante
// messo int Tempo_rimanente_MP_a display
// abbassato char stringa_timer_restante_campionamento[5] a char stringa_timer_restante_campionamento[4] per evitare lo zero dopo che da 10sec rimanga 90 invece di 9 sec
//ultoa


#include <Wire.h>
#include <OLED_I2C.h>
#include <SPI.h>
#include <EEPROM.h>
#define pulsante 49
int stato_pulsante = 0;
byte variabile_pulsante = 0;
byte variabile_pulsante_calibrazione = 0;
int Valore_umidita = 0;
int umiditaPianta = 0;
unsigned long pressione_pulsante = 0;
unsigned long TIMEOUT_pressione_pulsante = 500;
unsigned long durata_pressione_pulsante = 0;
bool cambio_stato_pulsante_calibrazione = false;
OLED  myOLED(SDA, SCL);

// font utilizzati
unsigned long t1 = 0;   // aggiorna display
unsigned long t2 = 0;   // aggiorna batteria
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
char misurazione[3];
int val_bagnato = 0;
int val_asciutto = 0;
char stringa_val_bagnato[4];
char stringa_val_asciutto[4];
char stringa_OLD_bagnato[4];
char stringa_OLD_asciutto[4];
char stringa_misurazione[4];
char stringa_batteria[4];
int batteria = 0;
long result = 0;
char stringa_result[5];
long Valore_Carico = 5200;
long Valore_Scarico = 3500;
char stringa_Valore_Scarico[4];
char stringa_Valore_Carico[4];
int somma_batteria = 0;
byte nr = 0;
int media_batteria = 0;
long somma_result = 0;
long media_result = 0;
byte cella_eeprom_asciutto = 0;
byte cella_eeprom_bagnato = 0;
byte pianta_selezionata = 0;
char stringa_pianta_selezionata[2];
unsigned long tempo_campionamento = 0;
unsigned long incremento_tempo_campionamento = 1;
char stringa_tempo_campionamento[10];
const char* cursore[] = {"<"};
const char* Menu[] = {"Menu", "Cal.Sensore", "Cal.Batteria", "Monit.Pianta", "Seleziona Pianta", "Esci"};
const char* cal[] = {"Menu' calibrazione", "OLD_bagnato:", "OLD_asciutto:", "Misurazione:", "%:", "Annulla"};
const char* mis_umidita[] = {"Umidita' %:", "Pianta", "selezionata"};
const char* Bat[] = {"BAT%:"};
const char* cal_bat[] = {"menu' batteria", "batt %:", "Valore VCC:", "Valore Scarico:", "Valore Carico:", "Annulla"};
const char* sel_pianta[] = {"menu' sel.pianta", "!Pianta1", "Pianta 1", "!Pianta2", "Pianta 2", "!Pianta3", "Pianta 3", "!Pianta4", "Pianta 4", "!Pianta5", "Pianta 5", "!Pianta6", "Pianta 6", "!Pianta7", "Pianta 7", "!Pianta8", "Pianta 8", "Resetta", "Esci"};
const char* mon_pianta[] = {"Menu'monit.Pianta", "Minuti:", "Conferma", "Annulla", "Esci"};
bool cancella_display = false;
unsigned long START_Campionamento_MP = 0;
unsigned long Timeout_Campionamento_MP = 0;
int raccolta_dati[16];
byte punto_raccolta_dati = 1;
char misurazione_RD[10];
char stringa_timer_restante_campionamento[2];
const char* Timer[] = {"T:", "OK  ", "     "};
const char* Lista_camp[] = {"1:", "2:", "3:", "4:", "5:", "6:", "7:", "8:", "9:", "10:", "11:", "12:", "13:", "14:", "15:"};
const char* Stato_camp[] = {"Campionamento...", "Completato!!!!!",};
const char* firmware[] = {"V1.09"};
byte posizione_cursore_altezza = 0;
byte posizione_cursore_larghezza = 0;
int Tempo_rimanente_MP_a_display = 0;

void cancella_schermo() {
  myOLED.clrScr();
}

void cursore_furbo() {
  myOLED.print(cursore[0], posizione_cursore_larghezza, posizione_cursore_altezza);
}

void menu() {
  Serial.println("menu");
  if ((stato_pulsante == LOW) && ((millis() - pressione_pulsante) > TIMEOUT_pressione_pulsante)) {
    variabile_pulsante++;
    pressione_pulsante = millis();
  }
  cancella_schermo();
  myOLED.print(Menu[0], CENTER, 1);
  myOLED.print(Menu[1], 0, 10);
  myOLED.print(Menu[2], 0, 20);
  myOLED.print(Menu[3], 0, 30);
  myOLED.print(Menu[4], 0, 40);
  myOLED.print(Menu[5], 0, 50);

  switch (variabile_pulsante) {
    case 2: //selezione calibrazione
      Serial.println("2");
      posizione_cursore_altezza = 10;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 2) && ((millis() - pressione_pulsante) > 2000)) {
        calibrazione();
        variabile_pulsante = 8;

      }
      break;
    case 3: //selezione batteria
      Serial.println("3");
      posizione_cursore_altezza = 20;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 3) && ((millis() - pressione_pulsante) > 2000)) {
        cal_batteria();
        variabile_pulsante = 13;

      }
      break;
    case 4: //selezione monitoraggio
      Serial.println("4");
      posizione_cursore_altezza = 30;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 4) && ((millis() - pressione_pulsante) > 2000)) {
        monitoraggio_pianta();
        variabile_pulsante = 30;

      }
      break;
    case 5: //seleziona pianta
      Serial.println("5");
      posizione_cursore_altezza = 40;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 5) && ((millis() - pressione_pulsante) > 2000)) {
        seleziona_pianta();
        variabile_pulsante = 18;

      }
      break;
    case 6: //esci
      Serial.println("6");
      posizione_cursore_altezza = 50;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 6) && ((millis() - pressione_pulsante) > 2000)) {
        variabile_pulsante = 0;

      }
      break;
    case 7:
      variabile_pulsante = 2;
      Serial.println("7");
      break;
  }
}


void monitoraggio_pianta() {
  Serial.println("mon pioggia");
  if ((stato_pulsante == LOW) && ((millis() - pressione_pulsante) > TIMEOUT_pressione_pulsante)) {
    variabile_pulsante++;
    pressione_pulsante = millis();
  }
  if ((variabile_pulsante != 36) && (variabile_pulsante != 37) && (variabile_pulsante != 38)) {
    cancella_schermo();
    myOLED.print(mon_pianta[0], CENTER, 1);
    myOLED.print(mon_pianta[1], 0, 10);
    myOLED.print(mon_pianta[2], 0, 20);
    myOLED.print(mon_pianta[3], 0, 30);
    myOLED.print(mon_pianta[4], 0, 40);
    if (incremento_tempo_campionamento > 1) {
      myOLED.print(stringa_tempo_campionamento, 55, 10);
    }
  }
  switch (variabile_pulsante) {
    case 30: // attende interazione utente
      Serial.println("30");
      break;
    case 31: //seleziona tempo
      posizione_cursore_altezza = 10;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 31) && ((millis() - pressione_pulsante) > 2000)) {
        tempo_campionamento = 5 * incremento_tempo_campionamento;
        itoa(tempo_campionamento, stringa_tempo_campionamento, 10);
        incremento_tempo_campionamento++;
        variabile_pulsante = 30;
        Serial.println("31");
      }
      break;
    case 32: //conferma
      posizione_cursore_altezza = 20;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 32) && ((millis() - pressione_pulsante) > 4000)) {
        Timeout_Campionamento_MP = (tempo_campionamento * 1000UL);
        START_Campionamento_MP = millis();
        variabile_pulsante = 36;
        Serial.println("32");
      }
      break;
    case 33: //annulla
      posizione_cursore_altezza = 30;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 33) && ((millis() - pressione_pulsante) > 2000)) {
        incremento_tempo_campionamento = 1;
        variabile_pulsante = 30;
        Serial.println("33");
      }
      break;
    case 34: //Esci e Annulla
      posizione_cursore_altezza = 40;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 34) && ((millis() - pressione_pulsante) > 2000)) {
        incremento_tempo_campionamento = 1;
        variabile_pulsante = 0;
        Serial.println("34");
      }
      break;
    case 35: //ricomincia il giro nel menu
      variabile_pulsante = 31;
      Serial.println("35");
      break;
    case 36: //avvio campionamento dati
      Serial.println("36");
      if (cancella_display == false) {
        cancella_display = true;
        cancella_schermo();
        myOLED.print(Stato_camp[0], 0, 1);
        myOLED.print(Timer[0], 100, 0);
      }
      if (punto_raccolta_dati <= 16) {
        if ((millis() - START_Campionamento_MP) < Timeout_Campionamento_MP) {

          Tempo_rimanente_MP_a_display = (((Timeout_Campionamento_MP) / 1000) - (millis() - START_Campionamento_MP) / 1000);
          itoa(Tempo_rimanente_MP_a_display, stringa_timer_restante_campionamento, 10);
          myOLED.print(stringa_timer_restante_campionamento, 115, 0);
        }
        if ((millis() - START_Campionamento_MP) >= Timeout_Campionamento_MP) {
          START_Campionamento_MP = millis();
          Valore_umidita = analogRead(0);
          umiditaPianta = map (Valore_umidita, val_bagnato, val_asciutto, 100, 0);
          raccolta_dati[punto_raccolta_dati] =  umiditaPianta;
          sprintf(misurazione_RD, "%i", raccolta_dati[punto_raccolta_dati]);
          punto_raccolta_dati++;
          if (punto_raccolta_dati < 7) {
            myOLED.print(Lista_camp[punto_raccolta_dati - 2], 0, (10 * punto_raccolta_dati - 10));
            myOLED.print(misurazione_RD, 15, (10 * punto_raccolta_dati - 10));
          }
          if ((punto_raccolta_dati >= 7) && (punto_raccolta_dati <= 11)) {
            myOLED.print(Lista_camp[punto_raccolta_dati - 2], 40, ((10 * punto_raccolta_dati) - 60));
            myOLED.print(misurazione_RD, 60, ((10 * punto_raccolta_dati) - 60));
          }
          if ((punto_raccolta_dati >= 12) && (punto_raccolta_dati <= 16)) {
            myOLED.print(Lista_camp[punto_raccolta_dati - 2], 80, ((10 * punto_raccolta_dati) - 110));
            myOLED.print(misurazione_RD, 100, ((10 * punto_raccolta_dati) - 110));
          }
        }
        if (punto_raccolta_dati == 16) {
          punto_raccolta_dati = 17;
          myOLED.print(Stato_camp[1], 0, 1);
          variabile_pulsante = 37;
        }
      }
      break;
    case 37:
      Serial.println("37");
      myOLED.print(Timer[1], 100, 0);
      break;
    case 38:
      Serial.println("38");
      myOLED.print(cursore[0], 115, 0);
      if ((variabile_pulsante == 38) && ((millis() - pressione_pulsante) > 2000)) {
        punto_raccolta_dati = 1;
        for (punto_raccolta_dati = 1; punto_raccolta_dati < 17; punto_raccolta_dati++) {
          raccolta_dati[punto_raccolta_dati] = 0;
        }
        tempo_campionamento = 0;
        incremento_tempo_campionamento = 1;
        cancella_display = false;
        variabile_pulsante = 0;
        punto_raccolta_dati = 1;
      }
      break;
  }
}



void setup() {
  Serial.begin(9600);
  myOLED.begin();   // avvia oled
  myOLED.setBrightness(255);  // setta luminosit  oled
  myOLED.setFont(SmallFont);
  pinMode(pulsante, INPUT);
  EEPROM.get(8, Valore_Scarico);  //8-9-10-11-12 occupati
  EEPROM.get(13, Valore_Carico);  //13-14-15-16-17 occupati
  EEPROM.get(250, pianta_selezionata);  //4-5-6-7 occupati
  if (pianta_selezionata == 1) {
    cella_eeprom_bagnato = 0;
    cella_eeprom_asciutto = 4;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 2) {
    cella_eeprom_bagnato = 18;
    cella_eeprom_asciutto = 23;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 3) {
    cella_eeprom_bagnato = 28;
    cella_eeprom_asciutto = 33;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 4) {
    cella_eeprom_bagnato = 38;
    cella_eeprom_asciutto = 43;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 5) {
    cella_eeprom_bagnato = 48;
    cella_eeprom_asciutto = 53;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 6) {
    cella_eeprom_bagnato = 58;
    cella_eeprom_asciutto = 63;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 7) {
    cella_eeprom_bagnato = 68;
    cella_eeprom_asciutto = 73;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 8) {
    cella_eeprom_bagnato = 78;
    cella_eeprom_asciutto = 83;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  t1 = millis();
}

void loop() {

  stato_pulsante = digitalRead(pulsante);


  if ((variabile_pulsante == 0) || (variabile_pulsante == 13) || (variabile_pulsante == 14) || (variabile_pulsante == 15) || (variabile_pulsante == 16) || (variabile_pulsante == 17))  {
    if (nr < 10) {
      batteria = map(readVcc(), Valore_Carico, Valore_Scarico, 100, 0);
      somma_batteria = somma_batteria + batteria;
      somma_result = somma_result  + result ;
      nr++;
    }
    if (nr == 10) {
      media_batteria = somma_batteria / nr;
      media_result = somma_result / nr;
      nr = 0;
      somma_batteria = 0;
      somma_result = 0;
    }
  }


  if (variabile_pulsante < 1) { // in modalit  calibrazione
    if ((stato_pulsante == LOW) && ((millis() - pressione_pulsante) > TIMEOUT_pressione_pulsante)) {
      variabile_pulsante++;
      pressione_pulsante = millis();
      if (variabile_pulsante > 3) {
        variabile_pulsante = 0;
      }
    }
  }

  switch (variabile_pulsante) {
    case 0: //misurazione normale
      cancella_schermo();
      misurazione_umidita();
      stato_batteria();
      break;
    case 1: //menu'
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
      menu();
      break;
    case 8: //calibrazione
    case 9:
    case 10:
    case 11:
    case 12:
      calibrazione();
      break;
    case 13:
    case 14:
    case 15:
    case 16:
    case 17:
      cal_batteria();
      break;
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25:
    case 26:
    case 27:
    case 28:
    case 29:
      seleziona_pianta();
      break;
    case 30:
    case 31:
    case 32:
    case 33:
    case 34:
    case 35:
    case 36:
    case 37:
    case 38:
      monitoraggio_pianta();
      break;
  }
  //if ((millis() - t1) > 1000) {
  // t1 = millis;
  myOLED.update();
  //wdt_reset();
  //}
}






long readVcc() {
  Serial.println("batt");
  uint8_t low;
  uint8_t high;

  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // measuring
  low  = ADCL; // must read ADCL first - it then locks ADCH
  high = ADCH; // unlocks both
  result = (high << 8) | low;
  result = 1127346L / result; // Calculate Vcc (in mV); 1125300 = 1.102*1023*1000
  return result; // Vcc in millivolts
}


void calibrazione() {
  Serial.println("cal");
  if ((stato_pulsante == LOW) && ((millis() - pressione_pulsante) > TIMEOUT_pressione_pulsante)) {
    variabile_pulsante++;
    pressione_pulsante = millis();
  }
  cancella_schermo();
  myOLED.print(cal[0], CENTER, 1);
  myOLED.print(cal[1], 0, 20);
  //valore bagnato memorizzato
  itoa(val_bagnato, stringa_OLD_bagnato, 10);
  myOLED.print(stringa_OLD_bagnato, 80, 20);
  //valore asciutto memorizzato
  myOLED.print(cal[2], 0, 30);
  itoa(val_asciutto, stringa_OLD_asciutto, 10);
  myOLED.print(stringa_OLD_asciutto, 80, 30);
  // valore analogico di misurazione per calibrare i valori asciutti e bagnati
  Valore_umidita = analogRead(0);
  myOLED.print(cal[3], 0, 40);
  itoa(Valore_umidita, stringa_misurazione, 10);
  myOLED.print(stringa_misurazione, 80, 40);
  umiditaPianta = map (Valore_umidita, val_bagnato, val_asciutto, 100, 0);
  sprintf(misurazione, "%i", umiditaPianta);
  myOLED.print(cal[4], 103, 40);
  myOLED.print(misurazione, 110, 40);
  myOLED.print(cal[5], 0, 50);
  switch (variabile_pulsante) {
    case 8: // attendi interazione utente
      Serial.println("8");
      break;
    case 9:  // selezione calibrazione valore umido
      Serial.println("9");
      posizione_cursore_altezza = 20;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 9) && ((millis() - pressione_pulsante) > 4000)) {
        val_bagnato = Valore_umidita;
        EEPROM.put(cella_eeprom_bagnato, val_bagnato);
        variabile_pulsante = 8;
      }
      break;
    case 10: // selezione calibrazione valore asciutto
      Serial.println("10");
      posizione_cursore_altezza = 30;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 10) && ((millis() - pressione_pulsante) > 4000)) {
        val_asciutto = Valore_umidita;
        EEPROM.put(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        variabile_pulsante = 8;
      }
      break;
    case 11: // annulla scelta
      Serial.println("11");
      posizione_cursore_altezza = 50;
      posizione_cursore_larghezza = 105;
      cursore_furbo();
      if ((variabile_pulsante == 11) && ((millis() - pressione_pulsante) > 2000)) {
        variabile_pulsante = 0;
      }
      break;
    case 12: // annulla scelta
      Serial.println("12");
      variabile_pulsante = 9;
      break;
  }
}
void misurazione_umidita() {
  Serial.println("um");
  cancella_schermo();
  Valore_umidita = analogRead(0);
  umiditaPianta = map (Valore_umidita, val_bagnato, val_asciutto, 100, 0);
  myOLED.print(mis_umidita[0], 0, 5);
  sprintf(misurazione, "%i", umiditaPianta);
  myOLED.setFont(MediumNumbers);
  myOLED.print(misurazione, 75, 1);
  myOLED.setFont(SmallFont);
  myOLED.print(mis_umidita[1], LEFT, 30);
  sprintf(stringa_pianta_selezionata, "%i", pianta_selezionata);
  myOLED.print(stringa_pianta_selezionata, 40, 30);
  myOLED.print(mis_umidita[2], 50, 30);
  myOLED.print(firmware[0], RIGHT, 50);

}

void stato_batteria() {
  Serial.println("batteria");
  myOLED.print(Bat[0], 0, 50);
  itoa(media_batteria, stringa_batteria, 10);
  myOLED.print(stringa_batteria, 25, 50);
}

void cal_batteria() {
  Serial.println("cal batt");
  if ((stato_pulsante == LOW) && ((millis() - pressione_pulsante) > TIMEOUT_pressione_pulsante)) {
    variabile_pulsante++;
    pressione_pulsante = millis();
  }
  cancella_schermo();
  myOLED.print(cal_bat[0], CENTER, 1);
  myOLED.print(cal_bat[1], 0, 10);
  itoa(media_batteria, stringa_batteria, 10);
  myOLED.print(stringa_batteria, 50, 10);
  myOLED.print(cal_bat[2], 0, 20);
  itoa(media_result, stringa_result, 10);
  myOLED.print(stringa_result, 70, 20);
  myOLED.print(cal_bat[3], 0, 30);
  itoa(Valore_Scarico, stringa_Valore_Scarico, 10);
  myOLED.print(stringa_Valore_Scarico, 90, 30);
  myOLED.print(cal_bat[4], 0, 40);
  itoa(Valore_Carico, stringa_Valore_Carico, 10);
  myOLED.print(stringa_Valore_Carico, 90, 40);
  myOLED.print(cal_bat[5], 0, 50);
  switch (variabile_pulsante) {
    case 13:
      Serial.println("13");
      break;
    case 14: //selezione calibrazione batteria
      Serial.println("14");
      posizione_cursore_altezza = 30;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 14) && ((millis() - pressione_pulsante) > 4000)) {
        Valore_Scarico = media_result;
        EEPROM.put(8, Valore_Scarico);
        variabile_pulsante = 13;
      }
      break;
    case 15: //aggiorna valore batterie cariche
      Serial.println("15");
      posizione_cursore_altezza = 40;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 15) && ((millis() - pressione_pulsante) > 4000)) {
        Valore_Carico = media_result;
        EEPROM.put(13, Valore_Carico);
        variabile_pulsante = 13;
      }
      break;
    case 16: //aggiorna valore batterie scariche
      Serial.println("16");
      posizione_cursore_altezza = 50;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 16) && ((millis() - pressione_pulsante) > 2000)) {
        variabile_pulsante = 0;
      }
      break;
    case 17: //aggiorna valore batterie scariche
      Serial.println("17");
      variabile_pulsante = 14;
      break;
  }
}

void seleziona_pianta() {
  Serial.println("sel pianta");
  if ((stato_pulsante == LOW) && ((millis() - pressione_pulsante) > TIMEOUT_pressione_pulsante)) {
    variabile_pulsante++;
    pressione_pulsante = millis();
  }
  cancella_schermo();
  myOLED.print(sel_pianta[0], CENTER, 1);
  if ((EEPROM.read(0) == 1) || (EEPROM.read(4) == 1)) {
    myOLED.print(sel_pianta[1], 0, 10);
  } else {
    myOLED.print(sel_pianta[2], 0, 10);
  }
  if ((EEPROM.read(18) == 1) || (EEPROM.read(23) == 1)) {
    myOLED.print(sel_pianta[3], 0, 20);
  } else {
    myOLED.print(sel_pianta[4], 0, 20);
  }
  if ((EEPROM.read(28) == 1) || (EEPROM.read(33) == 1)) {
    myOLED.print(sel_pianta[5], 0, 30);
  } else {
    myOLED.print(sel_pianta[6], 0, 30);
  }
  if ((EEPROM.read(38) == 1) || (EEPROM.read(43) == 1)) {
    myOLED.print(sel_pianta[7], 0, 40);
  } else {
    myOLED.print(sel_pianta[8], 0, 40);
  }
  if ((EEPROM.read(48) == 1) || (EEPROM.read(53) == 1)) {
    myOLED.print(sel_pianta[9], 0, 50);
  } else {
    myOLED.print(sel_pianta[10], 0, 50);
  }
  if ((EEPROM.read(58) == 1) || (EEPROM.read(63) == 1)) {
    myOLED.print(sel_pianta[11], 60, 10);
  } else {
    myOLED.print(sel_pianta[12], 60, 10);
  }
  if ((EEPROM.read(68) == 1) || (EEPROM.read(73) == 1)) {
    myOLED.print(sel_pianta[13], 60, 20);
  } else {
    myOLED.print(sel_pianta[14], 60, 20);
  }
  if ((EEPROM.read(78) == 1) || (EEPROM.read(83) == 1)) {
    myOLED.print(sel_pianta[15], 60, 30);
  } else {
    myOLED.print(sel_pianta[16], 60, 30);
  }
  myOLED.print(sel_pianta[17], 60, 40);
  myOLED.print(sel_pianta[18], 60, 50);
  switch (variabile_pulsante) {
    case 18: // attende interazione utente
      Serial.println("18");
      break;
    case 19: //pianta 1
      Serial.println("19");
      posizione_cursore_altezza = 10;
      posizione_cursore_larghezza = 52;
      cursore_furbo();
      if ((variabile_pulsante == 19) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 0;
        cella_eeprom_asciutto = 4;
        pianta_selezionata = 1;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(0) == 1) || (EEPROM.read(4) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 20: //pianta 2
      Serial.println("20");
      posizione_cursore_altezza = 20;
      posizione_cursore_larghezza = 52;
      cursore_furbo();
      if ((variabile_pulsante == 20) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 18;
        cella_eeprom_asciutto = 23;
        pianta_selezionata = 2;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(18) == 1) || (EEPROM.read(23) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 21: //pianta 3
      Serial.println("21");
      posizione_cursore_altezza = 30;
      posizione_cursore_larghezza = 52;
      cursore_furbo();
      if ((variabile_pulsante == 21) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 28;
        cella_eeprom_asciutto = 33;
        pianta_selezionata = 3;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(28) == 1) || (EEPROM.read(33) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 22: //pianta 4
      Serial.println("22");
      posizione_cursore_altezza = 40;
      posizione_cursore_larghezza = 52;
      cursore_furbo();
      if ((variabile_pulsante == 22) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 38;
        cella_eeprom_asciutto = 43;
        pianta_selezionata = 4;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(38) == 1) || (EEPROM.read(43) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 23: //pianta 5
      Serial.println("23");
      posizione_cursore_altezza = 50;
      posizione_cursore_larghezza = 52;
      cursore_furbo();
      if ((variabile_pulsante == 23) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 48;
        cella_eeprom_asciutto = 53;
        pianta_selezionata = 5;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(48) == 1) || (EEPROM.read(53) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 24: //pianta 6
      Serial.println("24");
      posizione_cursore_altezza = 10;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 24) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 58;
        cella_eeprom_asciutto = 63;
        pianta_selezionata = 6;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(58) == 1) || (EEPROM.read(63) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 25: //pianta 7
      Serial.println("25");
      posizione_cursore_altezza = 20;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 25) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 68;
        cella_eeprom_asciutto = 73;
        pianta_selezionata = 7;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(68) == 1) || (EEPROM.read(73) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 26: //pianta 8
      Serial.println("26");
      posizione_cursore_altezza = 30;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 26) && ((millis() - pressione_pulsante) > 4000)) {
        cella_eeprom_bagnato = 78;
        cella_eeprom_asciutto = 83;
        pianta_selezionata = 8;
        EEPROM.update(250, pianta_selezionata);
        EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
        EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
        if ((EEPROM.read(78) == 1) || (EEPROM.read(83) == 1)) {
          variabile_pulsante = 8;
        } else {
          variabile_pulsante = 0;
        }
      }
      break;
    case 27: //cancella memoria eeprom
      Serial.println("27");
      posizione_cursore_altezza = 40;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 27) && ((millis() - pressione_pulsante) > 4000)) {
        val_bagnato = 1;
        EEPROM.put(0, val_bagnato);
        EEPROM.put(18, val_bagnato);
        EEPROM.put(28, val_bagnato);
        EEPROM.put(38, val_bagnato);
        EEPROM.put(48, val_bagnato);
        EEPROM.put(58, val_bagnato);
        EEPROM.put(68, val_bagnato);
        EEPROM.put(78, val_bagnato);
        val_asciutto = 1;
        EEPROM.put(4, val_asciutto);
        EEPROM.put(23, val_asciutto);
        EEPROM.put(33, val_asciutto);
        EEPROM.put(43, val_asciutto);
        EEPROM.put(53, val_asciutto);
        EEPROM.put(63, val_asciutto);
        EEPROM.put(73, val_asciutto);
        EEPROM.put(83, val_asciutto);
        variabile_pulsante = 18;
      }
      break;
    case 28: // esci
      Serial.println("28");
      posizione_cursore_altezza = 50;
      posizione_cursore_larghezza = 115;
      cursore_furbo();
      if ((variabile_pulsante == 28) && ((millis() - pressione_pulsante) > 2000)) {
        variabile_pulsante = 0;
      }
      break;
    case 29: //ricomincia da pianta 1
      Serial.println("29");
      variabile_pulsante = 19;
      break;
  }
}

Questo blocco puoi metterlo nel setup:

  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

e potresti anche togliere ciò che pensi non ti servirà mai.
Tutta questa cosa è inutile:

somma_batteria = somma_batteria + batteria;
      somma_result = somma_result  + result ;
      nr++;
    }
    if (nr == 10) {
      media_batteria = somma_batteria / nr;
      media_result = somma_result / nr;
      nr = 0;
      somma_batteria = 0;
      somma_result = 0;
    }

Fai due letture dell'ADC, scarta la prima e basta. Mica è un contatore Geiger! :grin:
Non ho mai fatto medie sull'ADC e non ho mai avuto problemi.
Ti consiglio anche di fare una tabella dell'assegnazione delle locazioni di memoria dell'EEPROM:

Locazioni di memoria EEPROM:
 1: 
 2: 
 3: 
 4: 
 5: 
...

Qui c'è una contraddizione:

    cella_eeprom_bagnato = 0;
    cella_eeprom_asciutto = 4;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  // 0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  // 4-5-6-7 occupati

Se le locazioni 0 e 4 sono occupate, ci vai a scrivere?...
Comunque, come detto, anziché:

if (pianta_selezionata == 1) {
    cella_eeprom_bagnato = 0;
    cella_eeprom_asciutto = 4;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 2) {
    cella_eeprom_bagnato = 18;
    cella_eeprom_asciutto = 23;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 3) {
    cella_eeprom_bagnato = 28;
    cella_eeprom_asciutto = 33;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 4) {
    cella_eeprom_bagnato = 38;
    cella_eeprom_asciutto = 43;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 5) {
    cella_eeprom_bagnato = 48;
    cella_eeprom_asciutto = 53;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 6) {
    cella_eeprom_bagnato = 58;
    cella_eeprom_asciutto = 63;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 7) {
    cella_eeprom_bagnato = 68;
    cella_eeprom_asciutto = 73;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }
  if (pianta_selezionata == 8) {
    cella_eeprom_bagnato = 78;
    cella_eeprom_asciutto = 83;
    EEPROM.get(cella_eeprom_bagnato, val_bagnato);  //0-1-2-3 occupati
    EEPROM.get(cella_eeprom_asciutto, val_asciutto);  //4-5-6-7 occupati
  }

farei così:

EEPROM.get (pianta_selezionata*2-1, val_bagnato); // 1, 3, 5, 7, 9, 11, 13, 15.
EEPROM.get (pianta_selezionata*2, val_asciutto); // 2, 4, 6, 8, 10, 12, 14, 16.

Herman, il mostro si chiama Herman Munster

@clarksavagejr:

Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

Ho provato a guardare un po' di cose ma ogni punto è infarcito di inesattezze e ambiguità e io mi perdo. Le variabili globali in gioco sono:

 Valore_Scarico        (long)
 Valore_Carico         (long)
 pianta_selezionata    (byte)
 cella_eeprom_bagnato  (int)
 cella_eeprom_asciutto (int) 
 val_bagnato           (int)  16 bit o 32 bit???
 val_asciutto          (int)  16 bit o 32 bit???

Le prime letture sono le seguenti, ma i commenti non sono congruenti con i tipi dati, perché 5 byte per i tipi long? Perché 4 byte per un tipo byte? Perché 4-5-6-7 occupati se l'indirizzo parte da 250?

EEPROM.get(8, Valore_Scarico);  //8-9-10-11-12 occupati 
EEPROM.get(13, Valore_Carico);  //13-14-15-16-17 occupati
EEPROM.get(250, pianta_selezionata);  //4-5-6-7 occupati

Poi in base al valore di pianta_selezionata si devono andare a pescare i dati (i valori di val_bagnato e val_asciutto). Ma mentre per la pianta 1 gli indirizzi dei valori sono 0 e 4, per le piante seguenti la formula cambia: gli indirizzi dei valori "bagnato" sono 18 28 38 48 ecc, e per i corrispondenti valori "asciutto" sono 5 byte più avanti (di nuovo, perché 5 byte?). La formula per ottenere i 18 28 38 ecc partendo dalla pianta 2 in poi sarebbe:

cella_eeprom_bagnato = ((pianta_selezionata - 1) * 10) + 8;
cella_eeprom_asciutto = cella_eeprom_bagnato + 5;

Però, questi offset di 5 byte... sono un errore o sono voluti?

val_bagnato e val_asciutto vengono da valore_umidità, che conserva il valore di un analogRead, quindi massimo 1023.

Ciao ragazzi, grazie mille ancora per il tempo che mi state dedicando.... ma conto nel WE di mettermi a smanettare e a rispondervi...

nel frattempo ho fatto una prova che mi da un risultato alquanto strano......:
premessa: in attesa di rifare da zero tutto e fare un lavoro decente seguendo i vostri consigli,ho fatto in modo di non far scrivere continuamente al display ottimizzando l'uso della CPU e per vedere se miglirava la precisione di millis... quello che emerge è:

  • facendo di nuovamente debug con un mega(perchè tutti quei serial printl il nano non me li permetteva...) tutto funziona a meraviglia... il ritardo di millis è sparito e tutto funziona come voluto
  • preso il programma funzionante, ripulito da tutti i serial print e messo nel nano, questo va peggio rispetto a quando non avevo ottimizzato l'aggiornamento del display.... convinto di aver pasticciato il codice ho ripreso quello del mega e ho rifatto tutta la pulizia... stesso identico risultato del precedente punto......
  • allora mi sono detto, sarà il mega più performante...(ovviamente) ho messo il codice senza seriale(quello che avevo ripulito dalla seriale per il nano) e fa la stessa cosa identica cosa sul mega, ovvero lentezza infinita anche solo per aggiornare semplicemente il cursore(2000ms di attesa)
    ho rimesso quello con la seriale sul mega e tutto funziona alla grande.....

onestamente mi arrendo...... ma come è possibile?

allego i files(sono identici,solo uno con seriale(MEGA) e uno senza(nano)
v1.11 con debug e ottimizzazione schermo per mega.txt (33.2 KB)
v1.11 con SENZA debug e ottimizzazione schermo per nano.txt (30.7 KB)

Mah, ancora non mi hai convinto

@docdoc l'ultima mia prova fatta nel post #36 conferma che tutto viene eseguito correttamente, comincio a pensare che oltre al pessimo codice che appensantisce troppo, forse la libreria usata è anche lei troppo pesante?

cioè se si resta per più di 2 secondi nello stesso case il timer scade e viene eseguita l'azione.

@Claudio_FF si questo è quello che volevo proprio fare

Quindi la domanda è: dove nel design del codice di simosere ci ingolfiamo, riconosciamo i tempi in ritardo e aggiorniamo altrettanto in ritardo?

@Claudio_FF come detto dalle prove fatte nel post #36 non è un problema di reset o di ritardo nell'aggiornamento di millis....

Questo blocco puoi metterlo nel setup:

  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

@Datman se metto questo blocco nel setup nel mega tutto ok, se lo metto nel nano la lettura della batteria non va, da valori a caso, per il momento ho tolto il calcolo medio e lasciato lettura singola... grazie!!

Ho provato a guardare un po' di cose ma ogni punto è infarcito di inesattezze e ambiguità e io mi perdo. Le variabili globali in gioco sono:

hai ragione, tra copia incolla qualche fregnaccia c'è avoglia...

Per poterlo rendere più comprensibile, efficiente e anche modulare, dovrei sapere se per ogni pianta è possibile creare una struttura dati che la descrive.

si esatto, ogni pianta a quelle tre informazioni che vengono richiamati con la lettura eeprom, ma val bagnato e val asciutto sono valori int, e se ho capito bene 16 bit...(ci provo)

Questa domanda è importante e quindi vista l'importanza e bene rispondere.

sei stato molto chiaro e grazie per il tempo che mi hai dedicato... purtoppo il mio mindset non è per nulla portato alla programmazione o per lo meno non ha radici culturali nel settore, se non da autodidatta e quindi non mi risulta facile ragionarla nel modo che tu mi hai effettivamente fatto notare... diciamo che l'obbiettivo, per incapacità magari e mancanza di tempo, è arrivare a dama nel minor tempo possibile.... :frowning:

RAGAZZI, per tutto ciò che riguarda i vostri commenti sul codice che non capite e sull'ottimizzazione tipo della eeprom, devo rivedere bene per darvi una risposta sui vari perchè sono cosi e fare delle prove con le vostre proposte e vedere se già cosi un minimo migliora.... e magari poi ridisegnarlo completamente...

spero di aver risposto a tutti, nel pomeriggio mi metto a rivedere il codice e magari riesco ad alleggerirlo un pò in base ai vostri consigli...

cmq aggiungo che il codice del post #36 del nano occupa questo:

Lo sketch usa 15074 byte (49%) dello spazio disponibile per i programmi. Il massimo è 30720 byte.
Le variabili globali usano 809 byte (39%) di memoria dinamica, lasciando altri 1239 byte liberi per le variabili locali. Il massimo è 2048 byte.

non mi sembra un codice cosi tanto pesante... boh

Quale libreria?

void setup() {
    Serial.begin()115200);
     // qui il tuo codice per inizializzare display e pin ecc.
    uint32_t us = micros();
    myOLED.print(Menu[0], CENTER, 1);
    Serial.println(micros() - us);
     
}
void loop() {
#if(0)
// qui tutto il tuo codice nel loop attuale

#endif
}

Questo codice serve a visualizzare il costo tempo della chiamata a funzione myOLDE.print(...
Al posto di questa chiamata a funzione ci puoi mettere la chiamata a funzione cancella_schermo().

Riporta i dati che stampa, così vediamo tutti quando impiegano queste funzioni.

Ciao.

la libreria è questa: #include <OLED_I2C.h>

const char* Menu[] = {"Menu", "Cal.Sensore", "Cal.Batteria", "Monit.Pianta", "Seleziona Pianta", "Esci"};
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
extern uint8_t SmallFont[];

void setup() {
  Serial.begin(115200);
  myOLED.begin();   // avvia oled
  myOLED.setBrightness(255);  // setta luminosit  oled
  myOLED.setFont(SmallFont);
  // qui il tuo codice per inizializzare display e pin ecc.
  uint32_t us = micros();
  myOLED.print(Menu[0], CENTER, 1);
  myOLED.update();
  Serial.println(micros() - us);

}
void loop() {
#if(0)
  // qui tutto il tuo codice nel loop attuale

#endif
}

questo il risultato: 3744

const char* Menu[] = {"Menu", "Cal.Sensore", "Cal.Batteria", "Monit.Pianta", "Seleziona Pianta", "Esci"};
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
extern uint8_t SmallFont[];

void cancella_schermo() {
  myOLED.clrScr();
}

void setup() {
  Serial.begin(115200);
  myOLED.begin();   // avvia oled
  myOLED.setBrightness(255);  // setta luminosit  oled
  myOLED.setFont(SmallFont);
  // qui il tuo codice per inizializzare display e pin ecc.
  uint32_t us = micros();
  //myOLED.print(Menu[0], CENTER, 1);
  cancella_schermo();
  myOLED.update();
  Serial.println(micros() - us);

}
void loop() {
#if(0)
  // qui tutto il tuo codice nel loop attuale

#endif
}

questo il risultato: 1344

const char* Menu[] = {"Menu", "Cal.Sensore", "Cal.Batteria", "Monit.Pianta", "Seleziona Pianta", "Esci"};
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL);
extern uint8_t SmallFont[];

void cancella_schermo() {
  myOLED.clrScr();
}

void setup() {
  Serial.begin(115200);
  myOLED.begin();   // avvia oled
  myOLED.setBrightness(255);  // setta luminosit  oled
  myOLED.setFont(SmallFont);
  // qui il tuo codice per inizializzare display e pin ecc.
  uint32_t us = micros();
  myOLED.print(Menu[0], CENTER, 1);
  cancella_schermo();
  myOLED.update();
  Serial.println(micros() - us);

}
void loop() {
#if(0)
  // qui tutto il tuo codice nel loop attuale

#endif
}


questo il risultato: 3104

aggiungo solo un'ultima cosa: basta solo che inserisco il serial.begin(9600) che non mi si avvia più il display.... carica il codice ma ottengo schermata nera..... lo tolgo e riparte con tutti i rallentamenti del caso....