Go Down

Topic: sistema per memorizzare un numero grande 0-99999 (Read 3531 times) previous topic - next topic

gingardu

volevo chiedere se c'è un sistema piu semplice di quello che mi è venuto in mente a me per memorizzare nella eeprom un numero da 0  a 99999

per leggere la eeprom  ho provato questo e funziona

  EEPROM.write(0, 0);
    EEPROM.write(1, 1);
    EEPROM.write(2, 2);
    EEPROM.write(3, 3);
    EEPROM.write(4, 4);
    EEPROM.write(5, 5);

   K = (EEPROM.read(1)*10000) + (EEPROM.read(2)*1000)+ (EEPROM.read(3)*100)+ (EEPROM.read(4)*10)+ (EEPROM.read(5)*1);
    if (EEPROM.read(0)==0) K = K-(K*2);


ma per scrivere sulla eeprom  il valore di K  (es: 98765)
come si fa?

a me è venuto in mente es
velificare il numero con gli if

if (K>90000 && K<99999)  EEPROM.write(1, 1);

.....ò........
if (K>90000 && K<99999)  K= K-90000

........... ect
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

astrobeed

Questa è una cosa che abbiamo spiegato un milione di volte   :)
Il numero lo memorizzi sulla EEPROM nel suo formato nativo, ovvero int (2 byte) se minore di 65536, oppure long int (4 byte) se maggiore di 65536 e se si tratta di valori esclusivamente positivi, se sono anche negativi non cambia nulla salvo i limiti rappresentabili.
Per scomporre la variabile in byte in modo da poterli memorizzare sulla EEPROM, o per ricostruire la variabile stessa, puoi usare i puntatori oppure una unione, cerca sul forum che trovi tutti i dettagli.



gingardu

mah... c'è qualcosa che non va  =(  
se metto
   EEPROM.write(0, 99999);

   
   K = EEPROM.read(0);

K prende il valore di 159   :smiley-eek-blue:

ho provato a fare una ricerca con le parole  "scomporre variabile in byte"

da 2 risultati e piu o meno  rimandano a leggere il Reference che chi la scritto da per scontato che chi legge e gia un professore della materia   :smiley-yell:
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

leo72

I metodi .write e .read della libreria EEPROM accettano solo byte quindi non possono trattare numeri di tipo int o long.
Per scomporre un int in 2 byte, usa le funzioni lowByte e highByte di Arduino:
http://arduino.cc/en/Reference/LowByte
http://arduino.cc/en/Reference/HighByte

quindi
int valore;
EEPROM.write(cella, highByte(valore));
EEPROM.write(cella+1, lowByte(valore));

Per ricomporlo puoi usare una semplice moltiplicazione:
valore = (EEPROM.read(cella)*256)+EEPROM.read(cella+1);

Tralascio le operazioni sui bit che potrebbero farti risparmiare qualche byte di Flash nella scomposizione e ricomposizione del numero.

gingardu


servirebbe  una mezza spiegazione  (anche a grandi linee)

  questa funzione cosa fa  a un numero  ( es 98765 ) come lo separa e come e dove lo memorizza?

e  la conversione inversa e gia automatica

all'atto pratico   se si vogliono memorizzare sei numeri  da 1 a 5 cifre 

questo sistema è ancora usabile?

Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

m_ri

#5
Sep 12, 2012, 10:36 am Last Edit: Sep 12, 2012, 10:48 am by m_ri Reason: 1
per avere numeri da 0 a 99999 devi usare i long int,i quali occupano 4 byte..dato che la eeprom memorizza/òegge un byte per volta,devi scomporre il long int(4 byte) in 4 gruppi da 1 byte ognuno..come ti è già stao detto,puoi usare le union,i puntatori,o lowByte e highByte..

per esempio puoi usare

Code: [Select]
union numeroEEPROM{
  long int num;
  byte bytes[4];
}


numeroEEPROM numero;
numero.num=98000;
for(int i=0;i<4;i++)EEPROM.write(i,numero.bytes[i]);


però dovresti cercare le basi di programmazione anche un po' su internet..

leo72

Per capire come funziona devi partire dal tipo base "int" e da come è memorizzato. Facciamo un esempio senza union, per capire come lavora il compilatore.
Il tipo "int" è un tipo dati a 16 bit, occupa quindi 2 byte in memoria. Quindi, per memorizzarlo, il compilatore usa 2 celle di SRAM per il suo valore.
Sapendo questo, se vuoi memorizzare una variabile "int" in EEPROM non devi fare altro che dividerla nei suoi 2 byte. Le funzioni che ti ho suggerito fanno questo (le hai lette le pagine linkate?).
Il byte alto è il byte più a sinistra, il byte basso quello più a destra.

Per ricomporre il numero non fai altro che leggere i 2 byte singolarmente, poi inserirli in una variabile di tipo "int", ossia mettere i valori in 2 byte della RAM. La moltiplicazione per 256 equivale ad uno spostamento di 8 bit a sinistra.
Ti illustro.
Mettiamo che devi salvare il valore 0b1100001100111100

lowByte(0b1100001100111100) restituisce 0b00111100, cioè gli 8 bit più a destra mentre highByte(0b1100001100111100) restituisce 0b11000011, cioè gli 8 bit più a sinistra. Così saranno memorizzati.

Per ricomporre il numero leggi prima il byte alto e lo inserisci nella variabile di tipo "int", che conterrà dopo questa operazione:
0b0000000011000011

Adesso gli 8 bit a destra li devi spostare di 8 bit a sinistra, per far posto al resto dei bit.
Puoi ottenere la cosa o con uno spostamento di bit (<<8) oppure anche con una moltiplicazione per 256 (la strada che ti ho suggerito, che è più facile da capire. Questo perché 256=2^8, quindi moltiplicando un numero per 256 lo sposti di 8 bit a sinistra.
Quindi 0b0000000011000011 * 256 = 0b1100001100000000
Ora sommando il byte basso, 0b00111100, riotterrai il valore iniziale
0b1100001100000000 + 0b0000000000111100 = 0b1100001100111100

All'atto pratico, un numero da 1 65535 ti occupa 2 byte. Se i numeri sono superiori a 65535, devi usare un dato di tipo "long", che occupa 4 byte. Le operazioni da eseguire sono più complesse perché questa volta devi usare le operazioni sui bit, quali and, or e spostamenti.
Ad esempio, prendiamo il valore "long" 9000, che è in binario
0b00000000000000010101111110000

Per ottenere il 1° byte a sinistra, devi spostare a destra di 24 posizioni il valore così da spostare i primi 8 bit nelle posizioni meno significative e poi devi fare un AND con una maschera con 8 bit ad 1
0b00000000000000010101111110000 >> 24 = 0b00000000000000000000000000000000
Poi 0b00000000000000000000000000000000 AND 0b11111111 = 0b00000000

Per il secondo byte, fai lo stesso spostando però di 16 posizioni
0b00000000000000010101111110000 >> 16 = 0b00000000000000000000000000000001
Poi 0b00000000000000000000000000000001 AND 0b11111111 = 0b00000001

Ecc...

Per ricomporre devi fare semplicemente una somma con spostamento a sinistra ed OR binario per sommare i vari byte in un unico "long"
long variabile = (EEPROM.read(primacella)<<24) | (EEPROM.read(secondacella)<<16) | (EEPROM.read(terzacella)<<8) | EEPROM.read(quartacella)

gingardu

ok   cosi si inizia a capire meglio  per divisione in 2 si intende proprio una separazione al centro  della cifra ,

i link li ho visti,   ma  (secondo me) chi li capisce è gia un esperto della materia (e chi e un esperto della materia non ha bisogno di quel tipo di "spiegazioni")

se ci fossero anche anche delle spiegazioni pratiche  come hai fatto tu qui  aiuterebbero  molto,

tanks
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

m_ri

secondo me qui qualcuno sotto sotto si aspetta la pappa fatta.. :smiley-mr-green:

leo72


ok   cosi si inizia a capire meglio  per divisione in 2 si intende proprio una separazione al centro  della cifra ,

i link li ho visti,   ma  (secondo me) chi li capisce è gia un esperto della materia (e chi e un esperto della materia non ha bisogno di quel tipo di "spiegazioni")

se ci fossero anche anche delle spiegazioni pratiche  come hai fatto tu qui  aiuterebbero  molto,

tanks

Credo di averti spiegato tutto, e nei link ci sono alla fine riassunte le info che ti ho dato nel mio ultimo post.

gingardu


Per capire come funziona devi partire dal tipo base "int" e da come è memorizzato. Facciamo un esempio


ALLORA .. fatto un  po di prove questo funziona con numeri fino a 32000 circa

EEPROM.write(cella, highByte(valore));
EEPROM.write(cella+1, lowByte(valore));

funziona anche mettendo 2 indirizzi di memoria distanti o mettendo il numero direttamente tra parentesi al posto di valore,

per recuperarlo funzionano entrambi questi questi sistemi


K = (EEPROM.read(777)*256)+EEPROM.read(1004);   
A = (EEPROM.read(777)<<8) | (EEPROM.read(1004));

8) 

invece ho provato a scrivere un numero grande (88888)  con  i modi scritti in questo  tread ma non mi fa compilare  :smiley-eek-blue:
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

leo72

Senza codice e senza l'errore non so cosa stai facendo.
Riassumendo....
Il tipo int è un tipo che memorizza valori con segno, quindi da -32768 a +32767.
Se devi usare un valore da 0 a 65535 devi usare l'unsigned int.
Per valori superiori, i 16 bit non bastano più e devi usare i 32 bit. Con la differenza sempre fra signed long e unsigned long.
La divisione dei long te l'ho spiegata, devi manipolare 4 byte invece di 2. Non puoi usare lowByte e highByte perché lavorano al max su variabile di 2 byte (quindi int).

m_ri

vai qua http://arduino.cc/en/Reference/HomePage e guarda ogni tipoù(int,long,unsigned int) quale range di numeri accetta...
suggerimento: se uso 2 byte,potrò avere 2^(16=2*8)=65536 valori diversi..che possono essere tutti >=0,o un po' positivi,un po' negativi..

leo72


vai qua http://arduino.cc/en/Reference/HomePage e guarda ogni tipoù(int,long,unsigned int) quale range di numeri accetta...
suggerimento: se uso 2 byte,potrò avere 2^(16=2*8)=65536 valori diversi..che possono essere tutti >=0,o un po' positivi,un po' negativi..

No, così lo confondi. Non è corretto  :P


Il tipo int è un tipo che memorizza valori con segno, quindi da -32768 a +32767.
Se devi usare un valore da 0 a 65535 devi usare l'unsigned int.

gingardu



Per valori superiori, i 16 bit non bastano più e devi usare i 32 bit. Con la differenza sempre fra signed long e unsigned long.
La divisione dei long te l'ho spiegata, devi manipolare 4 byte invece di 2. Non puoi usare lowByte e highByte perché lavorano al max su variabile di 2 byte (quindi int).

per il tipo dei numeri int e tutto ok  so che hanno dei limiti  per il resto hai spiegato molto bene come funziona il tutto ecct

l'unica cosa che non riesco a fare è scrivere in memoria su 4 celle un numero grande,
non so se devo includere/escudere qualche libreria  particolare o se sto sbagliando qualcosa

per leggere/ricomporlo non ci dovrebbero essere problemi
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

Go Up