Code Monkey home page Code Monkey logo

minimalmodbus's People

Contributors

pyhys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

minimalmodbus's Issues

Using special function codes

Hi,

DISCLAIMER: I'm quite new to RS485 so... maybe I'm asking something really stupid :)

I've been working on a "driver" for reading values and controlling an Ozone Sensor that uses Modbus over a RS485 port.

Everything has been quite smooth by using this (great, by the way) library. Main features of the sensor use the standar function codes (1, 3, 4, 6, 16...) but it also uses function code 15 to configure a couple of relays (INT16 for 0 or 1 values). Here is the reference from the specs (columns are address, description, function code, R/W, length, value type, possible values and default values):

image

Is it possible to use those function code in any way? Does it make sense?

Thanks!

several reads fails on 0.7 with "IOError: No communication with the instrument (no answer)" but not on 0.6

Hallo minimalmodebus devs

I have an issue with the latest version. I have a drivers that runs perfectly with version 0.6, but with 0.7 it fails with the error mentioned in the subject. The debug information does not tell me very much (except that it times out):

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x02\x03\x00y\x00\x01U\xe0' (02 03 00 79 00 01 55 E0)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 20.1 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Response from instrument: '' () (0 bytes), roundtrip time: 2003.0 ms. Timeout setting: 2000.0 ms.

I guess my best bet is that something changed between 0.6 and 0.7 that changes how the lower level communication via serial is done.

The program is running on raspbian jessie. Serial version i 3.2.1.

I am happy to gather additional information as required.

write_register pauses indefinitely when no slave is connected

System information

  • OS Platform: Windows 10
  • python version: 3.6.5
  • minimalmodbus version: 0.7.0
  • Directions to reproduce: Use com0com to create a virtual serial port (for testing purposes). Then run this code:
import minimalmodbus as mb

def main():
    mb.BAUDRATE = 9600
    mb.TIMEOUT = 0.1
    slave = mb.Instrument('COM8', 0)
    print("Start Write")
    slave.write_register(1, 0b100, functioncode=6) #Program hangs here
    print("Done")

if __name__ == '__main__':
    main()

Problem

Minimalmodbus pauses indefinitely when write_register is called without a slave connected. I tested this with a virtual serial port, but I'm pretty sure it also happened once when I was using an actual serial port and the Arduino microcontroller I was talking to was off. I did a bit of print-statement testing and it looks like the problem occurs within _genericCommand.

read_bit does interprets wrong response part

Is it a bug, or am i doing something wrong ?

My code:

i = DeltaDVP.DeltaDVP('/dev/tty.usbserial-AI02L43I', 1)
i.read_bit(0x502,functioncode=1)

Debug Output:

MinimalModbus debug mode. Writing to instrument (expecting 13 bytes back): ':010105020001F6\r\n' (3A 30 31 30 31 30 35 30 32 30 30 30 31 46 36 0D 0A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 204687.4 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Response from instrument: ':01010103FA\r\n' (3A 30 31 30 31 30 31 30 33 46 41 0D 0A) (13 bytes), roundtrip time: 40.3 ms. Timeout setting: 50.0 ms.

Error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/minimalmodbus.py", line 193, in read_bit
    return self._genericCommand(functioncode, registeraddress)
  File "/usr/local/lib/python2.7/site-packages/minimalmodbus.py", line 726, in _genericCommand
    return _bitResponseToValue(registerdata)
  File "/usr/local/lib/python2.7/site-packages/minimalmodbus.py", line 1770, in _bitResponseToValue
    raise ValueError('Could not convert bit response to a value. Input: {0!r}'.format(bytestring))
ValueError: Could not convert bit response to a value. Input: '\x03'
>>> 

Interest in function code 23?

Hallo minimalmodbus devs and thanks for an amazing package.

I'm currently trying to communicate with a device that uses function code 23 (which is not currently supported by minimalmodbus). Right now I'm just using pymodbus, but I would like to use minimalmodbus for this also (since we use minimalmodbus other places as well, and since pymodbus is not as easy to use and does not support Python3).

I have read through the source code and feel relative certain that I can implement function code 23 (read/write multiple registers), but before I start, I wanted to ask whether there would be an interest in including it in minimalmodbus (provided the implementation is of high enough quality)?

If there is interest, we can have a discussion about implementation and top level interface afterwards.

read_register() and write_register() failing

When I call read_string( 19, 7 ) I get a response as expected. But when I call write_register( 99, 0 ) I get an error. Then when I call read_string( 19, 7) again I get an error (where it succeeded before), but all calls after that are fine.

This will happen with either read_register() or write_register() where they will throw an exception and print an incorrect response packet, and complain about the CRC.

My modbus instrument seems to be working fine. When I write_register() I can see the outputs change as I commanded. So I know the instrument is receiving the command. I also hooked up a second RS485toUSB converter (on a seperate computer) up so I could snoop on the transaction. Both the query and the response look fine on the bus, but the response is garbled in the exception report. And as said before the modbus instrument is responding correctly.

Here are some scripts that I wrote that demonstrate the issue.
minimal_bug.py (This demonstrates the issue)
minimal_bug_OUTPUT.txt (Annotated output from minimal_bug.py)
hexdump.py (snooping on the RS485 line from my linux box)
hexdump_OUTPUT.txt (Annotated output from hexdump.py, shows the correct query and response)

System running minimal_bug.py is:
Windows 10
python 2.7
minimalmodbus 0.7
minimalmodbus.serial 3.3

Please excuse my poor python skills, I am still new to it.

minimalmodbus_bug_scripts.zip

Problem to read rs485 using function 4 - Modbus Enron 32 bits

Hi,

I'm using the below code to try read data from devide by rs485, but return checksum error.

The device use Modbus Enron 32 bits according of the documentation.
Device: http://www.renzbr.com/produtos3.php?cod_produto=104

import minimalmodbus
import serial
instrument = minimalmodbus.Instrument('/dev/ttyUSB1', 1)
instrument.serial.baudrate = 19200 # Pode ser 9600 ou 19200.
instrument.serial.bytesize = 8 # Data bits.
instrument.serial.stopbits = 2 # Stop bits.
instrument.serial.parity = serial.PARITY_NONE
instrument.serial.timeout = 0.5
instrument.serial.dsrdtr = False
instrument.serial.rtscts = False
instrument.address = 1 # Pode ser de 1 até 247
instrument.debug = True
#instrument.precalculate_read_size = False
instrument.handle_local_echo = True
instrument.mode = minimalmodbus.MODE_RTU
instrument.read_register(registeraddress=6, functioncode=4)

But i receved the follow error:

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x01\x04\x00\x06\x00\x01\xd1\xcb' (01 04 00 06 00 01 D1 CB)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1527799597297.7 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Discarding this local echo: '\x01\x04\x00\x06\x00\x01\xd1\xcb' (8 bytes).
MinimalModbus debug mode. Response from instrument: '\x01\x04\x04?G\xdb\xc1' (01 04 04 3F 47 DB C1) (7 bytes), roundtrip time: 101.6 ms. Timeout setting: 500.0 ms.

Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 258, in read_register
return self._genericCommand(functioncode, registeraddress, numberOfDecimals=numberOfDecimals, signed=signed)
File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 697, in _genericCommand
payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 798, in _performCommand
payloadFromSlave = _extractPayload(response, self.address, self.mode, functioncode)
File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 1075, in _extractPayload
raise ValueError(text)
ValueError: Checksum error in rtu mode: '\xdb\xc1' instead of '\x08\xf3' . The response is: '\x01\x04\x04?G\xdb\xc1' (plain response: '\x01\x04\x04?G\xdb\xc1')

Searching about Enron Modbus I discovery that it's use 32bits by register instead 16 bits (not 2 registers 16bits to complete one 32bits).
I tried use read_long, read_float but nothing working too.

Note: function 3 to read registers works!

Anybody can help me?

I'm using Raspbian GNU/Linux 9 (stretch) operation system.

write_long() using function code 6

1)The current implementation uses function code 16 to write two registers. My slave accepts only function code 6 to write. I need to write 32 bit value to two consecutive registers using your write_long() function using code 6. Can you add that feature?

  1. When using read_long(address), the return value is calculated by placing value at address at upper half and value at address+1 at lower half. I need that to work vice-versa.

