risparmiare ram

ciao a tutti :slight_smile:
io so che ogni volta che faccio scrivere un testo su un lcd utilizzo della ram perchè l'arduino salva quello che devo scrivere su essa.
volevo sapere c'è un modo per evitare ciò?
premetto che non ho la shield per la memory card e non posso neanche comprarla.
posso usare la eeprom? se si come?
grazie :slight_smile:

lupo95:
ciao a tutti :slight_smile:
io so che ogni volta che faccio scrivere un testo su un lcd utilizzo della ram perchè l'arduino salva quello che devo scrivere su essa.
volevo sapere c'è un modo per evitare ciò?
premetto che non ho la shield per la memory card e non posso neanche comprarla.

E non ti servirebbe neanche a nulla perché dovresti comunque caricare dalla SD i dati nella RAM del microcontrollore.

posso usare la eeprom? se si come?
grazie :slight_smile:

Non ti serve, basta che usi la funzione F() per leggere direttamente dalla Flash le stringhe.
Quindi una stringa scritta con Serial.print("MARIO") o LCD.print("MARIO") diventa Serial.print(F("MARIO")) o LCD.print(F("MARIO"))

ma se allora non serve scriverla prima sulla flash o epprom cosa cambia per la ram l'utilizzo della funzione F() ?

lupo95:
ma se allora non serve scriverla prima sulla flash o epprom cosa cambia per la ram l'utilizzo della funzione F() ?

Che non accetta variabili come argomento ma solo costanti, ne abbiamo già discusso la settimana scorsa, mi pare.
Quindi Serial.print(F(a)) non funziona, non puoi costruire a e poi passarla.
Però per i messaggi standard funziona.

L'alternativa è usare PROGMEM ma anche qui si lavora solo con costanti.
http://www.arduino.cc/playground/Main/PROGMEM

ok grazie mille :slight_smile: non avevo capito XD
scusa il disturbo :slight_smile:

Tutto ciò che deve essere trattato dal programma viene caricato in RAM.
Quindi quando tu fai un Serial.print("Mario") viene creata una stringa in memoria e lì viene copiato il contenuto di "Mario" che è nel programma utente memorizzato in Flash. Ricapitoliamo: riservo una porzione di RAM; ci copio i dati dalla Flash; dalla RAM li prelevo e li passo alla funzione che li deve usare.

Se le scritte diventano molte, la RAM si esaurisce in breve tempo, perché oltre a queste stringhe essa deve contenere anche lo stack del programma e tutte le altre variabili.

Con F() si usa PROGMEM in modo trasparente per l'utente, PROGMEM istruisce il compilatore ad usare i dati prelevandoli direttamente dalla memoria Flash invece che a ricopiarli prima in RAM. Il rovescio della medaglia è appunto che questi dati devono essere costanti, perché nella Flash non puoi scriverci a runtime (non è del tutto vero, ma prendi quest'affermazione per buona).

ok ti ringrazio ancora :slight_smile:

oggi in questo topic http://arduino.cc/forum/index.php/topic,135034.0.html era venuto fuori il discorso della dimensione delle variabili, è giusto quello che dico lì? anche quello influisce sulla ram no?

?R:
è giusto quello che dico lì? anche quello influisce sulla ram no?

Eccome se influisce sull'uso della ram, usare un int dove basta uno char vuol dire utilizzare il doppio della ram necessaria, ancora peggio usare una variabile globale int per indicare un pin, due byte di ram sprecati per nulla quando si può fare con una #define che non usa nemmeno un bit di ram.
Anche nei calcoli serve molto più tempo cpu per fare qualunque operazione aritmetica su un int rispetto ad uno char/byte visto che il 328 è un processore a otto bit.

approposito dei define, nel reference c'è scritto che è meglio usare const, ma alla fine è lo stesso no?

?R:
approposito dei define, nel reference c'è scritto che è meglio usare const, ma alla fine è lo stesso no?

in c... e quindi spero anche con arduino... il define è visto come una direttiva al precompilatore: in pratica prima ancora di compilare il programma il codice viene "tradotto" o meglio le istanze del define vengono sostituite con il valore in modo letterale. Mentre il const è di fatto trattato come una variabile memorizzata in ram che non viene più sovrascritta.
Penso che il const possa essere più chiaro a livello di codice perchè chiarisce il tipo (int, byte, char eccetera) inoltre il define ha una dichiarazione "un po' più strana" nel senso che per esempio non c'è il ";"... copia proprio di brutto tutto quello che gli metti dentro compresi caratteri non significativi e robe simili...ma io se posso uso il define.
A livello di compilazione io non so bene come si comporta il compilatore arduino ma nei PC venivano tradotti per quanto ho scritto sopra in modo molto diverso perchè per il define faceva un indirizzamento "immediato" mentre il const, dato che accede alla ram, faceva un indirizzamento diretto alla memoria... una cosa tipo
MOV registro, 10 //DEFINE
MOV registro, IndirizzoCostanteInRam //const
...nei pc la scrittura dalla ram poteva implicare più cicli di clock... però è passato tanto tempo ed arduino ha una architettura differente...

?R:
approposito dei define, nel reference c'è scritto che è meglio usare const, ma alla fine è lo stesso no?

Da prove che ho fatto in passato, usare un #define o un const byte per un pin è del tutto equivalente. Il compilatore ottimizza e l'impegno di ram finale dello sketch è identico sia usando la prima che la seconda soluzione.

Su questo sketch:

#define PIN 13

void setup() {
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN, HIGH);
}

void loop() {
}

avr-size dà il seguente responso: 876 di flash e 9 byte di ram.

Su questo sketch:

const byte PIN = 13;

void setup() {
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN, HIGH);
}

void loop() {
}

avr-size dà gli stessi identici risultati: 876 byte di flash e 9 byte di ram.

Invece senza specificare "const":

byte PIN = 13;

void setup() {
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN, HIGH);
}

void loop() {
}

avr-size dice che lo sketch occupa 882 byte di flash e 11 byte di ram.

ok grazie delle conferme, magari tra qualche periodo provo anch'io quei programmi di avr che usate voi, sono cose molto interessanti :wink:

?R:
oggi in questo topic http://arduino.cc/forum/index.php/topic,135034.0.html era venuto fuori il discorso della dimensione delle variabili, è giusto quello che dico lì? anche quello influisce sulla ram no?

Veramente li parlavamo di spazio occupato dalla SRAM non RAM dove vengono allocate le variabili a meno che per ram non intendevi sram, che nel caso della UNO è di 2k nella MEGA invece 8k

pablos:
Veramente li parlavamo di spazio occupato dalla SRAM non RAM dove vengono allocate le variabili a meno che per ram non intendevi sram, che nel caso della UNO è di 2k nella MEGA invece 8k

RAM (Random Access Memory) è il termine generico per indicare la memoria di un micro dove puoi sia leggere che scrivere e accedere liberamente ad una qualunque singola cella, SRAM e DRAM sono due termini che identificano la tecnologia della RAM, SRAM = Static RAM, DRAM = Dynamic RAM, però sempre di RAM si tratta e svolge la stessa funzione.

leo72:
Da prove che ho fatto in passato, usare un #define o un const byte per un pin è del tutto equivalente. Il compilatore ottimizza e l'impegno di ram finale dello sketch è identico sia usando la prima che la seconda soluzione.

Vero però c'è una differenza sostanziale tra i due metodi, se usi un const viene creata una variabile di tipo costante sfruttando la flash, se usi #define viene sostituito il valore in fase di compilazione direttamente nell'espressione.
Utilizzando const il codice è di questo tipo

const byte pin 13;
digitalWrite(pin, HIGH);

Utilizzando "#define pin 13" la digitalWrite, dopo la compilazione, diventa equivalente a:

digitalWrite(13, HIGH);

Anche se la differenza può sembrare minima, quasi inutile, in realtà cambia molto a livello di run time perché nel primo caso il codice deve indirizzare una variabile per recuperare il valore di pin, nel secondo caso il valore è subito disponibile nel codice assembly senza doverlo recuperare, questo si traduce in diversi cicli macchina risparmiati e di conseguenza un codice più veloce.
Da notare che per accedere ad un valore posto nella flash è necessario utilizzare l'istruzione LPM (load Program Memory) che aggiunge un ulteriore overhead di cicli macchina per il recupero del valore di una variabile.

questo codice...

#define BOO 3

const byte bii = 2;

byte res;
byte ciccio;
void setup() {
 
 ciccio = BOO; 
 res = bii;
}

void loop() {
   
  ciccio++;
  res++;
 
}

viene tradotto così:

00000000 <setup>:
   0:   83 e0           ldi     r24, 0x03       ; 3    <-- ciccio = BOO (DEFINE)
   2:   80 93 00 00     sts     0x0000, r24
   6:   82 e0           ldi     r24, 0x02       ; 2     <-- res = bii (const)
   8:   80 93 00 00     sts     0x0000, r24
   c:   08 95           ret

Disassembly of section .text.loop:

00000000 <loop>:
   0:   80 91 00 00     lds     r24, 0x0000
   4:   8f 5f           subi    r24, 0xFF       ; 255
   6:   80 93 00 00     sts     0x0000, r24
   a:   80 91 00 00     lds     r24, 0x0000
   e:   8f 5f           subi    r24, 0xFF       ; 255
  10:   80 93 00 00     sts     0x0000, r24
  14:   08 95           ret

ho dovuto complicarlo un po' perchè questo compilatore non è proprio tanto rinc0glionito... fa delle ottimizzazioni non esattamente scontate... infatti pensavo di aver capito tutto ed invece non ho capito proprio nulla...
allora lasciando stare la parte dove l'unica cosa curiosa è che per incrementare di 1 un byte lui toglie 255 :astonished: (...sti c@zzi) si vede che le due assegnazioni che ho fatto in setup sono tradotte pari pari.... quindi nessun risparmio in questo caso... quindi il mio messaggio precedente è del tutto errato: tanto per cambiare.

astrobeed, ciò è vero su un PC ma avr-gcc compila ottimizzando il codice ed i 2 listati sono trasformati nello stesso identico sorgente assembly. Il compilatore vede appunto che la variabile PIN è una const e la tratta nello stesso identico modo di una #define.

Avevo già fatto a suo tempo delle prove, le ho rifatte stamani con i 2 listati che ho pubblicato qualche post prima: "define.txt" contiene la versione assembly dello sketch che usa la #define, "const.txt" quella invece che usa la const byte.
Risultato di diff eseguito su di essi:

[leo@desktop-hp build8853307674189123112.tmp]$ diff define.txt const.txt -s
I file define.txt e const.txt sono identici

const.txt (13.4 KB)

qsecofr:
ho dovuto complicarlo un po' perchè questo compilatore non è proprio tanto rinc0glionito... fa delle ottimizzazioni non esattamente scontate...

Non è semplice, anche con poche righe di codice, capire cosa combina il compilatore e come ottimizza, spesso e volentieri il solo modo per verificare rapidamente se c'è stato un guadagno, o una perdita, di velocità sul nostro codice è fare delle misure strumentali.
Più tardi faccio un paio di prove, mirate a rilevare la reale differenza in cicli macchina tra l'uso di const e define, con l'utilizzo dell'analizzatore di stati logici in modo da poter misurare con precisione l'effettiva differenza.

leo72:
astrobeed, ciò è vero su un PC ma avr-gcc compila ottimizzando il codice ed i 2 listati sono trasformati nello stesso identico sorgente assembly. Il compilatore vede appunto che la variabile PIN è una const e la tratta nello stesso identico modo di una #define.

No, non è così, a parte che pure sul pc valgono le stesse regole e i compilatori ottimizzano sempre e comunque, certo sul pc non hai la flash con tutte le relative problematiche, però rimane il fatto che una const è una variabile e la define è una sostituzione operata dal compilatore con relative differenze nei metodi di indirizzamento.
Comunque lasciamo la parola definitiva agli strumenti, che non mentono mai, e vediamo cosa viene fuori dal test pratico, dovrei riuscire a farlo in giornata.