Vai al contenuto
PLC Forum


Supervisione Di Siemens S7 300 - (Sviluppo software in visual basic)


MrC

Messaggi consigliati

Per comunicare con S7 300 uso una libreria venduta da una ditta che si chiama sintesi www.sintesi.com , e mi trovo molto bene .

Unico problema è nel leggere/scrivere dati in formato virgola mobile (real) .

Provate a scrivere un numero real (es. 1.5) e leggerlo in DINT

(viene qualcosa come 45637292) .

Vorrei fare una funzione in VB che facesse questa conversione , in modo da dribblare il problema .

Che senso hanno i 32 bit del formato REAL ?

Immagino che abbiano n bit x mantissa e n bit x esponente ...

Mi suggeriite un algoritmo per fare la conversione ?

Grazie

Link al commento
Condividi su altri siti


Non conosco abbastanza VB per dare il codice, mi limito a descrivere i numeri REAL.

I numeri IEEE Floating Point usano tutti i 32 bit. Numera i bit da destra a sinistra da 0 a 31.

Il bit 31 rappresenta il segno e lo puoi copiare tale e quale nel DINT di destinazione.

Tolto il segno un numero FP e' rappresentato entro il registro a 32 bit come 1,mantissa X 2 ^(espo-127)

espo e' rappresentato in binario normale dagli 8 bit 30...23

mantissa e' rappresentato nei 23 bit 22...0, ma non in modo intero:

Il bit 22 pesa per 2^(-1), cioe' 0,5

Il bit 21 pesa per 2^(-2), cioe' 0,25

Il bit 20 pesa per 2^(-3), cioe' 0,125

..........

Il bit 0 pesa per 2^(-23)

Per fare un esempio il numero 123456.0 risulta codificato in binario nel registro REAL come:

0100_0111_1111_0001_0010_0000_0000_0000

espo vale 100_01111_1 --> 143 decimale

Per la mantissa 111_0001_0010_0000_0000_0000 ci sono:

2^(-1) + 2^(-2) + 2^(-3) + 2^(-7) + 2^(-10)

0,5 + 0,25 + 0,125 + 0,0078125 + 0,0009765625 = 0,8837890625

Infine 1,8837890625 X 2^(143-127) = 123456

Link al commento
Condividi su altri siti

Ecco la routine pronta pronta da usare:

Function CVT_REAL(FromPLC As String) As Double

Const conv = 1.19209289550781E-07 'Costante di conversione mantissa

Dim esp As Long 'Esponente in formato Long

Dim man As Long 'Mantissa in formato Long

Dim dec As Long 'Variabile di spostamento

Dim num As Double 'Variabile di spostamento

Dim ott_str As String 'Ottetto in formato stringa

Dim ott_num(1 To 4) As Byte 'Array di ottetti in formato byte

Dim i As Integer 'Contatore ciclo for

Dim seg As Byte 'Marcatore di segno

For i = 1 To 4

ott_str = Mid(FromPLC, i, 1)

ott_num(i) = Asc(ott_str)

Next i

'Determino mantissa

man = ((ott_num(2) And 127))

man = man * (256 ^ 2)

For i = 3 To 4

dec = ott_num(i) * (256 ^ (4 - i))

man = man + dec

Next i

num = man

num = num * conv

'Determino esponente

esp = ((ott_num(1) And 127) * 2)

dec = ((ott_num(2) And 128) / 128)

esp = esp + dec

'Determino segno

seg = ((ott_num(1) And 128) / 128)

If seg = 0 Then

CVT_REAL = (1 + num) * (2 ^ (esp - 127))

Else

CVT_REAL = -((1 + num) * (2 ^ (esp - 127)))

End If

End Function

Link al commento
Condividi su altri siti

ah scusa mi ero dimenticato come usare la routine

"FromPLC" è il parametro, stringa a 4 caratteri, che contiene i 32 bit del REAL.

Il risultato della funzione è il numero reale gia convertito.

Quindi

n.real = CVT_REAL(stringa 4 byte)

Link al commento
Condividi su altri siti

Gianmario Pedrani

non so se le funzioni che tu utilizzi sono simili a prodave, ma se utilizzi prodave ed delphi puoi usare queste

funzioni

function ReadReal(Low_Word: Word; High_Word: Word):Single;

var

Rec: array [0..1] of Word;

begin

try

Rec[0] := Swap(High_Word);

Rec[1] := Swap(Low_Word) ;

Move(Rec,Result,SizeOf(Result));

except

Result := 0;

end;

end;

procedure WriteReal(FloatNr:Single; var Low_Word: Word; var High_Word: Word);

var

Rec: array [0..1] of Word;

begin

try

Move(FloatNr,Rec,SizeOf(FloatNr));

Low_Word := Swap(Rec[1]);

High_Word := Swap(Rec[0]);

except

Low_Word := 0;

High_Word := 0;

end;

end;

;)

Link al commento
Condividi su altri siti

Anche io ho fatto una routin per leggere i numeri reali, con Prodave non sono riuscito a leggere questi numeri. La soluzione adottata comunque è un pò diversa ma simile alla vostra. Ciao

Link al commento
Condividi su altri siti

  • 2 years later...

chi si è cimentato nel fare il contrario ?

cioè dal numero reale creare i 4 byte da spedire al plc e in pratica strivere un real con quella sintassi ???

io ci ho provato..ma ho subito desistito.

Link al commento
Condividi su altri siti

Provate un po’ a vedere se funziona questo:

Private Declare Sub CopyMemory Lib "kernel32" _
      Alias "RtlMoveMemory" (pDest As Any, pSource As Any, _
      ByVal ByteLen As Long)



Public Function Real(ByVal dWord As Long) As Single
    CopyMemory Real, dWord, 4&
End Function

Modificato: da JumpMan
Link al commento
Condividi su altri siti

  • 4 weeks later...

ottima idea...

non va proprio bene come l'hai scritta... bisogna lavorarci sopra.

ma l'idea di sfruttare il copy mem è notevole.

questo pomeriggio ci lavoro sopra e vi so dire.

Grazie...

Link al commento
Condividi su altri siti

CASPITA FUNZIONA...

Private Declare Sub CopyMemory Lib "kernel32" _

Alias "RtlMoveMemory" (pDest As Any, pSource As Any, _

ByVal ByteLen As Long)

Public Function CreaLong(ByVal dWord As Single) As Long

CopyMemory CreaLong, dWord, 4&

End Function

Private Sub Command1_Click()

Dim a As Single

Dim b As Long

a = Val(Text1.Text)

b = CreaLong(a)

Text2.Text = b

Text3.Text = Hex(B)

End Sub

Hiii Hiii c'e' più codice scritto per visualizzare il risultato che quello per eseguire la conversione !

Lo stesso dovrebbe valere per la lettura... basta fare viceversa

Link al commento
Condividi su altri siti

chiaramente funziona anche in lettura....

Public Function CreaSingle(ByVal dWord As Long) As Single

CopyMemory CreaSingle, dWord, 4&

End Function

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...