Pages: 1 [2]   Go Down
Author Topic: decodificare complemento a due  (Read 1212 times)
0 Members and 1 Guest are viewing this topic.
Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 123
Posts: 9308
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

con questa riga di codice  
    
Code:
for(x=25; x<48; x++)  {  reading=reading+(data[x]*pow(2,x-25));
 

Che è una assurdità in partenza, si fa con l'operatore shift e non con l'elevazione a potenza.
Il tuo problema è che Arduino non gestisce gli "short long", sono gli interi a 24 bit, quindi sei obbligato ad usare i long convertendo il valore in questo formato, come farlo in modo semplice ci devo pensare un attimo.
« Last Edit: October 27, 2012, 03:27:26 am by astrobeed » Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se elimini   il bit piu significativo  rimangono sempre gli altri 23 bit invertiti
che va aggiunto anche un bit

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

Nota il ! che inverte il bit prima di moltiplicarlo. il ! ha la priorità sulla moltiplicazione.
L'ultimo non lo devi aggiungere perché è il segno.
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

con questa riga di codice  
    
Code:
for(x=25; x<48; x++)  {  reading=reading+(data[x]*pow(2,x-25));
 

Che è una assurdità in partenza, si fa con l'operatore shift e non con l'elevazione a potenza.
Il tuo problema è che Arduino non gestisce gli "short long", sono gli interi a 24 bit, quindi sei obbligato ad usare i long convertendo il valore in questo formato, come farlo in modo semplice ci devo pensare un attimo.

Astro, da quel poco che Gin ha spiegato, lui dovrebbe ricevere questi 48 bit in sequenza dalla seriale come caratteri 0 e 1. Poi con una funzione di lettura, che tiene segreta, li inserisce in un array, presumo di char (non ci ha dato neanche la definizione), che ha una dimensione di 48 (presumo)
A questo punto tramite il ciclo for trasforma questo array che contiene la rappresentazione di un numero binario in un unsigned long (presumo perche anche qui non ci è dato sapere che razza di tipo sia la variabile reading)

Insomma, per il poco che ha detto, è già un miracolo scrivergli qualche riga di codice che forse funziona.  smiley-eek-blue
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

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

Devi saltare la lettura dell'ultimo dato perché non fa parte del numero, ma indica solo il segno.
quindi per il primo pacchetto
Code:
for(x=24; x<47; x++)  {  reading1=reading1+(data[x]*pow(2,x-24));
e per il secondo:
Code:
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:
if (data[47]==1) reading1 = reading1 * -1;
e
Code:
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:
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.

e si qui ti volevo    smiley-twist

cosi la fai troppo semplice

il problema è, che la codifica  non porta SOLO a livello  alto  il bit piu significativo
ma il bit piu significativo   va alto perche e trasformato   in complemento a due

se elimini   il bit piu significativo  rimangono sempre gli altri 23 bit invertiti
che va aggiunto anche un bit

faccio un esempio  e solo un esempio per capire)
numero  bin                                                         000000000000000000000
numero bin trasformato in complemento a 1         111111111111111111111
numero bin trasformato incomplemento a 2          111111111111111111110

se non prendo il bit piu significativo ottengo   11111111111111111110  che e sempre un numero enorme

e se lo moltiplico per -1  otterro sempre un numero enorme negativo

quando in realta   il numero bin originale e un numero piccolissimo
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: 123
Posts: 9308
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Insomma, per il poco che ha detto, è già un miracolo scrivergli qualche riga di codice che forse funziona.  smiley-eek-blue

Vero, però rimane sempre il fatto che Arduino non gestisce i tipi dati a 24 bit e questo comporta inventarsi una procedura di conversione verso i long int.
Prendiamo pure come dato di fatto che alla fine lui si trova caricato su un long int un valore a 24 bit che in realtà è un numero negativo.
Dal punto di vista matematico il complemento a due altro non è che la sottrazione tra il valore positivo massimo, in funzione del numero di bit, e quello positivo che vogliamo rappresentare come negativo, per esempio con otto bit -1 si ottiene facendo 256 - 1 = 255 che è 0b11111111 ovvero -1 in binario se il dato è di tipo signed
Se carichiamo un numero negativo a 24 bit in un long int questo viene visto come un valore positivo sempre maggiore di 8388608 (2^23), però se facciamo il procedimento opposto, ovvero la sottrazione da 0x01000000 (16777216 = 2^24) del valore contenuto nel long int otteniamo il suo reale valore positivo, a questo punto lo si moltiplica per -1 e la conversione tra tipo di dati è fatta.
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nei post precedenti trovi tutte le informazioni per scriverti il codice.
Se devi invertire il singolo bit usa il !
Se devi invertire la sequenza dei bit cambia il for da 48 a 25 decrementando x e non 25 a 48 con incremento
Per il segno puoi usare l'if come ti ho mostrato.

Adesso vai... e scrivi... su su.  smiley-mr-green smiley-mr-green
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

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

Adesso vai... e scrivi... su su.  smiley-mr-green smiley-mr-green

Sei un ottimista  smiley-mr-green
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Insomma, per il poco che ha detto, è già un miracolo scrivergli qualche riga di codice che forse funziona.  smiley-eek-blue

Vero, però rimane sempre il fatto che Arduino non gestisce i tipi dati a 24 bit e questo comporta inventarsi una procedura di conversione verso i long int.
Prendiamo pure come dato di fatto che alla fine lui si trova caricato su un long int un valore a 24 bit che in realtà è un numero negativo.
Dal punto di vista matematico il complemento a due altro non è che la sottrazione tra il valore positivo massimo, in funzione del numero di bit, e quello positivo che vogliamo rappresentare come negativo, per esempio con otto bit -1 si ottiene facendo 256 - 1 = 255 che è 0b11111111 ovvero -1 in binario se il dato è di tipo signed
Se carichiamo un numero negativo a 24 bit in un long int questo viene visto come un valore positivo sempre maggiore di 8388608 (2^23), però se facciamo il procedimento opposto, ovvero la sottrazione da 0x01000000 (16777216 = 2^24) del valore contenuto nel long int otteniamo il suo reale valore positivo, a questo punto lo si moltiplica per -1 e la conversione tra tipo di dati è fatta.

Però gestisce i long a 32 bit, quindi puoi leggere dati a 24 bit con segno e trasformarli a 32 con segno.
Diverso se supportasse solo dati a 16 bit. In quel caso avresti dovuto tagliare il numero di 24 bit ai primi 16.
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

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

Però gestisce i long a 32 bit, quindi puoi leggere dati a 24 bit con segno e trasformarli a 32 con segno.

E io che ho detto ?
Il problema è proprio la conversione tra 24 bit signed e 32 bit signed, con il semplice calcolo matematico che gli ho indicato risolve la cosa con due righe di codice.
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, ma siccome lui ha il codice bello e pronto.... (http://arduino.cc/forum/index.php/topic,121193.msg917369.html#msg917369)
la domanda è: perché ci stiamo attorcigliando il cervello di sabato mattina??  smiley-eek smiley-eek
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

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

la domanda è: perché ci stiamo attorcigliando il cervello di sabato mattina??  smiley-eek smiley-eek

Mi sa tanto che devo inserire anche gingardu nella mia black list di quelli da non leggere mai smiley
Logged

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

Ok, ma siccome lui ha il codice bello e pronto.... (http://arduino.cc/forum/index.php/topic,121193.msg917369.html#msg917369)
la domanda è: perché ci stiamo attorcigliando il cervello di sabato mattina??  smiley-eek smiley-eek
quel post e stato fatto quando ero "ingenuo",   smiley-cry
si intende prendere per buono codice o progetti messi sul web e dati per buoni

e ha furia di perdere tempo e neuroni   è venuta fuori la     prima regola:  

mai andare appresso a presunti progetti messi solo sulla "carta" se nom si vuole uscire pazzi

anzi se non c'è una realizzazione fisica nemmeno guardarli

quel codice li fa parte di decine di codici simili che non funzionano



« Last Edit: October 27, 2012, 04:41:55 pm by gingardu » 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: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se elimini   il bit piu significativo  rimangono sempre gli altri 23 bit invertiti
che va aggiunto anche un bit

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

Nota il ! che inverte il bit prima di moltiplicarlo. il ! ha la priorità sulla moltiplicazione.
L'ultimo non lo devi aggiungere perché è il segno.

quindi devo duplicare il codice e mettere un if

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


ma manchera semprte un bit da aggiungere a reading   smiley-confuse
 
se il bit di segno viene invertito anche lui anche se non lo togliamo  diventera 0  e che è inoinfluente,

appena metto su tutto riprovo
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: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Devi saltare la lettura dell'ultimo dato perché non fa parte del numero, ma indica solo il segno.
quindi per il primo pacchetto
Code:
for(x=24; x<47; x++)  {  reading1=reading1+(data[x]*pow(2,x-24));
e per il secondo:
Code:
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:
if (data[47]==1) reading1 = reading1 * -1;
e
Code:
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:
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.

ho provato un po queste righe che hai scritto  -  funzionano   smiley-cool

mettendo  nel for 0<23  prende la lettura del primo pacchetto dei bit (o i primi 24)
che dovrebbe essere la lettura dello strumento  che non viene influenzata dai vari azzeramenti
fatti con i pulsanti
solo che questa lettura ho notato che cambia se l'alimentazione dello strumento viene tolta e poi rimessa  smiley-cry  comunque amen,  se la lettura era sempre la stessa anche interrompendo l'alimentazione  avevo   "risolto"
anche mettendo il simbolo !  davanti a data funziona da invertititore di bit  smiley-cool

volevo capire l'ultima cosa  nella riga
Code:
for(x=0; x<23; x++)  {  reading2=reading2+(data[x]*pow(2,x));

hai eliminato il -24 dopo l'ultima x  che funzione/calcolo   fa   nella formula originale
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: