Go Down

Topic: Come usare tanti Switch Case (o If) [Problemi memoria?] (Read 2586 times) previous topic - next topic

Giorgio

Ciao a tutti,
ho alcuni grossi problemi, nel caricare uno sketch su Arduino UNO / DUEMILANOVE.

il mio progetto prevede una serie di lezioni progressive, che al momento ho provato a inserire mediante vari metodi, che vanno da 0 a 139.

Code: [Select]
  switch(progress)
  {
case 0:TestRx= "U";break;
case 1:TestRx= "A";break;
case 2:TestRx= "UAU";break;
case 3:TestRx= "AAU";break;
case 4:TestRx= "AUA";break;
case 5:TestRx= "UAA";break;
case 6:TestRx= "V";break;
etc etc etc....fino al case 139.


Oppure ho provato con:

Code: [Select]
if (progress==1) {TestRx= "U";}
else if (progress==1) {TestRx= "A";}
else if (progress==2) {TestRx= "UAU";}
else if (progress==3) {TestRx= "AAU";}
else if (progress==4) {TestRx= "AUA";}
else if (progress==5) {TestRx= "UAA";}
else if (progress==6) {TestRx= "V";}
else if (progress==7) {TestRx= "VUA";}
etc etc...


e anche con:

Code: [Select]
  PROGMEM prog_char *strings[] ={
//"U",
//"A",
//"UAU",
//"AAU",
//"AUA",
//"UAA",
//"V",
... etc etc
TestRx=strings[progress];



Il mio problema è che non appena assegno un valore a "progress" attivando la relativa funzione, Arduino impazzisce completamente.

Sul mega tutto funziona benissimo, ma io ho necessità di caricare questo set di 139 lezioni progressive.
Per essere precisi avrei bisogno di caricare 2 set da 139 lezioni.

Vi viene in mente qualche metodo per caricare questi 139 stati in maniera più risparmiosa possibili in termini di ram?
Utilizzando PROGMEM nel modo in cui l'ho utilizzato al momento di caricare lo sketch e farlo partire va tutto bene, ma Arduino impazzisce non appena assegno un valore a "progress".

Sarebbero ben accette ottime idee :) per poter caricare questi set di lezioni su un Arduino Uno o Duemilanove.

grazie
Giorgio

leo72

Gestire tutte quelle variabili e stringhe differenti può saturare la memoria.
L'Arduino UNO non ha tutta la RAM che servirebbe. Sappi che ogni stringa contenuta nello sketch, prima di poter essere usata, viene copiata nella RAM, che è di soli 2 kB.

Inoltre tutti i salti degli if e degli switch..case creano anch'essi dati che vengono memorizzati nello stack di sistema per i salti di rientro dalle subroutine, e lo stack "vive" anch'esso nella RAM.


superlol

esiste un sistema per caricare le variabili in rom invece che ram.

comunque dai una letta a
http://arduino.cc/en/Reference/Volatile
e
http://arduino.cc/en/Reference/PROGMEM
Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

leo72

Lui ha già detto di aver usato Progmem. Il problema sono comunque anche i vari case dello switch. Ogni salto salva nello stack l'indirizzo del PC (Program Counter) per riprendere l'esecuzione una volta terminata l'esecuzione della subroutine chiamata. Poi bisogna anche vedere il resto dello sketch cosa fa, se ad esempio vengono caricate librerie esterne, viene usata la seriale, vengono stampati dati su un LCD ecc... tutte cose che possono aumentare il consumo di memoria.

Giorgio

Si, ho 2-3 librerie e scrivo su LCD.
Mi ritrovo a sketch partito SENZA lezioni, con 641 bytes di memoria liberi.
Se carico un set di lezioni, parto con 120, praticamente appena introduco un carattere Arduino impazzisce...letteralmente...

leo72

E' la memoria, te lo garantisco.
Non puoi usare la MEGA?

m_ri

#6
Sep 13, 2012, 11:48 pm Last Edit: Sep 14, 2012, 12:46 am by m_ri Reason: 1

Lui ha già detto di aver usato Progmem. Il problema sono comunque anche i vari case dello switch. Ogni salto salva nello stack l'indirizzo del PC (Program Counter) per riprendere l'esecuzione una volta terminata l'esecuzione della subroutine chiamata. Poi bisogna anche vedere il resto dello sketch cosa fa, se ad esempio vengono caricate librerie esterne, viene usata la seriale, vengono stampati dati su un LCD ecc... tutte cose che possono aumentare il consumo di memoria.

dove le vedi le call??  :D i case son delle jump,o se è furbo usa una jump table a va velocissimo..
lo so,sono un rompi****e che mette i puntini sulle i

superlol

comunque se sono librerie esterne magari prova ad ottimizzarle eliminando cose inutili (ad esempio nell'lcd la funzione per creare caratteri custom se non la usi ec...) forse riesci a recuperare quel che ti serve :D
Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

leo72


dove le vedi le call??  :D i case son delle jump

Probabilmente hai ragione.
E vista l'ora, non ho voglia di disassemblare un firmware per vedere come il compilatore traduce gli switch..case  :P

m_ri

io invece vado direttamente a dormire...
buonanotte guys!!

astrobeed

#10
Sep 14, 2012, 10:54 am Last Edit: Sep 14, 2012, 11:21 am by astrobeed Reason: 1

dove le vedi le call??  :D i case son delle jump,o se è furbo usa una jump table a va velocissimo..
lo so,sono un rompi****e che mette i puntini sulle i


La switch case viene codificata come una serie di chiamate a subroutine, una per ogni funzione invocata, e ovviamente sono delle call, i jump sono esclusivamente per la break che salta direttamente alla fine della switch.
Ovviamente di call ne viene eseguita solo una, ovvero quella della condizione valida, e occupa nello stack solo lo spazio riservato ad una singola chiamata a subroutine,  però a livello di flash viene utilizzata una word (call) per ogni funzione inserita nella switch che va a pesare sull'impiego della memoria di programma, ma non sulla ram.
Da notare che la riga "case 0:TestRx= "U";break; " viene totalmente memorizzata nella flash, la "U" viene considerata come rom constant e posta direttamente nella flash senza necessità di usare progmem.


PaoloP

E se provassi a registrare le sigle nella Eprom o in una eprom esterna o in una SD?
Dovresti fare solo una funzione per richiamare il dato in base all'indice.

m_ri

#13
Sep 14, 2012, 11:35 am Last Edit: Sep 14, 2012, 11:50 am by m_ri Reason: 1
@astrobeed: solitamente,gli switch vengono tradotti in una serie di cmp/test e jump..ho provato a fare un po' di disassemblaggio adesso,ed è così...
altrimenti,come ho detto prima,in alcuni casi,e se l'ottimizzazione è buona,lo switch viene tradotta in jump table..ossia usa l'argomento dello switch come indice in un vettore di puntatori a codice(ossia la cella i-esima del vettore contiene il puntatore al codice da eseguire nel caso la variabile valesse i,più alcune ottimizzazioni)..può essere che in alcuni casi usi la call,ma non mi vengono i mente..
EDIT: anche perchè il compilatore come fa a fare le call condizionate?al massimo può usare call + branch table,ma direi che ha più overhead di una jump table ..

amacbr

ma invece provare qualcosa di questo tipo:

se la prima lettera e' "U" allora
---se la seconda e' una "A" allora
------se la terza e' una "U" allora
---------azione da fare per la combinazione UAU
------else la terza e' una "A" allora
---------azione da fare per la combinazione UAA

non migliorerebbe l'occupazione di memoria? forse ancora meglio sarebbe definendo le lettere possibili come constanti (si puo'?) e poi fare le varie combinazioni con le constanti...
"Cosi non si va avanti..." disse il gambero

Go Up