Go Down

Topic: decodificare complemento a due (Read 1 time) previous topic - next topic

gingardu

volevo chiedere se c'è qualche comando specifico   in arduino per per trasformare in binario normale un numero  che
in origine   e a complemento a 2
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

leo72

Prendi il binario del numero in complemento a 2, lo inverti (cioè un bit ad 1 diventa 0 e viceversa) e poi ci sommi 1.

astrobeed


volevo chiedere se c'è qualche comando specifico   in arduino per per trasformare in binario normale un numero  che
in origine   e a complemento a 2


Un valore in complemento a due è semplicemente un numero con valore negativo, è già in binario, se hai bisogno di convertirlo come valore positivo basta che lo moltiplichi per -1.

gingardu


Prendi il binario del numero in complemento a 2, lo inverti (cioè un bit ad 1 diventa 0 e viceversa) e poi ci sommi 1.


ma non c'è un comado specifico bello e pronto?
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

gingardu



volevo chiedere se c'è qualche comando specifico   in arduino per per trasformare in binario normale un numero  che
in origine   e a complemento a 2


Un valore in complemento a due è semplicemente un numero con valore negativo, è già in binario, se hai bisogno di convertirlo come valore positivo basta che lo moltiplichi per -1.


ma se ho una serie di bit tipo   100110101000001010100011  se li trasformo viene fuori una schifezza  perche avendo il primo bit di sinistra a 1  aggiunge oltre due milioni alla cfra  quando il primo bit sta a significare solo il negativo,

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

leo72


ma non c'è un comado specifico bello e pronto?

Da dove ottieni questo numero in complemento a 2?


ma se ho una serie di bit tipo   100110101000001010100011  se li trasformo viene fuori una schifezza  perche avendo il primo bit di sinistra a 1  aggiunge oltre due milioni alla cfra  quando il primo bit sta a significare solo il negativo,

che si fa?

Che formato ha il numero? Lo hai come stringa, come array di char, come cosa? Per capire.

PaoloP

#6
Oct 26, 2012, 11:24 pm Last Edit: Oct 26, 2012, 11:26 pm by PaoloP Reason: 1

ma se ho una serie di bit tipo   100110101000001010100011  se li trasformo viene fuori una schifezza  perche avendo il primo bit di sinistra a 1  aggiunge oltre due milioni alla cfra  quando il primo bit sta a significare solo il negativo,

che si fa?


Leo ha già risposto.

Prendi il binario del numero in complemento a 2, lo inverti (cioè un bit ad 1 diventa 0 e viceversa) e poi ci sommi 1.


Prendi il tuo numero : 100110101000001010100011
lo inverti :                011001010111110101011100
e gli sommi 1:           011001010111110101011101

astrobeed


ma se ho una serie di bit tipo   100110101000001010100011  se li trasformo viene fuori una schifezza  perche avendo il primo bit di sinistra a 1  aggiunge oltre due milioni alla cfra  quando il primo bit sta a significare solo il negativo,


Mi sa tanto che non ti è molto chiara la rappresentazione dei valori negativi in binario, p.e. -1 diventa 255 con una codifica a 8 b it, 0b11111111, se lo guardi esclusivamente come valore a otto bit positivi, però se fai la conversione nel giusto modo diventa 1, il modo più rapido è moltiplicare il valore per -1, provare per credere.
Attenzione che se stai interpretando il valore binario che hai scritto come composto da un valore assoluto e l'ultimo bit come quello di segno stai sbagliando tutto.

leo72

Ma la domanda difatti è: da dove ha un numero in complemento a due?
Quella è una rappresentazione in memoria, lui non deve preoccuparsene di come i numeri sono memorizzati, ci pensa il compilatore a trattare i signed e gli unsigned nei modi appropriati.

astrobeed


Ma la domanda difatti è: da dove ha un numero in complemento a due?


Ho fatto una piccola prova sul numero che ha fornito come esempio, è esattamente come pensavo io, lui lo interpreta come composto da un valore binario assoluto e l'ultimo bit che fa da segno, ovvero non ha capito il concetto di complemento a due e la rappresentazione dei valori negativi in binario  :)

astrobeed


ma qui come facciamo a far distinguere ad arduino che se il 24°  bit  è uno   deve trattarlo come numero negativo
e fare la conversione e visualizzazione correttamente   (float per intenderci)


Dipende dal tipo dato, se uno char sono otto bit, se è un int sono 16 bit, se è un long int sono 32 bit, se è uno short long int sono 24 bit, non sono sicuro se Arduino supporta questo tipo di dato.
Però se è un float la cosa è molto diversa visto che non si usa il complemento a due per questa tipologia di valori, sono una rappresentazione del tipo mantissa con esponente e bit di segno, se il tuo dato è di questo tipo non può essere di solo 24 bit, per forza di cose deve essere a 32 bit (Arduino non tratta i double a 64 bit).

