添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

data blocks I cant seem to be able to read

I'm only quite new to python and modbus and I have been struggling to work out how to read the MSBytes and LSBytes of this controller using both pymodbus and minimalmodbus for a week or two now so hopefully someone in the brains trust here might be able to poke me in the right direction.

This particular controller has 3 digital/coil registers (2 register addresses are read only with 8 MSBytes and 8 LSBytes and one register 1536 as pictured above which has read and write 8 MSbytes and 8 LSBytes) However I'm confused because I can't seem to be able to work out how to read them correctly.

I only seem to get errors when I try to read them with a read_coil/bits only function but read_register and read_registers functions returns a single boolean result of 0 or 1 with a count of 1 register.

Using minimalmodbus

instrument.read_register(1536)

returns: 0

instrument.read_registers(1536, 1)

returns: [0]

instrument.read_bit(1536)

returns: error

UPDATE 12-09-2018:

Reading register when control is Off/standby.

In: client.read_register(1536, 0, 3, False) Out: 1

Reading register when control is On.

In: client.read_register(1536, 0, 3, False) Out: 0

Reading register when control is in defrost.

In: client.read_register(1536, 0, 3, False) Out: 4

Response from trying to write to registers:

The control documentation says to use functioncode 6 to write changes to registers however it seems to take the new value without error but doesn't update or change the controller register.

If I use functioncode 6

In: client.write_register(1536, 1, 0, 6, False) (no error or output, and register value doesn't change)

If I use functioncode 16 as suggested it leaves the following error.

In: client.write_register(1536, 1, 0, 16, False)

ValueError                                Traceback (most recent call last)
<ipython-input-22-66ccb391e76c> in <module>()
----> 1 client.write_register(1536, 1, 0, 16, False)
/usr/local/lib/python3.5/dist-packages/minimalmodbus.py in write_register(self, registeraddress, value, numberOfDecimals, functioncode, signed)
    294         _checkNumerical(value, description='input value')
--> 296         self._genericCommand(functioncode, registeraddress, value, numberOfDecimals, signed=signed)
/usr/local/lib/python3.5/dist-packages/minimalmodbus.py in _genericCommand(self, functioncode, registeraddress, value, numberOfDecimals, numberOfRegisters, signed, payloadformat)
    696         ## Communicate ##
--> 697         payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
    699         ## Check the contents in the response payload ##
/usr/local/lib/python3.5/dist-packages/minimalmodbus.py in _performCommand(self, functioncode, payloadToSlave)
    797         # Extract payload
--> 798         payloadFromSlave = _extractPayload(response, self.address, self.mode, functioncode)
    799         return payloadFromSlave
/usr/local/lib/python3.5/dist-packages/minimalmodbus.py in _extractPayload(response, slaveaddress, mode, functioncode)
   1087     if receivedFunctioncode == _setBitOn(functioncode, BITNUMBER_FUNCTIONCODE_ERRORINDICATION):
-> 1088         raise ValueError('The slave is indicating an error. The response is: {!r}'.format(response))
   1090     elif receivedFunctioncode != functioncode:
    ValueError: The slave is indicating an error. The response is: '\x02\x90\x01}À'`

EDIT: This function can read only the first bit of the address. If you have more than one bit on in the address you can't use this function or you will recive the error.

If you use the read_register function:

read_register(registeraddress, numberOfDecimals=0, functioncode=3, signed=False)
read_register(1536,0,3,False)

as output you will recive an Unsigned Int

If you use read_registers:

read_registers(registeraddress, numberOfRegisters, functioncode=3)
read_registers(1536, 1, 3)

As you can read here:

For asking modification to the device you have to write the MSByte and the LSByte.

SOLUTION:

import minimalmodbus
def _intToBin(toConvert):
    #Here you convert the int value to binary, after that to string getting from index 2 to 10
    MSByte = str(bin(toConvert))[2:10]
    #Here you convert the int value to binary, after that to string getting from index 10 to 18
    LSByte = str(bin(toConvert))[10:18]
    final = MSByte+LSByte
    return final
def _binToInt():
    return int(value,2)
def _changeBit(bitToChange, binVal, valueToSet):
    #Set the single bit
    tmpList = list(binVal)
    finalString = ""
    tmpList[bitToChange] = str(int(valueToSet))
    for x in tmpList:
        finalString += x
    return finalString
# DEFAULT CONFIG OF minimalmodbus
ReadType = minimalmodbus.MODE_RTU
minimalmodbus.CLOSE_PORT_AFTER_EACH_CALL = True
minimalmodbus.BAUDRATE = 19200
minimalmodbus.PARITY = 'E'
minimalmodbus.BYTESIZE = 8
minimalmodbus.STOPBITS = 1
minimalmodbus.TIMEOUT = 0.05
modbusAddress = 1536
instrument = minimalmodbus.Instrument("/dev/tty.usbserial-A9CVVTT5",1,mode="rtu")
instrument.debug = True
readValue = instrument.read_register(modbusAddress,0,3,False)
#This is to demostrate that the conversion works fine
print "This is the pure readed value: " + str(readValue)
binValue = _intToBin(readValue)
print "This is the value after the binary conversion, if you want to come back to int: " + str(int(binValue,2))
#Here you can change the state of your converted value
print "Before change binary value: " + binValue
changeBit = _changeBit(3,binValue,False)
print "Single bit change: " + str(changeBit)
print "Int after bit value change: " + str(_binToInt(changeBit))
#After that you can write back your register
instrument.write_register(modbusAddress,_binToInt(changeBit),0,16,False)

OUTPUT:

This is the pure readed value: 65472
This is the value after the binary conversion, if you want to come back to int: 65472
Before change binary value: 1111111111000000
Single bit change: 1110111111000000
Int after bit value change: 61376

UPDATE 12-09-2018:

Reading:

You are reading the register 1536, and it correctly returns the int value. So you only have to translate the int value to bin value, and to associate the translated bin value to the picture.

Writing:

As you can read in the documentation:

  • Function code 6: Write single register
  • Function code 16: Write multiple register
  • So this is the correct command:

    client.write_register(1536, 1, 0, 6, False)
    

    now, the problem is:

    If you read under the picture the note is talking about writing LSByte and MSByte to make bit status changes.

    So, you are writing the value 1 to the register 1536, but you are writing it only in the LSByte.

    You have to write also in the MSByte, then:

    LSByte = "00000001" # it is 1 in decimal
    MSByte = "00000001" # it is 1 in decimal
    ValueToSend = MSByte + LSByte
    # The result value will be: "0000000100000001"
    # If you convert it to decimal is: 257
    #Then here you have to write
    client.write_register(1536, 257, 0, 6, False)
    

    The MSByte must be written to 1, to the LSByte corresponding bit.

    For example:

  • Change standby status to 1: MSByte = "00000001" and the LSByte = "00000001"
  • Change standby status to 0: MSByte = "00000001" and the LSByte = "00000000"
  • Change cold room light to 1: MSByte = "00000010" and the LSByte = "00000010"
  • Change cold room light to 0: MSByte = "00000010" and the LSByte = "00000000"
  • You have to use the conversion from int to bin, change the bit value of the MSByte and LSByte, convert again from bin to int, and write the value.

    Thanks for taking the time to write back. Reading the register and registers is no problem however it only extracts a boolean integer value of 0. If I try to read a bit as your example it gives an error: [The response is: '\x02\x82\x01q`]' which is whats giving me a headache! read_register(1536, 0, 3) - returns 0 but I don't know how to break that into string bits and read them. – Cory C Sep 11, 2018 at 7:33 thanks. If i do read_string(1536, 1) it returns: '\x00\x04' which converts to 0 & 4 in hex but that doesn't seem to line up with what the bits should be either... – Cory C Sep 11, 2018 at 8:08 Thanks Carlo, I think there must be something wrong with there documentation? I can run the first block of your code (converted to python3, and it still gives me a read value of 0) – Cory C Sep 12, 2018 at 7:00

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.