Pages: [1] 2   Go Down
Author Topic: sistema per memorizzare un numero grande 0-99999  (Read 2783 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged


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

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 129
Posts: 9492
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Questa è una cosa che abbiamo spiegato un milione di volte   smiley
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.


Logged

Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mah... c'è qualcosa che non va  smiley-cry  
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
Logged


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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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?

Logged


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

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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..
« Last Edit: September 12, 2012, 03:48:14 am by m_ri » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 (<<smiley-cool 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)<<smiley-cool | EEPROM.read(quartacella)
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged


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

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)<<smiley-cool | (EEPROM.read(1004));

 smiley-cool 

invece ho provato a scrivere un numero grande (88888)  con  i modi scritti in questo  tread ma non mi fa compilare  smiley-eek-blue
Logged


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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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).
Logged


Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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*smiley-cool=65536 valori diversi..che possono essere tutti >=0,o un po' positivi,un po' negativi..
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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*smiley-cool=65536 valori diversi..che possono essere tutti >=0,o un po' positivi,un po' negativi..
No, così lo confondi. Non è corretto  smiley-razz

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.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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
Logged


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

Pages: [1] 2   Go Up
Jump to: