Go Down

Topic: Problemone con PROGMEM :( (Read 10558 times) previous topic - next topic

nid69ita

#15
Mar 27, 2014, 02:51 pm Last Edit: Mar 27, 2014, 02:55 pm by nid69ita Reason: 1

Scusa leo72 ho letto male..
ho un po di confusione.  Ho messo in tutti gli array const....
adesso che sono in memoria , per inviare i codici all AC devo leggerli con  
Pgm_read_word ...ma li devo salvare su un buffer [256] e poi inviarli direttamente?
Grazie a tutti intanto


Non sono sicuro ma credo di si, perchè la libreria che usi si aspetta un array nella SRAM e non nella Flash.
Forse si potrebbe modificare la libreria per leggere l'array da Flash (PROGMEM) usando il comando indicato da @Leo
Potrei provare (appena posso) se mi metti il link alla libreria e il tuo sketch.
Altra cosa, al primo post parli di array da 60, ora di 256, come mai ?
my name is IGOR, not AIGOR

roxdragon

#16
Mar 27, 2014, 02:58 pm Last Edit: Mar 27, 2014, 03:01 pm by roxdragon Reason: 1
quindi:

int x;
unsigned int ircode[256];

void setup(){...}

void loop(){
for(x=0; ???
}
non sapendo quanti elementi ci sono nel mio array come faccio?
perche se ircodel ho dichiarato 256 e C30 (array in progmem ha 145 elementi per dire come faccio?
Il codice che non riesco a scrivere deve fare questo:
- leggere C30 che sarebbe l array sulla progmem
- copiare quell'array su un nuovo buffer non sapendo quanti elementi ha C30





leo72


Non sono sicuro ma credo di si, perchè la libreria che usi si aspetta un array nella SRAM e non nella Flash.
Forse si potrebbe modificare la libreria per leggere l'array da Flash (PROGMEM) usando il comando indicato da @Leo


Tutto il codice è scritto per gestire dati in Ram per cui quando si vanno a modificare le cose va riscritto tutto il contorno.
Si potrebbe provare a usare un array temporaneo, popolandolo prima di passarlo alla libreria. Non so quanti array ha lui e non so se facendo così ha dei vantaggi oppure no ma sarebbe più semplice che andare a metter mani nella lib.

nid69ita


- copiare quell'array su un nuovo buffer non sapendo quanti elementi ha C30


Certo che sai quanti elementi ci sono anche senza contarli:
Code: [Select]
byte xdim=sizeof(C30)/sizeof(C30[0]);
Dimensione in byte di tutto l'array diviso la dimensione in byte della prima cella
my name is IGOR, not AIGOR

roxdragon

#19
Mar 27, 2014, 03:18 pm Last Edit: Mar 27, 2014, 03:20 pm by roxdragon Reason: 1
Grazie ragazzi...
@leo72 ho 61 array  circa

@nid69ita

Code: [Select]
unsigned int temp[256];
void loop(){

byte xdim=sizeof(C30)/sizeof(C30[0]); //cosi so quanto è grande l'array
for(int i=0; i< xdim; i++)

temp [i]=pgm_read_word(&(C30);
}

mi correggi se sbaglio? come dice leo72 vorrei popolare un array momentaneamente per poi spedire questo array temp alla lib
come va modificato questo codice?

nid69ita

#20
Mar 27, 2014, 03:50 pm Last Edit: Mar 27, 2014, 03:59 pm by nid69ita Reason: 1

Code: [Select]
unsigned int temp[256];
void loop(){
byte xdim=sizeof(C30)/sizeof(C30[0]); //cosi so quanto è grande l'array
for(int i=0; i< xdim; i++)
 temp[i] = pgm_read_word(&C30);
}

mi correggi se sbaglio? come dice leo72 vorrei popolare un array momentaneamente per poi spedire questo array temp alla lib
come va modificato questo codice?


Non conosco la pgm_read_word
ma di sicuro devi passargli un singolo elemento del array e non tutto l'array (usando l'indice i anche per lui)
quindi qualcosa del genere:
Code: [Select]
pgm_read_word(&C30[i]);
Non sono sicuro tu debba mettere quella &              @Leo72 penso possa consigliarti meglio
my name is IGOR, not AIGOR

roxdragon

Mmh...questo è lo sketch che sto usando...
Allora confido in leo72!

Code: [Select]

static const uint16_t  C30[] PROGMEM ={4492,4432,596,1600,592,508,592,1608,588,1608,596,504,588,508,596,1604,592,504,596,504,596,1604,592,504,600,500,592,1604,600,1600,596,504,596,1600,596,504,596,504,588,1608,596,1600,596,1604,588,1608,600,1600,592,1604,592,1604,600,1600,592,508,596,500,592,508,596,504,596,504,588,508,596,1604,588,508,596,1604,588,1608,600,1600,592,1604,592,508,592,508,596,500,592,1608,596,500,592,508,596,504,596,504,588,1608,596,1604,592,5268,4520,4424,592,1608,596,504,588,1608,596,1604,592,504,600,500,592,1608,596,500,592,508,592,1604,592,508,596,504,596,1600,596,1604,588,508,596,1604,592,504,596,504,600,1600,592,1604,592,1604,600,1600,596,1600,592,1608,588,1608,596,1604,592,504,596,504,600,500,592,508,592,504,600,500,592,1604,592,508,592,1604,592,1608,596,1600,592,1608,588,508,596,504,596,504,588,1608,596,504,600,500,592,504,596,504,588,1612,592,1604,592,1000}; //AnalysIR Batch Export - RAW
int i;
unsigned int buffer[256];

void setup(){
 Serial.begin(9600);
}

void loop(){
 
 byte lenght = sizeof(C30)/sizeof(C30)[0];

 for (byte i=0; i < lenght; i++) {
   buffer[i] = pgm_read_word(&(C30[i]));
 }
 Serial.println(lenght);  

}

Come lunghezza mi stampa: 200

nid69ita


 byte lenght = sizeof(C30)/sizeof(C30)[0];

Errato
Code: [Select]
 byte lenght = sizeof(C30)/sizeof(C30[0]);
Eventualmente visto che sai che C30 sono unsigned int anche così va bene:
Code: [Select]
 byte lenght = sizeof(C30)/sizeof(int);
my name is IGOR, not AIGOR

nid69ita

#23
Mar 27, 2014, 04:07 pm Last Edit: Mar 27, 2014, 04:08 pm by nid69ita Reason: 1
Ricorda poi che nel tuo programmone dovrai fare la copia da array a temporaneo sempre prima di spedire e quando spedisci i parametri sono relativi all'array temporaneo:

Code: [Select]
if( readString.indexOf("C=30") > 0 )
 My_Sender.IRsendRaw::send(C30, sizeof(C30)/sizeof(int), khz);


Code: [Select]
if ( readString.indexOf("C=30") > 0 )
{ byte lenght = sizeof(C30)/sizeof(int);
 for (byte i=0; i < lenght; i++)
 { buffer[i] = pgm_read_word( &C30[i] );        // forse senza &
 }
 My_Sender.IRsendRaw::send(buffer, lenght, khz);
}
my name is IGOR, not AIGOR

leo72

#24
Mar 27, 2014, 04:11 pm Last Edit: Mar 27, 2014, 04:21 pm by leo72 Reason: 1
Sì, dovrebbe andare:
Code: [Select]
pgm_read_word(&C30[i]);

roxdragon

Ecco! funziona al momento... però avendo 60 array vorrei evitare di ricopiare il codice, quindi mi sono fatto una funzione chiamata ReadFlash()

Code: [Select]

unsigned int buffer[256];
unsigned int ReadFlash(string x){
 
 byte lenght = sizeof(x)/sizeof(int);
 for (byte i=0; i < lenght; i++){
   buffer[i] = pgm_read_word( &x[i] );        // forse senza &
 }
 return buffer;
}


Code: [Select]
void loop(){ .....
....
        // CONDIZIONATORE -- ARIA CALDA --
         if ( readString.indexOf("C=30") > 0 )
         buffer = ReadFlash("C=30");
            My_Sender.IRsendRaw::send(buffer, lenght, khz);
         }

errore del compilatore:
Code: [Select]
sketch_arduino_con_raw:10: error: 'string' was not declared in this scope
sketch_arduino_con_raw:62: error: redefinition of 'unsigned int ReadFlash'
sketch_arduino_con_raw:10: error: 'unsigned int ReadFlash' previously defined here
sketch_arduino_con_raw:62: error: 'string' was not declared in this scope


vorrei passare x alla funzione che in questo caso avrebbe "C=30"

leo72

L'oggetto stringa si indica con la S maiuscola, quindi String.
Ma perché fare queste cose??? Passagli il puntatore, no?
In un array il puntatore indica il primo elemento quindi poi sommando il n° di cella ottieni il suo indirizzo.

nid69ita

#27
Mar 27, 2014, 04:33 pm Last Edit: Mar 27, 2014, 04:40 pm by nid69ita Reason: 1

Ecco! funziona al momento... però avendo 60 array vorrei evitare di ricopiare il codice, quindi mi sono fatto una funzione chiamata ReadFlash()

Nella progettazione però parti prima dal capire come vorrai utilizzare la nuova funzione.
Code: [Select]
buffer = ReadFlash("C=30");non può funzionare, che legame c'e' tra la frase "C=30" e il vero array C30 ? Nessuna

Così è meglio, intendo passare alla funzione l'array (in realtà gli passerò un puntatore) e quanti elementi deve copiare.
Code: [Select]
ReadFlash(C30,sizeof(C30)/sizeof(int));

Perciò:
Code: [Select]

void ReadFlash(unsigned int p_buf[],int p_lun)    // p_ per me significa parametro
{ for(byte i=0; i<p_lun; i++)
 { buffer[i] = pgm_read_word( &p_buf[i] );
 }
}

Il primo parametro io ho messo unsigned int, non sono sicuro che qui ci debba essere il tipo di come hai dichiarato C30.
Anche qui credo che @Leo72 possa consigliarci meglio.
my name is IGOR, not AIGOR

roxdragon

Ok ok vediamo se riesco a spiegarmi.. allora
questo è il mio codice...

Code: [Select]
static const uint16_t  C30[] PROGMEM ={4492,4432,596,1600,592,508,592,1608,588,1608,596,504,588,508,596,1604,592,504,596,504,596,1604,592,504,600,500,592,1604,600,1600,596,504,596,1600,596,504,596,504,588,1608,596,1600,596,1604,588,1608,600,1600,592,1604,592,1604,600,1600,592,508,596,500,592,508,596,504,596,504,588,508,596,1604,588,508,596,1604,588,1608,600,1600,592,1604,592,508,592,508,596,500,592,1608,596,500,592,508,596,504,596,504,588,1608,596,1604,592,5268,4520,4424,592,1608,596,504,588,1608,596,1604,592,504,600,500,592,1608,596,500,592,508,592,1604,592,508,596,504,596,1600,596,1604,588,508,596,1604,592,504,596,504,600,1600,592,1604,592,1604,600,1600,596,1600,592,1608,588,1608,596,1604,592,504,596,504,600,500,592,508,592,504,600,500,592,1604,592,508,592,1604,592,1608,596,1600,592,1608,588,508,596,504,596,504,588,1608,596,504,600,500,592,504,596,504,588,1612,592,1604,592,1000}; //AnalysIR Batch Export - RAW


Code: [Select]
static const uint16_t *IR[] PROGMEM = {C30, C29, C28, C27, C26, C25, C24, C23, C22, C21, C20, C19, C18, C17, F30, F29, F28, F27, F26, F25, F24, F23, F22, F21, F20, F19, F18, F17, OFF};


Code: [Select]

void ReadFlash(uint16_t x[]){
  unsigned int buffer[256];

  byte lenght = sizeof(x)/sizeof(int);
  for (byte i=0; i < lenght; i++){
    buffer[i] = pgm_read_word( &x[i] );        // forse senza &
  }
   My_Sender.IRsendRaw::send(buffer, lenght, khz);
}


Code: [Select]
void loop(){.......
....     
          if ( readString.indexOf("C=30") > 0 )
          ReadFlash(IR[0]);


così facendo faccio tutto in una funzione... e ne richiamo solo una ed evito righe inutili...
però il compilatore mi da questo errore:

Code: [Select]
sketch_arduino_con_raw.ino: In function 'void loop()':
sketch_arduino_con_raw:125: error: invalid conversion from 'const uint16_t*' to 'uint16_t*'
sketch_arduino_con_raw:125: error: initializing argument 1 of 'void ReadFlash(uint16_t*)'


sarò fuso io, scusatemi!

nid69ita

#29
Mar 27, 2014, 04:43 pm Last Edit: Mar 27, 2014, 04:49 pm by nid69ita Reason: 1
Guarda, ci sei quasi. Non puoi passare alla funzione un singolo elemento, ma passi tutto il nome dell'array.
Ed un secondo parametro con il numero di elementi.
Code: [Select]
if ( readString.indexOf("C=30") > 0 )
         ReadFlash(IR, sizeof(IR)/sizeof(int) );



Code: [Select]
void ReadFlash(uint16_t x[], byte lenght)
{ unsigned int buffer[256];
 for (byte i=0; i < lenght; i++){
   buffer[i] = pgm_read_word( &x[i] );        
 }
 My_Sender.IRsendRaw::send(buffer, lenght, khz);
}


Non mi convince
1. quell'array grosso dentro la funzione (funziona ma mi sembra che possa rallentare il programma)
2. forse il compilatore ti darà ancora errore o warning sul fatto che passi un array "const uint16_t" rispetto a "uint16_t"
my name is IGOR, not AIGOR

Go Up