eprom esterna 24LCxxx

Salve
riallacciandomi al discorso di scrittura dati che ho fatto in altro thread, sono giunto alla conclusione (da scolaretto) che non si può usare la spiffs per fare un write - diciamo - pesante, in quanto i cicli e/w sono circa 10.000
L'utilizzo di quel tipo di memoria fisica impone una ponderata attenzione e se ne deve fare quasi abuso, o ci si serve di una SD o di una 24LCxxx.
Per i miei scopi debbo evitare una SD, anche perchè da prove fatte ho notato che spesso si "incanta" e occorre fisicamente toglierla dal contenitore per poter far ripartire il tutto.
Forse sbaglio libreria o esempi ma fatto sta che mi è successo su più progetti.

Vengo al dunque : credo che userò una 24LC ma ....
ma ... sbaglio o occorre scrivere bit per bit ?
esiste una libreria o un qualcosa che possa aiutarmi a scrivere un file come succede per spiffs ?
non mi sembra di aver trovato nulla in proposito : ho cercato male o effettivamente non c'è?

grazie per la pazienza !

NON è par fare pubblicità (l'ho detto tante volte che, fortunatamente, non occorre), ma sull'ultimo numero di "Elettronica In", 252, marzo 2021, c'è un mio articolo con una soluzione molto semplice e veloce che usa una memoria NVSRAM dal costo irrisorio ed una piccola batteria a bottone. Prova a guardare perché ho sviluppato anche la libreria per l'uso :wink:

Guglielmo

ho acquistato la rivista ed ho visto il tuo lavoro (sinceramente non ho approfondito per motivi lavorativi, ma lo farò).
in ogni caso è eccellente, come tutti !
ti chiedo a questo punto alcune cose :
1 - esiste qualcosa del genere che lavori in I2C e non in SPI ?
2 - la libreria comprende un metodo per scrivere files "direttamente" ?
3 - è compatibile esp32 ? sul mio progetto uso miso mosi sui pin 31 37 (cs non è un problema).

p.s. c'è un errore nello schema di pagina 48 : due miso sia sul pin 1 che sul 4 :slight_smile:

1. so che esistono chip simili in I2C ... è un bus più molto più lento (un fattore 10 ed oltre), però, come detto, si, ci sono NVSRAM I2C.

2. No, la libreria contiene metodi simili a quelli della EEPROM, quindi lettura e scrittura dei vari tipi di dati classici del 'C, inclusi gli array e le strutture.

La gestione "files" NON la trovi in NESSUNA libreria che gestisce questo tipo di memorie esterne (EEPROM, NVSRAM, E, FRAM, EERAM, ...) ... te la devi scrivere (... anche io sto pensando ad un qualche cosa, ma, appunto, per ora ci sto solo pensando :smiley:)

Guglielmo

immaginavo per quanto concerne le librerie. quindi mi debbo armare di zappa informatica e scrivermi tutto bit per bit

dimmi se sbaglio su questa mia strategia di scrittura :
ho 10 gruppi di 500 bytes da scrivere, quindi 5000 bytes, quindi 40kbit.
mentalmente preparo 4k di spazio per ogni 500 bytes
quindi
da 1 a 4000 ----> primo gruppo
da 4001 a 8000 --> secondo gruppo
....
36000 - 40000 ---> decimo gruppo
quando debbo leggere/scrivere le info relative al 7° gruppo, vado a smanettare solo nei bytes compresi tra 28000 e 32000.
giusto?

... ma scusa, non riesci a disegnare il "RECORD" del tuo "FILE" come una struttura di lunghezza fissa (come si fa in tutte le gestioni ad accesso random o index), memorizzi una serie di "struct" ad indirizzi banalmente calcolabili (numero record * dimensione struct) e poi fai delle velocissime ricerche (sei su memorie RAM, no SD, quindi infinitamnete più veloci) in modo estremanete banale.

Guglielmo

per cortesia, un link di esempio banale farebbe comodo alla mia attuale congiuntivite ma soprattutto alla mia scarsa conoscenza della materia in questo tipo di applicazioni (eprom et similia), che per me sono nuove :frowning:

... emmm ... non ho un link, sono concetti base per chi opera con i files ... concetto di record, accessi sequenziali, accessi random, accessi index/sequential, ecc. ecc. :confused:

Comunque, in pratica, io userei una "struct" del 'C' per creare il tuo "record" di lunghezza fissa (così, se sai che occupa, ad esempio, 24 bytes, il primo partirà da 0, il secondo da 24, il terzo da 48 e così via, ovvero numero del record x lunghezza del record) che memorizzerei nella memoria e che poi utilizzerei, anche avanzando in sequenza (tanto sei su una memoria veloce), per ritrovare l'informazione cercata.

Ovviamente ci sono anche tecniche molto più veloci per la ricerca, ma ... magari un passo per volta :wink:

Guglielmo

bene ... ci provo. vediamo che schifezza che esce :blush:

fotosettore:
mentalmente preparo 4k di spazio per ogni 500 bytes

No, 500 byte occupano 500 byte, il primo blocco va dall'indirizzo 0 al 499 e così via. Non ho capito perché vorresti ottuplicare lo spazio usando un intero byte di EEPROM per ogni bit dei 500 byte di partenza

Ho teoricamente moltiplicato per 8 perchè non essendoci librerie, credevo di dover scrivere bit per bit.
Quando si parla di 24LC si parla in Kbit. Con la ram del pc si parla di Kbytes.
Alleluia quando ho capito che una 24LC512 mi tiene dentro 64Kbytes.
Mai lavorato finora con queste cose. Sempre smanettato su arduino senza dare troppa importanza al discorso memoria. Mi sto "erudendo". Mi si sta aprendo un mondo.
Capisci il mio stato di insufficienza mentale sull'argomento ? :o

frase della sera : "se fosse facile, lo farebbero tutti...."

.... tranquillo, per quelle memorie viene data la capacità in Kbit, ma l'organizzazione è sempre in byte per cui tu non ti devi preoccupare di gestire i bit :smiley:

Come hai visto nell'articolo, la 23LCV512 è 512 Kbit, ma la si vede come una 64 Kbytes e la sorella maggiore 23LCV1024 da 1Mbit, la si vede come 128 Kbytes :wink:

Guglielmo

gpb01:
Comunque, in pratica, io userei una "struct" del 'C' per creare .....

bene ...
caro Guglielmo, prendendo spunto dal tuo consiglio sto cercando di capire la struct, che da quello che vedo è molto simile all'array del visual studio.
Sulla base dell'esempio del tuo link, ho cercato di creare un array (perchè questo mi serve) ma la cosa mi ha bloccato perchè ho un risultato strano : il primo array contiene tutti gli altri, e gli altri a scalare.
Dove sbaglio ?

struct Fattoria
{
   char  par_1[6];
   char  par_2[6];
   char  par_3[6];
   char  par_4[6];
   char  par_5[6];
   char  par_6[6];
   char  par_7[6];
   char  par_8[6];
   char  par_9[6];      
};

void STRUTTURA()
{

     struct Fattoria Soggetto[70];

     strcpy( Soggetto[1].par_1, "pippo ");
     strcpy( Soggetto[1].par_2, "pluto "); 
     strcpy( Soggetto[1].par_3, "papero");
     strcpy( Soggetto[1].par_4, "gasto ");
     strcpy( Soggetto[1].par_5, "cip   "); 
     strcpy( Soggetto[1].par_6, "ciop  ");
     strcpy( Soggetto[1].par_7, "qui   ");
     strcpy( Soggetto[1].par_8, "quo   "); 
     strcpy( Soggetto[1].par_9, "qua   ");

     printf( "Soggetto par_1 : %s\n", Soggetto[1].par_1);
     printf( "Soggetto par_2 : %s\n", Soggetto[1].par_2);
     printf( "Soggetto par_3 : %s\n", Soggetto[1].par_3);
     printf( "Soggetto par_4 : %s\n", Soggetto[1].par_4);
     printf( "Soggetto par_5 : %s\n", Soggetto[1].par_5);
     printf( "Soggetto par_6 : %s\n", Soggetto[1].par_6);
     printf( "Soggetto par_7 : %s\n", Soggetto[1].par_7);
     printf( "Soggetto par_8 : %s\n", Soggetto[1].par_8);
     printf( "Soggetto par_9 : %s\n", Soggetto[1].par_9);   

}

che mi da come risultato :

Soggetto par_1 : pippo pluto paperogasto cip   ciop  qui   quo   qua   
Soggetto par_2 : pluto paperogasto cip   ciop  qui   quo   qua   
Soggetto par_3 : paperogasto cip   ciop  qui   quo   qua   
Soggetto par_4 : gasto cip   ciop  qui   quo   qua   
Soggetto par_5 : cip   ciop  qui   quo   qua   
Soggetto par_6 : ciop  qui   quo   qua   
Soggetto par_7 : qui   quo   qua   
Soggetto par_8 : quo   qua   
Soggetto par_9 : qua

:o :o :o :o

Naturalmente poi andrei a riempire gli altri array (ai quali, in questo esempio, ho dato un numero massimo di 70), ma vorrei risolvere prima questo problema ...

Se i tuoi parametri sono stringhe 6 caratteri l'array che li contiene (par_1,par_2,etc) deve essere lungo 7, perchè deve contenere il carattere '\0' di terminazione della stringa. Il risultato che ottieni è coerente, l'unico terminatore che trova è posto dopo l'ultima stringa. Prova a cambiare la dimensione e vedrai che funziona.
Inoltre impare a definire delle costanti, che in questi casi tornano utili, es. :

#define PARM_LEN 7
struct Fattoria
{
   char  par_1[PAR_LEN];
   char  par_2[PAR_LEN];
   [...]
}

così la modifica (anche in futuro) la fai una volta sola.

Ciao, Ale.

bene ...
ora funziona, grazie ilguargua
e adesso un problemone che credo non sia risolvibile
ho messo 120 al posto di 70 e ho un continuo reset con questo messaggio.
mi sa tanto che più di un tot non possono essere gestiti

abort() was called at PC 0x400870fd on core 1

Backtrace: 0x4008dde0:0x3ffafc80 0x4008e011:0x3ffafca0 0x400870fd:0x3ffafcc0 0x40087128:0x3ffafce0 0x40087279:0x3ffafd10 0x400f0805:0x3ffafd30 0x400f0daf:0x3ffafd50 0x4000bd83:0x3ffafd70 0x4000117d:0x3ffafd90 0x400592fe:0x3ffafdb0 0x4005937a:0x3ffafdd0 0x40058bbf:0x3ffafdf0 0x400f964d:0x3ffafe20 0x400fee4a:0x3ffafe50 0x400f5a65:0x3ffb0160 0x400d1f66:0x3ffb01b0 0x400d42c9:0x3ffb1f70 0x400e2a63:0x3ffb1fb0 0x4008a51d:0x3ffb1fd0

Rebooting...

Metti il programma completo (non vedo cosa fa il setup() ne il loop()) perché così non si capisce ...

Guglielmo

fotosettore:

abort() was called at PC 0x400870fd on core 1

Stai facendo qualcosa di "illegale" e viene richiamato l'abort() sul core dove gira il loop()
Il tool di analisi dell'eccezione potrebbe aiutarti ad individuare la riga incriminata

fa solo questo :frowning:

struct Fattoria
{
   char  par_1[7];
   char  par_2[7];
   char  par_3[7];
   char  par_4[7];
   char  par_5[7];
   char  par_6[7];
   char  par_7[7];
   char  par_8[7];
   char  par_9[7];      
};


void setup()
{
   STRUTTURA();
}



void loop() {
  // put your main code here, to run repeatedly:

}

//*********************************************
void STRUTTURA()
{
     struct Fattoria Soggetto[150];

     strcpy( Soggetto[1].par_1, "pippo ");
     strcpy( Soggetto[1].par_2, "pluto "); 
     strcpy( Soggetto[1].par_3, "papero");
     strcpy( Soggetto[1].par_4, "gasto ");
     strcpy( Soggetto[1].par_5, "cip   "); 
     strcpy( Soggetto[1].par_6, "ciop  ");
     strcpy( Soggetto[1].par_7, "qui   ");
     strcpy( Soggetto[1].par_8, "quo   "); 
     strcpy( Soggetto[1].par_9, "qua   ");

     printf( "Soggetto par_1 : %s\n", Soggetto[1].par_1);
     printf( "Soggetto par_2 : %s\n", Soggetto[1].par_2);
     printf( "Soggetto par_3 : %s\n", Soggetto[1].par_3);
     printf( "Soggetto par_4 : %s\n", Soggetto[1].par_4);
     printf( "Soggetto par_5 : %s\n", Soggetto[1].par_5);
     printf( "Soggetto par_6 : %s\n", Soggetto[1].par_6);
     printf( "Soggetto par_7 : %s\n", Soggetto[1].par_7);
     printf( "Soggetto par_8 : %s\n", Soggetto[1].par_8);
     printf( "Soggetto par_9 : %s\n", Soggetto[1].par_9);   

}

e rimetto anche l'errore

Soggetto par_1 : pippo 
Soggetto par_2 : pluto 
Soggetto par_3 : papero
Soggetto par_4 : gasto 
Soggetto par_5 : cip   
Soggetto p***ERROR*** A stack overflow in task loopTask has been detected.
abort() was called at PC 0x4008b1d8 on core 1

Backtrace: 0x4008af94:0x3ffaf490 0x4008b1c1:0x3ffaf4b0 0x4008b1d8:0x3ffaf4d0 0x400885b4:0x3ffaf4f0 0x40089f74:0x3ffaf510 0x40089f2a:0xfefefefe

Rebooting...

Il problema è che con 150 elementi dell'array superi la dimensione massima dello stack associata al task setup() / loop() che non è molto elevato (4/5 Kbyte se non ricordo male).

Se l'array lo sposti a livello globale, funziona come ti aspetti (anche con valori molto maggiori).

typedef struct 
{
   char  par_1[7];
   char  par_2[7];
   char  par_3[7];
   char  par_4[7];
   char  par_5[7];
   char  par_6[7];
   char  par_7[7];
   char  par_8[7];
   char  par_9[7];      
} Fattoria ;  // Io preferisco questa forma :)

Fattoria Soggetto[1000];

void setup()
{
   STRUTTURA();
}

void loop() {
  // put your main code here, to run repeatedly:
}

//*********************************************
void STRUTTURA()
{
     strcpy( Soggetto[1].par_1, "pippo ");
     strcpy( Soggetto[1].par_2, "pluto ");
     strcpy( Soggetto[1].par_3, "papero");
     strcpy( Soggetto[1].par_4, "gasto ");
     strcpy( Soggetto[1].par_5, "cip   ");
     strcpy( Soggetto[1].par_6, "ciop  ");
     strcpy( Soggetto[1].par_7, "qui   ");
     strcpy( Soggetto[1].par_8, "quo   ");
     strcpy( Soggetto[1].par_9, "qua   ");

     printf( "Soggetto par_1 : %s\n", Soggetto[1].par_1);
     printf( "Soggetto par_2 : %s\n", Soggetto[1].par_2);
     printf( "Soggetto par_3 : %s\n", Soggetto[1].par_3);
     printf( "Soggetto par_4 : %s\n", Soggetto[1].par_4);
     printf( "Soggetto par_5 : %s\n", Soggetto[1].par_5);
     printf( "Soggetto par_6 : %s\n", Soggetto[1].par_6);
     printf( "Soggetto par_7 : %s\n", Soggetto[1].par_7);
     printf( "Soggetto par_8 : %s\n", Soggetto[1].par_8);
     printf( "Soggetto par_9 : %s\n", Soggetto[1].par_9);  
}

Si confermo, il main task (ovvero quello dove girano setup() e loop()) di default ha solo 4 Kbyte di stack

#define CONFIG_MAIN_TASK_STACK_SIZE 4096