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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy