Python 32bit sw. float Ausgabe anstatt integer....

brenner

Commander
Registriert
Apr. 2002
Beiträge
3.037
N´Abend,

weiß gar nicht wie ich das Problem verständlich beschreiben soll.


Ich versuche gerade einen Stromzähler per ModBus RTU mittel RaspBerry auszulesen.
Zum testen habe ich den RS485 Adapter zuerst an ein Windows angeschlossen und diverse Tool ausprobiert. Mit einem habe ich Erfolg gehabt (siehe Screenshot). Dazu musste ich die Ausgabe aber auf "32Bit sw. float" umstellen. Im Screenshot sieht man z.b. bei Zeile 0, 2 und 4 die Spannungen der 3 Phasen.



Mittels Internet habe ich mir ein Script zusammenkopiert was die Register unter Debian ausgibt, allerdings immer nur zwei 16Bit Register und nur Dezimalwerte.
Code:
root@rpisrv01:/scripts# ./test01.py
[17255, 26771]
root@rpisrv01:/scripts#
Daraus muss, wenn ich es richtig verstanden habe, ein 32Bit Wert werden und als "sw. float"? ausgeben werden!?





Hier komme ich seit ein paar Stunden nicht weiter weil ich keine Ahnung habe was ich hier tun muss :rolleyes:




Code:
#!/usr/bin/python

import pymodbus
import serial
from pymodbus.pdu import ModbusRequest
from pymodbus.client.sync import ModbusSerialClient as ModbusClient #initialize a serial RTU client instance
from pymodbus.transaction import ModbusRtuFramer


#count= the number of registers to read
count=2
#unit= the slave unit this request is targeting
unit=1
#address= the starting address to read from
address=1


client=ModbusClient(method='rtu',port='/dev/ttyUSB0',stopbits=1,bytesize=8,parity='N',baudrate=9600,timeout=1)


#starting add, num of reg to read, slave unit.
result= client.read_input_registers(0x04,count=2,unit=1)


#print(result)
print(str(result.registers))


#closes the underlying socket connection
client.close()
 

Anhänge

  • image.jpg
    image.jpg
    281,1 KB · Aufrufe: 434
Zuletzt bearbeitet:
http://stackoverflow.com/questions/...manipulate-as-integers-bit-patterns-of-floats bespricht, was du vielleicht brauchst.
Also grob (in C)
Code:
float wert=get_float_representation_of_integer((wert1<<16)|wert2);
Wie die Fließkommadarstellung tatsächlich gewählt ist, kann ich dir leider nicht sagen.

Zur FP-Darstellung: http://www.chipkin.com/how-real-floating-point-and-32-bit-data-is-encoded-in-modbus-rtu-messages/

Ich denke, "float sw." heißt, du hast die beiden Words zu vertauschen. Also Word 2 vor Word 1

Also mit dem verlinkten Tool kommt man bei deinen Beispielwerten mit Swap Byte und Swap Word auf
+231.408493041992190

Dieser C-Code erzielt das gleiche Ergebnis (Intel-x86)
Code:
    int i1 = 17255, i2 = 26771;
    unsigned a = i1 & 0xFF, b = (i1 >> 8) & 0xFF,
        c = i2 & 0xFF, d = (i2 >> 8) & 0xFF;
    int res = (b << 24) | (a << 16) | (d << 8) | c;
    float resf = *((float*)&res);

Da ich grad Lust habe, den Code auch noch in Python 2.7
Code:
import struct
i1 = 17255
i2 = 26771
a = i1 & 0xFF
b = (i1 >> 8) & 0xFF
c = i2 & 0xFF
d = (i2 >> 8) & 0xFF;
res = (b << 24) | (a << 16) | (d << 8) | c
rep = struct.pack('>I', res)
myfloat = struct.unpack('>f', rep)[0]
print(res)
print(myfloat)
 
Zuletzt bearbeitet:
Coooool,

der Wert von 231 deutet darauf hin das es genauso ist wie du vermutet und umgesetzt hast :):):)



Auf jeden Fall komme ich jetzt weiter.


Danke!!!!
Ergänzung ()

Falls du noch wach bist,

warum funkioniert die Übergabe der Inhalte nicht?



Code:
root@rpisrv01:/scripts# ./test01.py
17255
27273
Traceback (most recent call last):
  File "./test01.py", line 46, in <module>
    a = i1 & 0xFF
TypeError: unsupported operand type(s) for &: 'str' and 'int'
root@rpisrv01:/scripts#





#!/usr/bin/python

import struct
import pymodbus
import serial
from pymodbus.pdu import ModbusRequest
from pymodbus.client.sync import ModbusSerialClient as ModbusClient #initialize a serial RTU client instance
from pymodbus.transaction import ModbusRtuFramer

##import logging
##logging.basicConfig()
##log = logging.getLogger()
##log.setLevel(logging.DEBUG)

#count= the number of registers to read
count=2
#unit= the slave unit this request is targeting
unit=1
#address= the starting address to read from
address=1


#client= ModbusClient(method = "rtu", port="/dev/ttyUSB0",stopbits = 1, bytesize = 8, parity = 'E' baudrate= 9600)
client=ModbusClient(method='rtu',port='/dev/ttyUSB0',stopbits=1,bytesize=8,parity='N',baudrate=9600,timeout=1)


###connect to the serial modbus server
##connection = client.connect()
##print connection

#starting add, num of reg to read, slave unit.
#result= client.read_holding_registers(0x00,2,unit= 0xff)
result= client.read_input_registers(0x04,count=2,unit=1)


#print(str(result.registers))

i1=(str(result.registers[0]))
i2=(str(result.registers[1]))
print(i1)
print(i2)


#i1 = 17255
#i2 = 26771
a = i1 & 0xFF
b = (i1 >> 8) & 0xFF
c = i2 & 0xFF
d = (i2 >> 8) & 0xFF;
res = (b << 24) | (a << 16) | (d << 8) | c
rep = struct.pack('>I', res)
myfloat = struct.unpack('>f', rep)[0]
print(res)
print(myfloat)


#closes the underlying socket connection
client.close()
 
Das "&" ist ein bitwise operator und kommt nicht damit klar, wenn ein Argument ein String und das andere ein Integer ist. Afaik müssen beide Integer sein, aber so ganz bin ich mit diesem bitwise Kram nie warm geworden.

Guck z.B. mal hier https://wiki.python.org/moin/BitwiseOperators

EDIT: Wo ich gerade nochmal in deinen Code gucke:

Hancock definiert i1 ja auch als int, aber das hast du auskommentiert und definierst i1 vorher als string. Sieh zu, dass in i1 der richtige Wert als int steht, dann sollte es gehen.
 
Zurück
Oben