Italian Aiuto calcolo

Fulvio75

Well-Known Member
Licensed User
Ciao, ho bisogno di un aiutino matematico ovvero, ho un PLC che mi invia
2 byte che tradotti in decimali mi danno due numeri interi A B.
Es.:
Quando A vale 40 il valore reale è 80 e A va da 0 a 256.
B anche lui va da 0 a 256.

Il problema è che il PLC incrementa A di 1 quindi 40 41 42 ecc.. per trovare il valore reale di A devo fare A*2 quindi avrei 80 82 84, i valori intermedi non li ho quindi non visualizzo 81 83.

B varia sempre dando valori da 0 a 256 e vorrei una formula utilizzando A e B che mi faccia incrementare il valore correttamente.

Il PLC passa questi dati in base alla posizione di un sensore quindi ruotando il sensore cambia A 40 41 42 che in realtà è 80 82 84 perché moltiplicato X2 e tra un valore e l'altro di A passa B da 0 a 256.
Es.
Quando A è 80 prima che diventi 82, B va da 0 a 256
 

Daestrum

Expert
Licensed User
Longtime User
B4X:
Sub Process_Globals
    Dim data(2) As Byte ' your data from ?
End Sub

Sub AppStart (Args() As String)
    data = Array As Byte(34,25) '  dummy data
   
    Dim a As Int = data(0)
    Dim b As Int = data(1)
    Dim res As Double ' for the result as decimal value
   
    res = (a*2) + (b/255) ' its possible the 255 could be 128 to give you the missing values see below
' if a was 20 then it is doubled to 40 so you would only get result values in series 0,2,4,6,8 etc
' if b is divided by 128 instead of 255 then it would pruduce values in range 0 to 1.9999999...
' so you could have result values that span 2 for each value pair , thus filling in the missing integer part.
' just a guess though.
   
    Log(res)
End Sub
 
Last edited:

sirjo66

Well-Known Member
Licensed User
Longtime User
Ok, ma devi fare degli esempi di quello che vuoi ottenere,
ad esempio
Se A vale 41 e B vale 100, che numero devi ottenere ???

La risposta di @Daestrum può anche andar bene se devi ottenere un risultato Float, ma facci capire meglio

B varia sempre dando valori da 0 a 256
mmmmmmmm........ mi sembra strano, un byte va da 0 a 255

B4X:
res = (a*2) + (b/255)

secondo me è errata, semmai dovrebbe essere
B4X:
res = (a * 2) + (b / 256)

Comunque dovresti vedere la documentazione, perchè la cosa è strana che A salti di due in due.
Infatti il discorso di @Daestrum è giusto, e cioè potrebbe essere che B si deva dividere per 128 per generare numeri da 0 a 1.9999999, che poi quindi A scatterebbe di 2
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Forgot to add check for -ve value (assuming you only want +ve ones)
B4X:
    Dim a As Int = data(0)
    Dim b As Int = data(1)
 
    If a < 0 Then a = a + 256
    If b < 0 Then b = b + 256
 
    Dim res As Double = a*2 + b/128

Or in 1 line (assuming data() has the 2 bytes)
B4X:
   res = Bit.And(data(0),0xff) * 2 + Bit.And(data(1),0xff) / 128
 
Last edited:

emexes

Expert
Licensed User
Infatti il discorso di @Daestrum è giusto, e cioè potrebbe essere che B si deva dividere per 128 per generare numeri da 0 a 1.9999999, che poi quindi A scatterebbe di 2

Oppure che il risultato è costituito dai 9 bit alti del valore a 16 bit A*256+B.

L'ho visto fare dai convertitori analogico-digitali per rendere le letture uguali indipendentemente dal fatto che siano convertitori a 10-11-12-ecc bit.
 

Fulvio75

Well-Known Member
Licensed User
Forgot to add check for -ve value (assuming you only want +ve ones)
B4X:
    Dim a As Int = data(0)
    Dim b As Int = data(1)
 
    If a < 0 Then a = a + 256
    If b < 0 Then b = b + 256
 
    Dim res As Double = a*2 + b/128