leo72



Arduino non tratta i double a 64 bit

In realtà li tratta, basta specificare un tipo long long ed Arduino compila il codice e gestisce i numeri. Solo che non lo fa nativamente per cui si appesantisce il codice in maniera esorbitante.

astrobeed

#12
Oct 27, 2012, 07:53 am Last Edit: Oct 27, 2012, 08:01 am by astrobeed Reason: 1

In realtà li tratta, basta specificare un tipo long long ed Arduino compila il codice e gestisce i numeri. Solo che non lo fa nativamente per cui si appesantisce il codice in maniera esorbitante.


E' vero che il tipo viene accettato dal compilatore, e ci mancherebbe che non lo fa visto che fa parte dello standard C, però sia il long long che il double, è la stessa identica cosa, vengono trattati come valori a 32 bit, ed è chiaramente scritto anche sul reference che è stato aggiornato da poco con la chiarificazione che sulla DUE il tipo dato è effettivamente da 64 bit.
Questa è una limitazione di tutti i compilatore per mcu a 8 bit, almeno in tutti quelli che mi è capitato di usare, perché è già molto oneroso gestire la matematica a 32 bit su questi micro, quella a 64 bit è proibitiva in termini di impegno cpu durante i calcoli, esistono librerie matematiche esterne al C standard che permettono di fare dei calcoli anche a 64 bit.

gingardu

allora   vediamo se riesco a venirne a capo  (sempre se è possibile)  

i dati vengono presi da un dispositiovo che misura,  il dispositivo puo inviare dati che vanno da 99999  a -99999  
le "certezze sono" il dispositivo   invia sempre 2 pacchetti da 24 bit  i dati giusti sono nel secondo pacchetto

arduino prende i dati tramite un pin interrupt  (clok del dispositivo)  e un altro pin  data del dispositivo

con questa riga di codice  


   
Code: [Select]
for(x=25; x<48; x++)  {  reading=reading+(data[x]*pow(2,x-25));  

arduino li mette in fila e trova il numero decimale corrispondente (reading)

ora fino ache il numero inviato è positivo   tutto viene decodificato bene

quando invece il numero è negativo il dispositivo lo trasmette a complemento a 2

e reading  va a un numero oltre 2000000  perche il bit piu significativo e passato a uno


come faccio a d aggiustare la lettura del numero negativo?
sapendo che se reading assume un valore maggiore di un milione è sicuramente un numero negativo,

e se faccio Serialprint ( reading, BIN)  
"qualdo reading e maggiore di un milione"
stampo il numero binario che in realta dovrebbe essere convertito da complemento a due a normale
quidi su questo numero binario  maggiore di un milione
andrebbe fatta la conversione (nello sketc ovviamente)

Prendi il tuo numero : 100110101000001010100011
lo inverti :                  011001010111110101011100
e gli sommi 1:             011001010111110101011101



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

PaoloP

#14
Oct 27, 2012, 10:13 am Last Edit: Oct 27, 2012, 10:21 am by PaoloP Reason: 1
Devi saltare la lettura dell'ultimo dato perché non fa parte del numero, ma indica solo il segno.
quindi per il primo pacchetto
Code: [Select]
for(x=24; x<47; x++)  {  reading1=reading1+(data[x]*pow(2,x-24));
e per il secondo:
Code: [Select]
for(x=0; x<23; x++)  {  reading2=reading2+(data[x]*pow(2,x));

Poi con un if moltiplichi il numero -1 in base al valore dell'ultimo bit.
Code: [Select]
if (data[47]==1) reading1 = reading1 * -1;
e
Code: [Select]
if (data[23]==1) reading2 = reading2 * -1;

Controlla il codice perché non ho verificato se è corretto e compila, ma la logica dovrebbe andare.
Forse puoi fare anche un
Code: [Select]
if (data[47]==1) reading1 != reading1;

EDIT:
Verifica gli indici perché non so se il tuo array in lettura parta da 0 o da 1.
Se parte da 0 i primi 24 bit vanno da 0 a 23. 0-22 i dati e 23 il segno. E il secondo gruppo da 24 a 47, 24-46 i dati e 47 il segno.
Viceversa se parte da 1 avrai da 1 a 24 il primo pacchetto con 1-23 i dati e 24 il segno e l'altro sarà da 25 a 48 con 25-47 di dati e il 48° il segno.

Go Up