sistema per memorizzare un numero grande 0-99999

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

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

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

K = EEPROM.read(0);

K prende il valore di 159 :fearful:

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 :stuck_out_tongue_closed_eyes:

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.

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?

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

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

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)

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

secondo me qui qualcuno sotto sotto si aspetta la pappa fatta.. :grin:

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

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

leo72:
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));

invece ho provato a scrivere un numero grande (88888) con i modi scritti in questo tread ma non mi fa compilare :fearful:

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

vai qua Arduino - Home 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..

m_ri:
vai qua Arduino - Home 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 :stuck_out_tongue:

leo72:
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.

leo72:
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

Leggi il mio mega post, è tutto scritto lì.
Per scomporre un numero di 4 byte (32 bit) devi usare diversi AND a livello di bit.

  1. Prendi il numero e fai un AND con 255 (binario 0b11111111): ottieni i primo 8 bit a destra;
  2. sposti il numero di 8 bit a destra (operazione numero>>8) e poi fai un altro AND con 255: ottieni i secondi 8 bit ecc...
  3. ogni volta ottieni un byte (8 bit) e lo salvi in una cella

ho scritto questo breve codice
guardando i serial print quello che ricompone senza passare per la memoria (Z) da valore corretto
invece quello che prende i dati dalla memoria (P) da valore sbagliato
=(

#include <EEPROM.h>


long K = 444456699;

long A;
long B;
long C;
long D;

long Z;

long p;

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

A=   (K >> 24) & 0b11111111;
B=   (K >> 16) & 0b11111111;
B=   (K >> 8)  & 0b11111111;
D=    K        & 0b11111111;
    EEPROM.write(1, A);
    EEPROM.write(2, B);
    EEPROM.write(3, C);
    EEPROM.write(4, D);

}

void loop(){


Z = (A << 24) | (B  <<16) | ( B <<8) | D;

p = (EEPROM.read(1)<<24) | (EEPROM.read(2)<<16) | (EEPROM.read(3)<<8) | EEPROM.read(4);

Serial.println (Z);
Serial.println (p);
}

Intanto fai assegnazione a A-B-B-D e non ad A-B-C-D :wink:
Perché poi dichiari A, B, C e D di tipo long? Esse devono contenere 8 bit, quindi devono essere di tipo byte.

:fearful:

azz che svista la doppia B domani "aggiusto" e riprovo

Ho riguardato il tuo codice, non ti funzionava anche per via del casting dei tipi. Questo funziona.

#include <EEPROM.h>


unsigned long K = 0xA0B0C0D0;

byte A;
byte B;
byte C;
byte D;

unsigned long Z;

unsigned long p;

void setup(){
    delay(2000);
    Serial.begin(9600); 

    A = (K >> 24) & 0b11111111;
    B = (K >> 16) & 0b11111111;
    C = (K >> 8)  & 0b11111111;
    D = K & 0b11111111;
    Serial.println(A, HEX);
    Serial.println(B, HEX);
    Serial.println(C, HEX);
    Serial.println(D, HEX);
    EEPROM.write(1, A);
    EEPROM.write(2, B);
    EEPROM.write(3, C);
    EEPROM.write(4, D);
    Z = ((unsigned long)(A) << 24) | ((unsigned long)(B) << 16) | ((unsigned long)(C) << 8) | (unsigned long)(D);
    p = ((unsigned long)(EEPROM.read(1)) << 24) | ((unsigned long)(EEPROM.read(2)) << 16) | ((unsigned long)(EEPROM.read(3)) << 8) | (unsigned long)(EEPROM.read(4));

    Serial.println(Z, HEX);
    Serial.println(p, HEX);
}

void loop(){

}

Te l'ho messo in esadecimale così vedi come vengono scomposte le variabili.