Or in 1 line (assuming data() has the 2 bytes)
B4X:
   res = Bit.And(data(0),0xff) * 2 + Bit.And(data(1),0xff) / 128
Oggi provo questo, nei giorni scorsi ho provato (a*2)+(b/256) ma non dava il valore corretto
A è la metà del valore corretto e infatti va moltiplicato X2 però il risultato salta di un numero ovviamente.
B va da 0 a 255
Es
A= 41 prima di diventare 42 b va da 0 a 255 poi diventa 42 e b torna a 0

Gestirò tutto via codice, pensavo si potesse fare con una formula, controllo B e in base a quello che mi restituisce vario A
 
Last edited:

udg

Expert
Licensed User
Longtime User
A parte verificare se il suggerimento di @emexes non sia quello risolutivo, potresti pensare di portare pima tutto in B e poi produrre il valore finale, come faresti per ore e minuti.
Ad esempio A = 21 ti dice che B è arrivato a 255 21 volre (che tu raddoppi a 42), a questo sommi il valore corrente di B (es. 37) e ti ritrovi 42*255+37 ovvero il valore "finale" espresso in giri di B. A quel punto dividi per 255 e hai parte intera e parte decimale, se è ciò che ti occorre.
 

Fulvio75

Well-Known Member
Licensed User
A parte verificare se il suggerimento di @emexes non sia quello risolutivo, potresti pensare di portare pima tutto in B e poi produrre il valore finale, come faresti per ore e minuti.
Ad esempio A = 21 ti dice che B è arrivato a 255 21 volre (che tu raddoppi a 42), a questo sommi il valore corrente di B (es. 37) e ti ritrovi 42*255+37 ovvero il valore "finale" espresso in giri di B. A quel punto dividi per 255 e hai parte intera e parte decimale, se è ciò che ti occorre.
Il problema è che raddoppiando A
20 valore reale quindi 20x2 40
21 valore reale quindi 21x2 42

Il valore di mezzo 41 non lo trovo perché il PLC passa 20,21,22 eccecc che corrispondano alla metà del valore reale
 

Fulvio75

Well-Known Member
Licensed User
Forse mi sono spiegato male io
Il PLC mi dà due valori che ricavo da una stringa hex
A
B

Es:
Mentre il valore A corrisponde 40 (valore effettivo reale 80) il valore B varia da 0 a 255, poi A passa 41 e B torna 0.
Il problema è che raddoppiando A salta di un numero quindi 80 82 84 i mezzi 81 e 83 non li trovo.
Pensavo si potesse fare una formula per avere tutti i numeri di seguito
 

udg

Expert
Licensed User
Longtime User
Quindi il 127 di B vale 1 reale di A
Se calcoli tutto come B e dividi per 127 dovresti avere ciò che cerchi, no?
Ora sono in giro e non posso provare
 

Fulvio75

Well-Known Member
Licensed User
Quindi il 127 di B vale 1 reale di A
Se calcoli tutto come B e dividi per 127 dovresti avere ciò che cerchi, no?
Ora sono in giro e non posso provare
Non posso calcolare tutto come B perché quello ti da il "passo" tra due numeri di A
 

Fulvio75

Well-Known Member
Licensed User
Fatto con codice

B4X:
Sub test
        
    Dim res As Float = 0
    
    For a = 0 To 40
        
        'Log(i)       
        For b = 0 To 256
            
            If b = 0 And a = 0 Then
                
                res = 0
            
            else If b <= 128 And a > 0 Then
    
                res= (a*2)-1

            else If b > 128 And a > 0 Then
    
                res= (a*2)

            End If
            
            Label1.Text = res
            
            'per vedere il risultato'
            Sleep(10)
            
        Next

    Next
    
End Sub
 

Sagenut

Expert
Licensed User
Longtime User
Mi chiedo solo se la forma corretta non sia questa.
B4X:
Sub test
        
    Dim res As Float = 0
    
    For a = 0 To 40
        
        'Log(i)       
        For b = 0 To 255    'Quì 255 anzichè 256
            
            If b = 0 And a = 0 Then
                
                res = 0
            
            else If b <= 127 And a > 0 Then    '127 al posto di 128
    
                res= (a*2)-1

            else If b > 127 And a > 0 Then    '127 al posto di 128
    
                res= (a*2)

            End If
            
            Label1.Text = res
            
            'per vedere il risultato'
            Sleep(10)
            
        Next

    Next
    
