Simboli strani sul display

Ciao ragazzi!innanzi tutto Buon Natale a tutti!
Volevo chiedere un consiglio agli esperti di questo forum. Da qualche giorno mi sono imbattuto in un problema strano!
Sto usando un termistore per rilevare la temperatura dell'acqua dei miei termosifoni e in base alla temperatura rilevata, viene visualizzato un programma sul mio display LCD.
Esempio
0 -40°C --->Programma1
40-50°C ---> Programma2
.
.
.
fino a qui tutto bene, funziona tutto e viene tutto visualizzato sul display per una mezzoretta circa, dopo di che appaiono dei simboli tipo questi:

sapreste aiutarmi?vi posto anche il codice che ho creato per stampare su monitor:

void stampalcd(int valore_programma, int t_acqua, int t_sonda, int errore){

  if(errore ==0){
    if(t_sonda_precedente != t_sonda || t_acqua_precedente!= t_acqua || programma_precedente != valore_programma)
    {
      lcd.clear();
      lcd.setCursor(0,0);

      if (valore_programma == 1){
        lcd.print("Load Wood");
      }
      if (valore_programma == 2){
        lcd.print("Programma 1");
      }
      if (valore_programma == 3){
        lcd.print("Programma 2");
      }
      if (valore_programma == 4){
        lcd.print("Programma 3");
      }
      if (valore_programma == 5){
        lcd.print("Programma 4");
      }

      lcd.setCursor(0,1);
      lcd.print("H20:");
      lcd.print(t_acqua);
      lcd.print(" / ");
      lcd.print("T-c");
      lcd.print(t_sonda);
      t_sonda_precedente = t_sonda;
      t_acqua_precedente = t_acqua;
      programma_precedente = valore_programma;
    }
  }
  else
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Errore!");
  }
}

non so proprio più che pesci prendere.

Mi sembra un classico caso di saturazione della memoria Ram.
Lo sketch che stai usando è molto grande o include molte librerie o fa uso di tante variabili testuali?

Si, in effetti lo sketch è molto grande e poi uso 4 librerie. Come variabili testuali uso soltanto una variabile di tipo string

comunque mi sembra strano. Perchè per accendere e spegnere il sistema ho un pulsante.
Quando spengo il sistema riazzero tutte le variabili, che penso sia utile a svuotare la ram.
Il problema adesso sono due:

  • quando si presenta questo problema, anche quando schiaccio il pulsante per spegnere il sistema, al riavvio il problema si presenta fin dall'inizio. Per ripristinare tutto devo per forza utilizzare il tasto di reset.
  • provando qualunque cosa, adesso ho tolto il termistore e a posto di questo ho messo un semplice potenziometro che utilizzo per far variare, in modo manuale, la temperatura.
    Il sistema è acceso da circa un ora e non fa una piega...

cosa sta succedendo?! :astonished:

Sta succedendo che la RAM è pulita all'avvio ma nella RAM le variabili vengono continuamente create e distrutte, inoltre ogni stringa che deve essere stampata sul display viene letta dalla Flash e poi caricata in Ram, da cui viene poi elaborata.
Infine, nella Ram vive lo stack, dove vengono memorizzate tutti i punti di rientro di salti a subroutine.
Tenendo conto che di Ram l'Atmega ne ha 2 kB, si fa presto ad esaurirla.

Ti consiglio questa lettura:
http://www.leonardomiliani.com/?p=572

ed inoltre l'utilizzo della funzione F() per salvare direttamente su Flash tutti i messaggi testuali del tuo sketch.
Esempio:
lcd.print("TEMPERATURA: ");
diventa
lcd.print(F("TEMPERATURA: "));

ok...adesso mi metto all'opera..ma perchè l'errore non sussiste con il potenziometro?

Innanzi tutto leo72 grazie per la risposta....
Ho seguito la tua guida utilizzando l'avr-size e quello che mi restituisce sullo sketch del mio programma è questo:

Device: Unknown

Program: 18710 bytes
(.text + .data + .bootloader)

Data: 815 bytes
(.data + .bss + .noinit)

hermit274:
ok...adesso mi metto all'opera..ma perchè l'errore non sussiste con il potenziometro?

Non so. Dovresti studiarti il codice e vedere se ci sono possibili punti deboli. Ad esempio un array che va fuori indice. Delle conversioni ecc.. non so.

ho delle domande sulla funzione F() (a proposito ma nel Reference dove devo cercarla questa funzione)

  1. quando si usa la F() per memorizzare una stringa testuale, la stringa per essere visualizzata non deve cmq passare per la ram ?

  2. la si puo' usare anche per memorizzare una variabile, tipo la misura di un sensore ? (Credo cmq che non avrebbe senso farlo)

  1. No, è fatto apposta per evitare di consumare RAM.

  2. No, non è applicabile alle variabili.

Della funzione F() ne parla qui --> Serial.print() - Arduino Reference

You can pass flash-memory based strings to Serial.print() by wrapping them with F(). For example :
Serial.print(F(“Hello World”))

grazie, e progmem invece ? e' un suo concorrente o serve ad altro ?

quando ho scritto deve passare per la ram, intendo un passaggio in sottfondo, non so come spiegarmi, cioe' la cpu per poter stampare il dato non e' obbligata a ricevere il flusso dei dati attraverso la ram ? credo abbia a che fare con le architetture delle cpu, invece di studiarmelo chiedo e faccio prima :slight_smile:

Testato:
grazie, e progmem invece ? e' un suo concorrente o serve ad altro ?

progmem è un alias dell'attributo ATTR_PROGMEM definito nelle librerie avr che servono ad istruire il compilatore a trattare i dati seguenti dalla Flash:
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

La funzione F() altro non è che un altro alias che inserisce questo codice:

#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

Rilevata la parola chiave __FlashStringHelper, la libreria Print.h recupera i dati della stringa in byte alla volta dalla memoria Flash

size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

quando ho scritto deve passare per la ram, intendo un passaggio in sottfondo, non so come spiegarmi, cioe' la cpu per poter stampare il dato non e' obbligata a ricevere il flusso dei dati attraverso la ram ? credo abbia a che fare con le architetture delle cpu, invece di studiarmelo chiedo e faccio prima :slight_smile:

Normalmente in un'architettura Harvard i dati vengono sempre caricati in Ram e poi da lì trattati.
Ovviamente un microcontrollore è capace anche, con determinati comandi, di gestire dei dati dalla Flash. E' ciò che aiuta a fare PROGMEM, grazie al quale il compilatore viene istruito affinché carichi i dati non in Ram prima di passarli nei registri ma direttamente in essi.

grazie ora e' tutto piu' chiaro
ultima cosa, quindi sia progmem che f() sono strumenti per caricare dei dati senza passare dalla ram, ma ad oggi, con le release attuali dell'ide, la f() ha sostituito completamente il comando progmem, oppure ci sono casi in cui e' meglio usare l'uno e non l'altro ? (si capisce che non ho colto granche' dal codice allegato ? :grin:)

Testato:
grazie ora e' tutto piu' chiaro
ultima cosa, quindi sia progmem che f() sono strumenti per caricare dei dati senza passare dalla ram, ma ad oggi, con le release attuali dell'ide, la f() ha sostituito completamente il comando progmem, oppure ci sono casi in cui e' meglio usare l'uno e non l'altro ? (si capisce che non ho colto granche' dal codice allegato ? :grin:)

Partiamo da un concetto. In Flash con PROGMEM puoi gestire SOLO costanti. Dati fissi che non cambiano durante l'esecuzione del programma perché in Flash non puoi scriverci (non è del tutto vero, però prendi per buona quest'affermazione relativamente al discorso che stiamo facendo).
Ora, F() serve solo per gestire stringhe, che in C sono costanti. Difatti una stringa è un array di char, un tipo di dati non modificabile.
Se devi usare altri tipi di dato, allora devi usare PROGMEM.

Attento che il problema non è tanto dire al compilatore di lasciare un dato in Flash, quanto quello di farglielo recuperare, quel dato. :wink:

karma+1
thanks :slight_smile:

Ciao Ragazzi!
Sono ancora alle prese con il progetto sopra indicato. Dai consigli di leo72, ho fatto tutto ciò che mi ha detto cercando di alleggerire il codice e liberare quanta più ram possibile.
Per sapere quanta ram mi rimane libera durante l'esecuzione del programma, ho utilizzato la funzione freeRam() presente nella sua guida al link che lui ha indicato.
Durante l'esecuzione del programma, sto facendo stampare sul display LCD la memoria libera e mi visualizza costantemente 1579byte liberi.
Il bello è che dopo un oretta che arduino è acceso, i simboli strani sul monitor si presentano di nuovo...
uffaaaaa!!!come mai?non ci sto capendo più niente

nessuno ha un consiglio?

Controlla i collegamenti e creati un secondo sketch col minimo indispensabile per il funzionamento del display.
Se è tutto a posto allora il problema è nel codice corrente.

1579 libero vuol dire che ne stai consumando veramente poca, il tuo problema deve essere di carattere hardware.
prova semplicemente a tenere in stampa hello world e vedi cosa fa.

Oppure che lo sketch riempie col tempo la RAM (stack e/o heap che saturano la memoria). Il fatto che prima il problema compariva quasi subito ed ora, a RAM sgombra, compaia in ritardo (perché ci mette di più a consumare tutta la RAM) fa pensare anche a questo.