Go Down

Topic: Simboli strani sul display (Read 6634 times) previous topic - next topic

hermit274

Dec 26, 2012, 11:01 am Last Edit: Jan 09, 2013, 08:11 pm by hermit274 Reason: 1
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:

Code: [Select]
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.

leo72

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?

hermit274

#2
Dec 26, 2012, 11:29 am Last Edit: Dec 26, 2012, 11:32 am by hermit274 Reason: 1
Si, in effetti lo sketch è molto grande e poi uso 4 librerie. Come variabili testuali uso soltanto una variabile di tipo string

hermit274

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?! :smiley-eek:

leo72

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: "));

hermit274

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

hermit274

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)

leo72


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.

Testato

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)
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

PaoloP

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

2. No, non è applicabile alle variabili.

Della funzione F() ne parla qui --> http://arduino.cc/en/Serial/Print
Quote
You can pass flash-memory based strings to Serial.print() by wrapping them with F(). For example :
Serial.print(F("Hello World"))

Testato

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 :)
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

leo72


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:
Code: [Select]
#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
Code: [Select]
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;
}


Quote

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 :)

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.

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 ?  :smiley-mr-green:)
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

leo72


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 ?  :smiley-mr-green:)

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.
http://arduino.cc/en/Reference/PROGMEM

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

Testato

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Go Up