End Sub
 

udg

Expert
Licensed User
Longtime User
Bene che hai risolto. Per completezza, io intendevo qualcosa di questo genere;
B4X:
    Dim a,b As Int
    Dim temp As Double
   
    'valori ricevuti dal PLC all'istante x
    a = 3                        'questo fornisci il valore 2
    b = 128                        'questo fornisce il valore 1 per B che va da 128 a 255; altrimenti zero
    temp = (a*256+b)/128        'formula che riporta tutto a n gruppi da 128
    Log(Floor(temp))            'solo parte intera
    Log ("************")
   
    'Test in un loop di valori continui da A=0 e B =0 fino a A=40 e B=255; stampiamo solo per 0, 128
    'Il contatore scatta a B=128 per le letture dispari; quelle pari provvengono da A
    For a = 0 To 40
        For b = 0 To 255
            temp = (a*256+b)/128
            Select b
                Case 0, 128
                   Log($"$1.0{temp}  $1.0{Floor(temp)}"$)
            End Select
        Next
    Next
Di tutto questo a te basta la formula di temp visto che i valori di A e B li ricevi dal PLC.

Se A e B fossero due rotelline dello stesso meccanismo (ad esempio un odometro), qui avresti che quando B raggiunge 128 A si incrementerebbe di 1 e lo stesso quando B torna a zero; in pratica ogni giro completo di B vale 2 unità per A.
Nel tuo caso il valore di A è fornito separatamente ed indica la metà dei cicli effettuati da B, quindi la formula "corregge" questa situazione.

Come dicevo, questo post è solo per completezza rispetto all'idea che avevo espresso inizialmente.
 

Daestrum

Expert
Licensed User
Longtime User
It would be useful to know what values you expect to get (and what they represent).
You get 2 bytes, is that a short? Does the endian come into play?
 

udg

Expert
Licensed User
Longtime User
In che senso? Se lanci il loop sembra restituire tutti i valori da 0 in avanti con passo 1.
Non è ciò che desideravi?
Altrimenti vale la considerazione ultima di @Daestrum : che valori ti aseptti in funzione di A e B? Come sono legati tra loro?

Ripeto. l'importante è che tu abbia trovato una soluzione al problema. Qui ora si parla solo9 di una possibile alternativa che porti ad una formula unica. Alternativa ovviamente non necessaria.
 

Fulvio75

Well-Known Member
Licensed User
In che senso? Se lanci il loop sembra restituire tutti i valori da 0 in avanti con passo 1.
Non è ciò che desideravi?
Altrimenti vale la considerazione ultima di @Daestrum : che valori ti aseptti in funzione di A e B? Come sono legati tra loro?

Ripeto. l'importante è che tu abbia trovato una soluzione al problema. Qui ora si parla solo9 di una possibile alternativa che porti ad una formula unica. Alternativa ovviamente non necessaria.
A del PLC è la metà del valore reale che devo ottenere quindi va moltiplicato per 2 e salta di un numero
 

udg

Expert
Licensed User
Longtime User
Ok, ma se provi il loop di cui al #14 vedi che produce tutti gli interi positivi da zero in avanti, senza saltare nulla.
Così come la formula che precede il loop e che si basa sul fatto che fornisci tu i valori di A e B; anche questa produce tuti gli interi positivi (i dispari li ottieni per B >=128)
 
Last edited:

Fulvio75

Well-Known Member
Licensed User
Ok, ma se provo il loop di cui al #14 vedi che produce tutti gli interi positivi da zero in avanti, senza saltare nulla.
Così come la formula che precede il loop e che si basa sul fatto che fornisci tu i valori di A e B; anchen questa produce tuti gli interi positivi (i dispari li ottieni per B >=128)
L'ho provato ora con calma PLCValue= ((a*256)+b))/128 funziona
Grazie
Commento il mio codice e lo tengo di riserva, quindi va con la sola formula
 
Top