cannot change serial.parity

The following code works correctly:
import minimalmodbus # pip3 install -U minimalmodbus
device = minimalmodbus.Instrument('/dev/ttyS0', 7)
device.serial.baudrate = 9600
device.serial.bytesize = 8
device.serial.parity = 'N'
device.serial.stopbits = 1
print(device)

An attempt to change the serial.parity 'N' to e.g. 'E' or 'O' ends in an error:
import minimalmodbus # pip3 install -U minimalmodbus
device = minimalmodbus.Instrument('/dev/ttyS0', 7)
device.serial.baudrate = 9600
device.serial.bytesize = 8
device.serial.parity = 'E' # <-- place of change, possible values 'N', 'E', 'O', 'M', 'S'
device.serial.stopbits = 1

[iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
termios.error: (22, 'Invalid argument')

screenshot

it's probably a minimalmodbus module error

Doubt with the Code: 20033

I have some doubts, I was able to connect my device with minimalmodbus. I return some values that are shown on the device correctly, but the main part of alerts I can not.

An example is trying to read the code: 20033, which should return from 1 to 15 bits, but returns a different number as below:

End 20033 Status Record

query = instrument.read_register (20033, 0)
print (query)
Result Pages: 8469

Could someone help me?

Read Multiple coils?

I may be missing out on something basic but for some reason, I can't find a direct way to read multiple coils using minimalmodbus. I read the documentation, StackExchange pages, and even this Github project.
Like to read multiple registers you use read_registers() instead of read_register. Why isn't there a read_coils() function along with read_coil().
As a way around this, I have to manually write the whole packet over serial and read its reply back. This even though is functional, is too tedious to maintain.
Please help me understand if I am missing something silly.

Thank you.

How to read Error Message

Hi how to read error message for print() function. Can you help me ?
For example : Timeout error , Slave device illegal adress ......
How to show with print function

"ValueError: Wrong functioncode: 4 instead of 3. The response is: '\x01\x04\x04\x00\x00\x00\x00û\x84'"

System Information

  • OS Platform: Ubuntu 16.04 LTS
  • Python version: 3.5.2
  • minimalmodbus version: 0.7.0
  • Directions to reproduce: try polling a device with read_registers() for a value.

Problem

This error was thrown from the following code:

var_1 = i.read_registers(registeraddress=2012, numberOfRegisters=2, functioncode=3)

The device was setup like this, if it's relevant:

i = minimalmodbus.Instrument(port='/dev/ttyUSB0', slaveaddress=1, mode='rtu')
i.serial.baudrate = 19200
i.serial.bytesize = 8
i.serial.parity = serial.PARITY_EVEN
i.serial.stopbits = 1
i.serial.timeout = 1

The only thing I can think of is Python is returning the wrong line when providing the ValueError.

I wanted to post this to make this Git aware of the problem, I know it's not the most active repo. I think this is just a one-off exception but this code has been working for over a year without fail.

Thanks

Convert read_registers to long

Hello,

I'm trying to read 14 longs via read_registers. Read registers returns a list of integers where I need to combine them for a long.

How can I achieve that?
Thanks,

Problem with IOError line 930

I poll 3 registers with 3 uses of the raw=slave.read_register(x) cmd on a RPi running python 2.7 under Jessie Lite. I've noticed if I get a legitimate I/O error on the first register then I get bogus I/O errors for the other two. The USB to RS232 dongle does not flash it's Tx light for the next 2 reads, so I'm getting those I/O errors because minimal modbus is not sending for the other two. Somehow the 1st error does something inside minimal modbus that prevents it sending for the next 2 slave.read cmds.
Bizarrely, if I close & rerun my program all is good again till the next legitimate IOError then complete lockout again for any subsequent reads, again because minimal modbus is not sending.
Upon further checking I've realised this also applies to any other errors raised by minimal modbus. For example the ValueError (when response checksum is wrong) triggers indefinite IOErrors from then on, again because minimal modbus is not sending. It says it's sending (with diagnostic mode on) but it isn't.

Handling of broadcast - no response expected

When using address 0, no slave should reposne, so there is no answer expected (no need to wait for timeout etc.)

How to implement correctly this behavior in minimalmodbus?

After investigating the source code little bit, I must change the source itself. In function _perform_command, I set number_of_bytes_to_read = 0 when the address is broadcast. This generates exception minimalmodbus.NoResponseError without any timeout which is good compromise for me, but what is the correct solution for this?

If there is no good solution for this now, I can create pull-request, but currently, I don't know the target behavior which will fit to library ideas, e.g. what to return.

Handling multiple slaves on one bus

Imagine a case where I have more than one USB <=> RS485 Modbus dongle on one machine. And further imagine that each RS485 Modbus has more than one instrument attached to it. (In fact, in our testing environment, that's exactly what we're facing.)

Unless I'm mistaken, minimalmodbus is not set up to handle multiple instruments on one bus. I see two problems in the current structure:

  • Communication parameters are all class variables (e.g. minimalmodbus.BAUDRATE) and cannot be set per master.
  • Port names (e.g. COM4 or /dev/cu.usb01) are associated with the Instrument and not with the master.

So, some release in the future might consider a refactoring to make this kind of thing possible:

masterA = minimalmodbus.Master('COM4')
masterA.baud_rate = 19200
masterA.timeout = 0.01
masterB = minimalmodbus.Master('COM5')
masterB.baud_rate = 38400

instrumentA1 = minimalmodbus.Instrument(masterA, 1) # modbus A, address 1
instrumentA2 = minimalmodbus.Instrument(masterA, 2) # modbus A, address 2
instrumentB1 = minimalmodbus.Instrument(masterB, 1) # modbus B, address 1

I'd welcome thoughts and discussion on whether or not this is a good direction.

Using non-standard device adresses

Thanks for this module! Here are my findings:

Eurotherm 3200 series use Modbus RTU with the reserved* address 255 for their Configuration Clip (ID 3000CK. Contacts: 3.3V GND _ Tx Rx [relay?]). This address is AFAIK not accessible as parameter and thus cannot be changed.

MODBUS over serial line specification and implementation guide V1.0

2.2 MODBUS Addressing rules
The MODBUS addressing space comprises 256 different addresses.
0 Broadcast address
From 1 to 247 Slave individual addresses
From 248 to 255 Reserved
The Address 0 is reserved as the broadcast address. All slave nodes must recognise the broadcast address.
The MODBUS Master node has no specific address, only the slave nodes must have an address. This address must be unique on a MODBUS serial bus.

The device address ("slaveaddress" aka "self.address") used by class minimalmodbus.Instrument(port, slaveaddress, mode='rtu') is limited from 0 to 247 by the module-level function _checkSlaveaddress(slaveaddress).

Aside hacking this limit in minimalmodbus.py directly, one can replace the function in question like so:

#! python3
#coding=utf-8
"""
Playing with a 3000 series Eurotherm connected with "Configuration Clip" using the hardcoded address 255.
"""

import minimalmodbus  # https://github.com/pyhys/minimalmodbus

# change default
minimalmodbus.BAUDRATE = 9600


# Currently
print("This doesn't work ..")
try:
  instrument = minimalmodbus.Instrument('COM3', 255) # port name, slave address (in decimal)
  temperature = instrument.read_register(1, 1) # Registernumber, number of decimals
  print(temperature)
except ValueError as e:
  print("", e)


# Replacing the module function testing the address
print("This does ..")
def _checkSlaveaddress(slaveaddress):
  SLAVEADDRESS_MAX = 255
  SLAVEADDRESS_MIN = 0
  minimalmodbus._checkInt(slaveaddress, SLAVEADDRESS_MIN, SLAVEADDRESS_MAX, description='slaveaddress')

minimalmodbus._checkSlaveaddress = _checkSlaveaddress

# connect and read
instrument = minimalmodbus.Instrument('COM3', 255) # port name, slave address (in decimal)
temperature = instrument.read_register(1, 1) # Registernumber, number of decimals
print(" ", temperature) # decimal point off with instrument set to nnn.nn

Alternatively, one could add a convenience argument to the constructor, e.g. addressrange=range(247+1).
Or, instead of raising an Exception, just issue a warning.

Slave errors should be a distinct exception

Having errors from the slave be ValueError exceptions makes it hard to discriminate between protocol problems (slave errors and the like) and internal errors (coding mistakes, etc).

It might be nice if there were a separate class of exceptions (like ModbusError) which were thrown when slave errors occur, so one could do something like

try:
    instrument.write_register(whatever, a_value)
except minimalmodbus.ModbusError:
    # Handle the error somehow

Choose CRC algorithm

We want to use minimalmodbus to talk to a Sierra Compod interface on some lab equipment. We have determined that the unit uses a CRC-16 CCITT algorithm, which is different than the CRC-16 algorithm that minimalmodbus uses.

Browsing the code, it looks like switching algorithms should be a matter of changing the lookup table and possibly a function definition. We have two questions:

  1. Is there anyone here who could walk us through modifying the code to calculate the CRC's?
  2. Would you consider an option to choose the CRC algorithm in later releases?

Thanks!

rolling response or delay to answer (first byte empty)

Hello,

Sorry, I am not an Modbus or python expert, but I don't know how continue to solve my issue :
I've an modbus equipment (Nilan combi 300), and use an FDTI USB plugin RPI to communicate.

My issue is I can't get a stable response, and that give checksum error. I've two script to explained issue :

  • one the response is stable
  • second the response is "rolling", and I success to get one right response after 5-6times.

I never have issue with transmitting a request, the equipment react always at first sending, but response is always... uncertain.
I have also try another USB-serial chip, same issue.
Note the first byte from stable response is always an empty byte, so I've put some resistor for biasing but without more success, and with two type of cable

First script output (stable, always the same):

sudo python nilan2.py
TESTING Nilan Connection
__main__.Nilan<id=0x76c99238, address=30, mode=rtu, close_port_after_each_call=False, precalculate_read_size=False, debug=True, serial=Serial<id=0x76ab0530, open=True>(port='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_00000000-if00-port0', baudrate=19200, bytesize=8, parity='E', stopbits=1, timeout=1.1, xonxoff=False, rtscts=False, dsrdtr=False)>

MinimalModbus debug mode. Writing to instrument (expecting 1000 bytes back): '\x1e\x03\x03\xeb\x00\x01\xf6\x15' (1E 03 03 EB 00 01 F6 15)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1502978904014.4 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x00\x1e\x03\x02\x00\x02\xacG\x00' (00 1E 03 02 00 02 AC 47 00) (9 bytes), roundtrip time: 1101.7 ms. Timeout setting: 1100.0 ms.

Traceback (most recent call last):
  File "nilan2.py", line 68, in <module>
    old_userVent_value = n.get_userVent()
  File "nilan2.py", line 45, in get_userVent
    return self.read_register(1003, numberOfDecimals=0, signed=False, functioncode=3)
  File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 258, in read_register
    return self._genericCommand(functioncode, registeraddress, numberOfDecimals=numberOfDecimals, signed=signed)
  File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 697, in _genericCommand
    payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
  File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 798, in _performCommand
    payloadFromSlave = _extractPayload(response, self.address, self.mode, functioncode)
  File "/usr/local/lib/python2.7/dist-packages/minimalmodbus.py", line 1075, in _extractPayload
    raise ValueError(text)
ValueError: Checksum error in rtu mode: 'G\x00' instead of '\\\x1b' . The response is: '\x00\x1e\x03\x02\x00\x02\xacG\x00' (plain response: '\x00\x1e\x03\x02\x00\x02\xacG\x00')

First script .py :

#!/usr/bin/env python

#reference https://minimalmodbus.readthedocs.io/en/master/apiminimalmodbus.html#minimalmodbus.Instrument.read_register
import minimalmodbus
import serial

__author__  = "Nick Ma"

class Nilan( minimalmodbus.Instrument ):
    """Instrument class for nilan heat pump.
    communication via RS485
    """

    HOLDINGREG_OFFSET = 10000

    def __init__(self, portname, slaveaddress=30):
        minimalmodbus.Instrument.__init__(self, portname, slaveaddress)

        self.serial.baudrate = 19200
        self.serial.stopbits = 1
        self.serial.bytesize = 8

        self.serial.parity = serial.PARITY_EVEN
        self.serial.timeout = 1.1  #timeout to 1000ms because I discovered roundtrip times as high as 898.5 ms

        self.serial.rtscts = False

        self.mode = minimalmodbus.MODE_RTU
        self.precalculate_read_size = False
        self.FIRST_BYTE_READING = 1
        self.handle_local_echo = False

    def is_manual_loop1(self):
        """Return True if loop1 is in manual mode."""
        return self.read_register(273, 1) > 0


    def get_t11Top(self):
        """Return the setpoint (SP) target for loop1."""
        return self.read_register(211, numberOfDecimals=2,
            signed=True, functioncode=4)

    def get_userVent(self):
        """This is a holding register -> functioncode=3"""
        return self.read_register(1003, numberOfDecimals=0, signed=False, functioncode=3)

    def set_userVent(self, speed=2):
        if (speed<0) or (speed>4):
            return
        return self.write_register(1003, speed)

########################
## Testing the module ##
########################

if __name__ == '__main__':
#    NILAN_SERIAL_PORT = '/dev/ttyUSB0'
    NILAN_SERIAL_PORT = '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_00000000-if00-port0'

    print( 'TESTING Nilan Connection')

    n = Nilan(NILAN_SERIAL_PORT)
    n.debug = True
    print(n)

    ## starting demo
    old_userVent_value = n.get_userVent()
    print( 'old userVentSet:             {0}'.format( old_userVent_value ))

    n.debug = False
    new_designated_userVent = 1 if old_userVent_value==2 else 2
    n.set_userVent(new_designated_userVent)
    print( 'new userVentSet:             {0}'.format( n.get_userVent()       ))

    print( 'Connection to the Nilan instrument looks good!' )

pass

Second script output (with a loop) with multiple response :

16:23:59 08/17/17 CEST

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xd2\x00\x01\x93\x9c' (1E 04 00 D2 00 01 93 9C)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1502979839213.4 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x00\x1e\x04\x02\x0ba\xea' (00 1E 04 02 0B 61 EA) (7 bytes), roundtrip time: 41.7 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xd2\x00\x01\x93\x9c' (1E 04 00 D2 00 01 93 9C)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1003.7 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '*\x00\x00\x1e\x04\x02\x0b' (2A 00 00 1E 04 02 0B) (7 bytes), roundtrip time: 15.6 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xd2\x00\x01\x93\x9c' (1E 04 00 D2 00 01 93 9C)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1006.4 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: 'a\xea*\x00\x00\x1e\x04' (61 EA 2A 00 00 1E 04) (7 bytes), roundtrip time: 16.2 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xd2\x00\x01\x93\x9c' (1E 04 00 D2 00 01 93 9C)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1005.0 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x02\x0ba\xea*\x00\x00' (02 0B 61 EA 2A 00 00) (7 bytes), roundtrip time: 7.0 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xd2\x00\x01\x93\x9c' (1E 04 00 D2 00 01 93 9C)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1004.9 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x1e\x04\x02\x0ba\xea*' (1E 04 02 0B 61 EA 2A) (7 bytes), roundtrip time: 0.4 ms. Timeout setting: 1100.0 ms.

lecture OK
Temp. maison =  29.13

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xcf\x00\x01\x03\x9a' (1E 04 00 CF 00 01 03 9A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 3.9 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x00\x00' (00 00) (2 bytes), roundtrip time: 1101.5 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xcf\x00\x01\x03\x9a' (1E 04 00 CF 00 01 03 9A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1004.0 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x00\x1e\x04\x02\x05\n\xaf' (00 1E 04 02 05 0A AF) (7 bytes), roundtrip time: 15.8 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xcf\x00\x01\x03\x9a' (1E 04 00 CF 00 01 03 9A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1004.9 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\xa5\x00\x00\x1e\x04\x02\x05' (A5 00 00 1E 04 02 05) (7 bytes), roundtrip time: 22.8 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xcf\x00\x01\x03\x9a' (1E 04 00 CF 00 01 03 9A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1006.4 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\n\xaf\xa5\x00\x00\x1e\x04' (0A AF A5 00 00 1E 04) (7 bytes), roundtrip time: 16.6 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xcf\x00\x01\x03\x9a' (1E 04 00 CF 00 01 03 9A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1005.4 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x02\x05\n\xaf\xa5\x00\x00' (02 05 0A AF A5 00 00) (7 bytes), roundtrip time: 16.4 ms. Timeout setting: 1100.0 ms.

exception lecture

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x1e\x04\x00\xcf\x00\x01\x03\x9a' (1E 04 00 CF 00 01 03 9A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1004.6 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '\x1e\x04\x02\x05\t\xef\xa4' (1E 04 02 05 09 EF A4) (7 bytes), roundtrip time: 0.4 ms. Timeout setting: 1100.0 ms.

lecture OK
Temp. air pulsee =  12.89

Second script with multiple answer :

#!/usr/bin/env python
import minimalmodbus
import requests
import time
import sys
import datetime
import random
import traceback

#sys.stdout = open('/home/pi/nilan.log', 'w')
#instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 30) # port name, slave address (in decimal)
#instrument.serial.parity   = minimalmodbus.serial.PARITY_EVEN

#sudo strace -ewrite -p 2222   pour voir le stdout quand il tourne en bg

hum_hist0 = 0
hum_hist1 = 0
flag_hum = 0


def lire_nilan (un, deux, trois, quatre):
    success = 0
    while (success != 1):
        try:
            resultat = instrument.read_register(un, deux, trois, quatre)
            print 'lecture OK'
#            print traceback.format_exc()
            success = 1
        except:
            print 'exception lecture'
#            print traceback.format_exc()
            time.sleep (1)
    return resultat

def ecrire_nilan (un, deux, trois):
    success = 0
    while (success != 1):
            try:
                instrument.write_register(un, deux, trois)
                print 'write OK'
                success = 1
            except:
                print 'exception ecriture'
#                print traceback.format_exc()
                time.sleep (1)
while (1):
    try:

        #instrument = minimalmodbus.Instrument('/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A9O3R1L9-if00-port0', 30) # port name, slave address (in decimal)
        instrument = minimalmodbus.Instrument('/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_00000000-if00-port0', 30) # port name, slave address (in decimal)
        #instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 30)
        instrument.serial.timeout  = 1.1   # seconds
        instrument.serial.parity   = minimalmodbus.serial.PARITY_EVEN
        instrument.CLOSE_PORT_AFTER_EACH_CALL = True
        instrument.debug = True
        print time.strftime('%X %x %Z')



        ## Read temperature (PV = ProcessValue) ##
        temp_maison = lire_nilan(210, 2, 4, True) # Registernumber, number of decimals
        print 'Temp. maison = ', temp_maison
        if temp_maison < 5 :
            os.exit()

        temp_puls = lire_nilan(207, 2, 4, True) # Registernumber, number of decimals
        print 'Temp. air pulsee = ', temp_puls

        ventil_consigne = lire_nilan(1003, 0, 3, True)
        print 'Ventilation 1003 = ', ventil_consigne

#        ecrire_nilan(1003,2,0)

    except:
        print 'Exception'
        print traceback.format_exc()
        sys.exit(0)

Read bit seems to read two bits

I've got an instrument with bits at address 0 and address 1.

When both those registers are 0, then everything is fine. However, if I write a 1 to both address 0 and 1, then I get an error when I try to read either one of the bits.

The error happens in the _bitResponseToValue function; the parsed slave response would read 0x03, which is invalid. If I set address 1 to 0, but address 0 to 1, then I read 0x02.

It seems like the library is reading both address 0 and 1 and reporting back. This error happens when I call instrument.read_bit on a AcuDC 240 meter.

Use time.monotonic (if available) instead of time.time

The time.time function is affected by system clock changes. This means that the silence duration calculation in _communicate can be affected by such system clock changes.

In Python 3.3 the time.monotonic function was added that is not affected by system clock changes and is a better choice for the silence duration calculation.

Cannot change baud rate when extending

Currently the only way to change the baud rate when extending minimalmodbus.Instrument is by doing something like this:

import minimalmodbus
 
class myInstrument(minimalmodbus.Instrument):
    def __init__(self, port, slaveaddress, baudrate):
        minimalmodbus.Instrument.__init__(self, port, slaveaddress)
        self.serial._baudrate=9600

This is not ideal since _baudrate should be protected. Is there a reason baud rate is not a parameter in the constructor?

FC2 Data Address Bug

Below is my debug output.
I believe the request for the data address using FC2 is calculated incorrectly.
I am new to this depth of modbus, but I believe FC2 itself implies a compensation of a +10001 offset of the address parameter given to it.

My FC2 request to the slave d'01', register d'100001' populates a data address of x'27 11' (d 10001).
I believe the request packet should be:
(01 02 00 00 00 01 xx xx)
as compared to
(01 02 27 11 00 01 xx xx)

MinimalModbus debug mode. Writing to instrument (expecting 6 bytes back): "\x01\x02'\x11\x00\x01\xe3{" (01 02 27 11 00 01 E3 7B)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1469204431578.1 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x82\x02\xc1a' (01 82 02 C1 61) (5 bytes), roundtrip time: 50.6 ms. Timeout setting: 50.0 ms.

It is possible I am misunderstanding the protocol, so any input to confirm/deny would be appreciated. This is the information I am using that has led me to this belief:

Read Input Status (FC=02)

Request

This command is requesting the ON/OFF status of discrete inputs # 10197 to 10218
from the slave device with address 17.

11 02 00C4 0016 BAA9

11: The Slave Address (11 hex = address17 )
02: The Function Code 2 (read Input Status)
00C4: The Data Address of the first input to read.
( 00C4 hex = 196 , + 10001 offset = input #10197 )
0016: The total number of coils requested. (16 hex = 22, inputs 197 to 218 )
BAA9: The CRC (cyclic redundancy check) for error checking

[(http://www.simplymodbus.ca/FC02.htm)]

I have been digging through the code to try and find where this information is parsed to see the method used, but this is my first project in Python and I'm having difficulty navigating the rabbit hole to find the source.

Any response is much appreciated,
Thanks!

close_port_after_each_call logic doesn't take exceptions into account

The _communicate function assumes that the serial port is closed if close_port_after_each_call is set and tries to open it. But If it is already open the serial.open call will fail with an exception saying that it is already open.

This situation can be triggered if any unhandled exception occurs between the serial.open call and the serial.close call in the _communicate function. There are several places that can raise such exceptions:

  • the serial.write call can fail with an SerialTimeoutException
  • the local echo logic can raise an IOError
  • I think in my case I also saw the serial.read call fail, even if the pySerial documentation doesn't say it could

Probably the easiest fix is to put all code in the _communicate function between the serial.open call and the serial.close call into a try/finally block and move the serial.close call itself in the finally part of it.

ModBus on Linux Aria Board fails

Hello

When i want to communicate with a device, but i gets only this Errors back (one Byte 0). I checked the Settings they are the same as on the device. what is the problem here?

It is a testing build (Bus is only 10cm long) and the device should answer me because it's was never in use before.
I use a "aria" https://www.acmesystems.it/aria with debain Jessie 8.9 installed

error
modbus

'minimalmodbus' has no attribute 'instrument'

Ran into this firing up interactive mode:

$ python                                                                                            
Python 3.8.1 (default, Jan 22 2020, 06:38:00) 
[GCC 9.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import minimalmodbus
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/thoth/monitaur/daijin-modbus/minimalmodbus.py", line 4, in <module>
    instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1)  # port name, slave address (in decimal)
AttributeError: partially initialized module 'minimalmodbus' has no attribute 'Instrument' (most likely due to a circular import)

possibly my python is too new?

python -V                                                                                                              [8:12:41]
Python 3.8.1

How to write multiple coils

Hi, sorry for the silly question.

Is just that I do not know how to write multiple coils at a time. The provided function (write_bit) throws an error when I try to write a value grater than 1. Forcing the argument functioncode = 15 in the fucntion call doesn't work either. Looking at the source code apparently there is no obvious implementation of this function. What am I missing?

Thanks in advance 👍

No response error from Instrument after several successful readings in Modbus-RTU mode

Hi,

I am trying to read a PV & SP values from a temperature controller by using while true condition in python script, it is running but every time after 5 -6 successful readings I am getting : No response from Instrument error. Please help in resolving this issue.

Log is as follows:

minimalmodbus.Instrument<id=0x76679bb0, address=1, mode=rtu, close_port_after_each_call=False, precalculate_read_size=True, clear_buffers_before_each_transaction=True, handle_local_echo=False, debug=False, serial=Serial<id=0x766bbb50, open=True>(port='/dev/ttyUSB0', baudrate=2400, bytesize=8, parity='E', stopbits=1, timeout=10, xonxoff=False, rtscts=False, dsrdtr=False)>
78

~~ 2020-09-01, 09:03:40 ~~
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 30030.19 ms, minimum silent period: 16.04 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00\x00¸D' (01 03 02 00 00 B8 44) (7 bytes), roundtrip time: 76.4 ms. Timeout for reading: 10000.0 ms.

MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x01\x00\x01ÕÊ' (01 03 00 01 00 01 D5 CA)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. Sleeping 12.48 ms before sending. Minimum silent period: 16.04 ms, time since read: 3.56 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00N8p' (01 03 02 00 4E 38 70) (7 bytes), roundtrip time: 127.3 ms. Timeout for reading: 10000.0 ms.


~~ 2020-09-01, 09:04:10 ~~
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 30034.68 ms, minimum silent period: 16.04 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00\x00¸D' (01 03 02 00 00 B8 44) (7 bytes), roundtrip time: 73.0 ms. Timeout for reading: 10000.0 ms.

MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x01\x00\x01ÕÊ' (01 03 00 01 00 01 D5 CA)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. Sleeping 12.45 ms before sending. Minimum silent period: 16.04 ms, time since read: 3.60 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00N8p' (01 03 02 00 4E 38 70) (7 bytes), roundtrip time: 125.9 ms. Timeout for reading: 10000.0 ms.


~~ 2020-09-01, 09:04:40 ~~
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 30034.79 ms, minimum silent period: 16.04 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00\x00¸D' (01 03 02 00 00 B8 44) (7 bytes), roundtrip time: 86.8 ms. Timeout for reading: 10000.0 ms.

MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x01\x00\x01ÕÊ' (01 03 00 01 00 01 D5 CA)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. Sleeping 12.44 ms before sending. Minimum silent period: 16.04 ms, time since read: 3.60 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00N8p' (01 03 02 00 4E 38 70) (7 bytes), roundtrip time: 110.8 ms. Timeout for reading: 10000.0 ms.


~~ 2020-09-01, 09:05:10 ~~
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 30035.23 ms, minimum silent period: 16.04 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00\x00¸D' (01 03 02 00 00 B8 44) (7 bytes), roundtrip time: 85.5 ms. Timeout for reading: 10000.0 ms.

MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x01\x00\x01ÕÊ' (01 03 00 01 00 01 D5 CA)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. Sleeping 12.46 ms before sending. Minimum silent period: 16.04 ms, time since read: 3.58 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00N8p' (01 03 02 00 4E 38 70) (7 bytes), roundtrip time: 107.0 ms. Timeout for reading: 10000.0 ms.


~~ 2020-09-01, 09:05:41 ~~
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. Clearing serial buffers for port /dev/ttyUSB0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 30034.18 ms, minimum silent period: 16.04 ms.
MinimalModbus debug mode. Response from instrument: '' () (0 bytes), roundtrip time: 10010.4 ms. Timeout for reading: 10000.0 ms.

Traceback (most recent call last):
File "logger_csv.py", line 73, in
main()
File "logger_csv.py", line 65, in main
logger.collect_data()
File "logger_csv.py", line 35, in collect_data
pv = instrument.read_register(0,0)
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 447, in read_register
payloadformat=_PAYLOADFORMAT_REGISTER,
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1170, in _generic_command
payload_from_slave = self._perform_command(functioncode, payload_to_slave)
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1240, in _perform_command
response = self._communicate(request, number_of_bytes_to_read)
File "/usr/local/lib/python3.7/dist-packages/minimalmodbus.py", line 1406, in _communicate
raise NoResponseError("No communication with the instrument (no answer)")
minimalmodbus.NoResponseError: No communication with the instrument (no answer)

Limit t3.5 at 1750µs

Hi,

I’m looking into minimalmodbus Python library to test a slave I'm implementing on a SAML21 µC. I like it, however I found something you might want to consider.

In the timing section of the docs you have a table with the 3.5 character time which includes the baud rates 38400 (1.0ms) and 115200 (0.33 ms).

However, the MODBUS over the serial line specification V1.02 states at page 13:

“The implementation of RTU reception driver may imply the management of a lot of interruptions due to the t1.5 and t3.5 timers. With high communication baud rates, this leads to a heavy CPU load. Consequently these two timers must be strictly respected when the baud rate is equal or lower than 19200 Bps. For baud rates greater than 19200 Bps, fixed values for the 2 timers should be used: it is recommended to use a value of 750μs for the inter-character time-out (t1.5) and a value of 1.750ms for inter-frame delay (t3.5).”

Slave devices implementing the t1.5 and t3.5 like suggested in the spec might have problems if the master is using the timeouts from your table. I think minimalmodbus should also limit the t3.5 time-out at 1.75 ms for baud-rates higher than 19200.

Best regards,
Draghi

The slave is indicating an error

Hello, I have electricity meter Schneider iem 3155 (http://www.schneider-electric.com/en/product-range/61273-acti-9-iem3000-series/)

I'm loading without any problem using your library registers: 3204, 3208, 3220, 3224, 3000, 3002, 3004, 3010

But now I need run command number 2008, action = write, size = 1, type = Uint16, possible values = 1-4

When I use
instrument.write_long(2008, 1)

I get back
ValueError: The slave is indicating an error. The response is: '\x02\x90\x04\xbd\xc3'

I use python 2.7

Shneider support told me set on e. meter Com. Protection like disabled, I did, and no change.
You're my last resort. Some idea?

Communication work with v0.7 but not with v1.0.2

This is my code:

minimalmodbus.BAUDRATE = 9600
minimalmodbus.PARITY = serial.PARITY_EVEN
minimalmodbus.BYTESIZE = 8
minimalmodbus.STOPBITS = 1
minimalmodbus.TIMEOUT = 1
self.instrument = minimalmodbus.Instrument(port,slaveaddress,mode='rtu')        
self.instrument.debug = True
self.instrument.read_float(address)

Output from version 0.7:

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x01\x03\x00\x04\x00\x01\xc5\xcb' (01 03 00 04 00 01 C5 CB)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1594126730633.0 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00\x00\xb8D' (01 03 02 00 00 B8 44) (7 bytes), roundtrip time: 29.0 ms. Timeout setting: 1000.0 ms.
MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. Sleeping for 3.0 ms. Minimum silent period: 4.0 ms, time since read: 1.0 ms.
MinimalModbus debug mode. Response from instrument: '\x01\x03\x02\x00\xdb\xf8\x1f' (01 03 02 00 DB F8 1F) (7 bytes), roundtrip time: 30.0 ms. Timeout setting: 1000.0 ms.
Temperature 21.9 Centigrade

And with version 1.0.2:

MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): '\x01\x03\x00\x04\x00\x01\xc5\xcb' (01 03 00 04 00 01 C5 CB)
MinimalModbus debug mode. Clearing serial buffers for port COM4
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1594126681759.00 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: '' () (0 bytes), roundtrip time: 60.0 ms. Timeout for reading: 50.0 ms.

Test with python 3.6 and 2.7 on Windows 10 x64 with USB-RS485-WE-1800-BT. Buffer are the same (01 03 00 04 00 01 C5 CB)

Control signals

Hi,
In minimalmodbus I want to understand how the control lines are handled for MODBUS-RTU. In the example applications I couldn't see anything relevant to this. Any help is appreciated.
I want to use minimalmodbus on Linkit7688 with OpenWRT. In my system I have connected the Rx and TX to UART1. I have connected RE and DI control pins to GPIO 4,5. My slave device is running Arduino UNO. I have connected the two with MAXIM RS485 (half duplex)connector.

Negative temperatures when reading from Eurotherm3508

Morning.

I was using the eurotherm3500.py over the weekend to record temperatures from our oven as it was running an experiment.

Noticed in the logged data that negative numbers did not look like they were being converted correctly to a signed integer. For example the value -0.1 was being recorded as 6553.5

I added a small kludge to my code which sorted everything out:

def eurotherm_sanitize_temp(temp):
    raw = int(temp*10)
    if raw > 32767:
        temp = -0.1*float(65536 - raw)
    return temp

Hope this note is of some use to you. You saved me a tonne of work by making this code available, so many thanks!

Feature request: custom minimum silent period.

My instrument does not respond reliably unless i add a tiny sleep before I read from a register. It would be awesome if it would be possible to configure the minimum silent period (e.g. to 4chars instead of 3.5).

Not getting response from a system I am trying to use Minimal Modbus to talk to

print instrument.read_register(0, 1)

MinimalModbus debug mode. Writing to instrument (expecting 7 bytes back): '\x01\x03\x00\x00\x00\x01\x84\n' (01 03 00 00 00 01 84 0A)
MinimalModbus debug mode. No sleep required before write. Time since previous read: 1310283.0 ms, minimum silent period: 8.02 ms.
MinimalModbus debug mode. Response from instrument: '' () (0 bytes), roundtrip time: 51.0 ms. Timeout setting: 50.0 ms.

Traceback (most recent call last):
File "", line 1, in
File "minimalmodbus.py", line 258, in read_register
return self._genericCommand(functioncode, registeraddress, numberOfDecimals=numberOfDecimals, signed=signed)
File "minimalmodbus.py", line 697, in _genericCommand
payloadFromSlave = self._performCommand(functioncode, payloadToSlave)
File "minimalmodbus.py", line 795, in _performCommand
response = self._communicate(request, number_of_bytes_to_read)
File "minimalmodbus.py", line 930, in _communicate
raise IOError('No communication with the instrument (no answer)')
IOError: No communication with the instrument (no answer)

Issue in subsequent read of 2 registers

When I read a register for e.g. 201, due to physical wire error, am doing it in for loop for 4 times.

Now when I read next register, e.g. 209; again using a for loop for 4 times. What happens is the readings for register 201 are read while 209 also, for the first time only, when subsequent for loops execute, I get the new reading.
But for first time, it definitely reads the last value only. I tried with numerous trials but it appears the same way.

below is a snippet


for x in range(0,4):
          try:
               print('reading Solar Kvarh')
               pfc3 = meter.read_registers(209,6,3)
               pf1 = pfc3[0]
               pf2 = pfc3[1]
               solar_kvarh = unpack('<f',pack('<HH',pf1,pf2))[0]
               solar_kvarh = round(solar_kvarh,4)
               print 'Solar kvarh = ',solar_kvarh
          except IOError:
               print("Failed to read from instrument")
          except ValueError:
               print("value error")
          time.sleep(2)
     print("*************************************************************************************\n")
     for x in range(0,4):
          try:
               print('reading Solar Kvah')
               pfc4 = meter.read_registers(217,6,3)
               pf1 = pfc4[0]
               pf2 = pfc4[1]
               solar_kvah = unpack('<f',pack('<HH',pf1,pf2))[0]
               solar_kvah = round(solar_kvah,4)
               print 'Solar kvah = ',solar_kvah
          except IOError:
               print("Failed to read from instrument")
          except ValueError:
               print("value error")
          time.sleep(2)

first time, the KVAH reads the same value as that of KVARH in above code
from next read, it comes back to reading the expected reading

Would it be possible to handle Modbus TCP ?

Hi,

I know Modbus TCP is not supported by minimalmodbus.

I am already using minimalmodbus with the RTU protocol and it is working fine.
I would like to use Modbus TCP for another instrument but as minimalmodbus does not support it, it means I need to use another lib or modify minimalmodbus to make it work with TCP.

Have you tried to handle Modbus TCP ? If no, why ?
Do you think it would be hard to modify minimalmodbus to handle it ?

read the bit status of internal relay of plc

Hello! I have Fatek PLC FBs-32MN and need to get bit status of internal relay.
I try to use read_bit() with function code = 2, it's return error(wrong adress).

Which function should i use? and which function code?

here some doc with memory allocation of this PLC:
doc

P.S. i try to read registers and output relays and its works

Changing byte order in CRC checksum

I am currently working with a device that is using modbus as a base for its own protocol with own function codes. Also, they changed the order of bytes in the CRC checksum.
I saw that the function
def _num_to_twobyte_string(value, number_of_decimals=0, lsb_first=False, signed=False)
has the option to switch the bytes. From my understanding the function
def _calculate_crc_string(inputstring):
is used to create and check all CRC checksums. Here it is hardcoded that the LSB is send first.
return _num_to_twobyte_string(register, lsb_first=True)

Is there an option how I can quickly jump between "CRC-LSB first" and "CRC-HSB first" when using devices that use both the switched and the normal CRC checksum on the same bus?

Package puts some inappropriate modules into root namespace

Hi!
Thank you for this package, and especially the very detailed documentation!

One surprising thing that I found is that this package puts dummy_serial, eurotherm3500 and omegacn7500 modules into the "root" namespace of installed python packages. I found this weird and surprising/unexpected. Let me show you:

Jupyter QtConsole 4.3.0
Python 3.6.2 |Anaconda custom (64-bit)| (default, Jul 20 2017, 12:30:02) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

import numpy as np  # as expected

np
Out[2]: <module 'numpy' from 'C:\\Continuum\\Anaconda3\\lib\\site-packages\\numpy\\__init__.py'>

import minimalmodbus  # as expected

minimalmodbus
Out[4]: <module 'minimalmodbus' from 'C:\\Continuum\\Anaconda3\\lib\\site-packages\\minimalmodbus.py'>

import eurotherm3500

# What did I just import? What is this?

eurotherm3500
Out[7]: <module 'eurotherm3500' from 'C:\\Continuum\\Anaconda3\\lib\\site-packages\\eurotherm3500.py'>

# hmm, no idea from which package that came from...

import dummy_serial

dummy_serial
Out[10]: <module 'dummy_serial' from 'C:\\Continuum\\Anaconda3\\lib\\site-packages\\dummy_serial.py'>

#same deal here

minimalmodbus.__version__  # for completeness
Out[12]: '0.7'

I think it would be preferable to have these obviously minimalmodbus-related modules remain within the minimalmodbus namespace, by refactoring into a package and adding these as modules. I think even the normal usage API can be preserved by some from minimalmodbus import * or similar within the __init__py.

Read and write flag registers

Hi. I want to use MinimalModbus to control some fan coil unit. According to the manufacturer manual, there are integer registers, decimal registers and also flags register, composed by more boolean value. How can I read and write that registers? I have to read the registers as simple integer, and then parse to binary to get the flags, and vice versa to write? Thanks

Package dummy_serial.py again

Hi,

For running tests/, it would be useful to repackage dummy_serial.py again in the .tar.gz file for pypi, as was done back in 0.7. This would make it easier to run tests from the OpenBSD ports frameworks (using it there with an SDM630 and an Eurotherm TE200A).

Thanks!
-m

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.