no communication with the instrument (no answer) Minimalmodbus - python

I'm having problem with minimalmodbus library. The slave does not respond to the master's request, I want to request a read. I'm using the Raspberry Pi 3 Model B+, with Python 3.10.1, it's the minimalmodbus library with version 2.0. I'm using the Arduino Mega as a slave and I'm also using a Mini Adapter Serial Converter USB to RS485 is a Converter Module RS485 for Arduino.
import serial
import minimalmodbus
instrument = minimalmodbus.Instrument('COM6',1)
instrument.serial.baudrate = 9600
instrument.serial.timeout = 10
instrument.clear_buffers_before_each_transaction = True
instrument.debug = True
temperature = instrument.read_register(1,1)
print(temperature)
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 03 00 01 00 01 D5 CA (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port COM6
MinimalModbus debug mode. No sleep required before write. Time since previous read: 87898406.00 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Response from instrument: (0 bytes), roundtrip time:10.0 ms. Timeout for reading: 0 ms.

I have a similar issue on Win10 python 3.7.9. When I write
import minimalmodbus
instrument = minimalmodbus.Instrument('COM3', 2)
instrument.serial.baudrate = 9600
instrument.clear_buffers_before_each_transaction = True
reg_0 = instrument.read_register(0, 0)
reg_1 = instrument.read_register(1, 0)
print(reg_0)
print(reg_1)
instrument.serial.close()
I have error message "minimalmodbus.NoResponseError: No communication with the instrument (no answer)". But, when I write
import minimalmodbus
instrument = minimalmodbus.Instrument('COM3', 2)
instrument.serial.baudrate = 9600
instrument.clear_buffers_before_each_transaction = True
instrument.debug = True
reg_0 = instrument.read_register(0, 0)
reg_1 = instrument.read_register(1, 0)
print(reg_0)
print(reg_1)
instrument.serial.close()
all works correct.
I use Arduino UNO as a slave. In ModbusPoll both registrers read correct
Upd. When I use construction "try... except..." all works correctly
import minimalmodbus
instrument = minimalmodbus.Instrument('COM3', 2)
instrument.serial.baudrate = 9600
instrument.clear_buffers_before_each_transaction = True
try:
reg_0 = instrument.read_register(0, 0)
except minimalmodbus.NoResponseError:
reg_0 = instrument.read_register(0, 0)
reg_1 = instrument.read_register(1, 0)
print(reg_0)
print(reg_1)
instrument.serial.close()

Related

Raspberry: USB to RS232 (FT4232H chip) can't communicate with Device via Python

I want to set up my serial connection to a pump with a USB to 4xRS232 (FT4232H chip). However, my serial connection can't write output from the pump. The whole setup works with a single usb to rs232 converter but not with my USB to 4xRS232 converter. My raspberry recognizes all 4 USB ports:
/dev/ttyAMA0: ttyAMA0 [fe201000.serial]
/dev/ttyUSB1: FT4232H Device
/dev/ttyUSB2: FT4232H Device
/dev/ttyUSB3: FT4232H Device
/dev/ttyUSB4: FT4232H Device
My code to write and read information with my external device looks as following:
import serial
import time
global ser
ser = serial.Serial()
ser.port = '/dev/ttyUSB1'
#ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS
ser.parity = serial.PARITY_NONE
ser.stopbits = serial.STOPBITS_ONE
ser.open()
encoding='utf-8'
def pump_loop():
if ser.inWaiting() == 0:
out_press=''
ser.write(b'PRESSURE?\r')
time.sleep(.1)
#print(ser.in_waiting)
#print(ser.read())
while int(ser.in_waiting) > 0:
out_press += str(ser.read(1), encoding)
print(out_press)
pump_loop()
Edit: Cable set-up is the following: raspberry-usb--> FT4232H --> 4 RS232 --> female-to-female coupling --> pump
Closed: had to swap PIN 2 and 3 before using the female-female coupler, as they are swapped inside.

Python minimalmodbus, how to read MODBUS RTU

Sorry for my bad English.
I am trying to read data by the Modbus RTU method (library: minimalmodbus) but have a problem.
This is my 'Modbus Poll' display.
I would like to read data by using minimalmodbus.
import minimalmodbus
import serial
instrument = minimalmodbus.Instrument('COM5', 1) # port name, slave address (in decimal)
instrument.serial.port = 'COM5' # this is the serial port name
instrument.serial.baudrate = 9600 # Baud
instrument.serial.bytesize = 8
instrument.serial.parity = serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout = 0.1 # seconds
instrument.address = 1 # this is the slave address number
instrument.mode = minimalmodbus.MODE_RTU # rtu or ascii mode
result = instrument.read_float(0, 4, 20)
print(result)
But, I keep failing.
Can please someone help me with how to read data?

MCP4728 on RP4 with Python

I am trying to use MCP4728 DAC with RP4.
I can’t get it to work.
Connection map:
RP4 1 (3.3V) to 1 at 4728.
RP4 6 (GND) to 10 at 4728.
RP4 3 (SDA) to 3 at 4728.
RP4 5 (SCL) to 2 at 4728.
GND to 4 at 4728.
Tried using this code:
import board
import busio
import adafruit_mcp4728
i2c = busio.I2C(board.SCL, board.SDA)
mcp4728 = adafruit_mcp4728.MCP4728(i2c)
with an error: No I2C device at address: 0x60
Tried using this code:
from smbus import SMBus
bus = SMBus(1) #indicates /dev/i2c-1
addr = 0x60
bus.write_byte(addr, 0x50)
with an error: [Errno 121] Remote I/O error
Any ideas ?
Thank you.
This worked for me.
# write to MCP4728
#for the first channel
command = 0x58
addr = 0x61 #bus address
bus = SMBus(1) #indicates /dev/i2c-1
bus.write_i2c_block_data(addr,command,[value_msb,value_lsb])

How to read data into Raspberry Pi using modbus-tk?

So I'm doing a project where I want my Raspberry Pi 4 to communicate through Modbus. I've bought a shield to enable RS485 communication from the Pi and I've been modifying the demo code (Software/Test Codes/MODBUS/rtumaster.py) and have been using a slave simulator on my computer to test.
I'm reaching out because I've gotten stuck on trying to read data from my slave. The command seems to go through okay (or the slave simulator doesn't complain is perhaps better to say), but I don't know how to get the data into my program. I've been trying something like this:
read = logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 5, 1))
And then trying to print that value to check, but it just returns 'None' instead of my value.
Any help is appreciated.
Current code:
## To install dependencies:
## sudo pip3 install modbus-tk
##################################################################################################
import serial
import fcntl
import os
import struct
import termios
import array
#import modbus lib
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus as modbus
#import modbus_tk.modbus_rtu as modbus_rtu
from modbus_tk import modbus_rtu
# RS485 ioctls define
TIOCGRS485 = 0x542E
TIOCSRS485 = 0x542F
SER_RS485_ENABLED = 0b00000001
SER_RS485_RTS_ON_SEND = 0b00000010
SER_RS485_RTS_AFTER_SEND = 0b00000100
SER_RS485_RX_DURING_TX = 0b00010000
# rs 485 port
ser1 = serial.Serial("/dev/ttySC0",19200)
ser2 = serial.Serial("/dev/ttySC1",9600)
def rs485_enable():
buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
#enable 485 chanel 1
fcntl.ioctl(ser1, TIOCGRS485, buf)
buf[0] |= SER_RS485_ENABLED|SER_RS485_RTS_AFTER_SEND
buf[1] = 0
buf[2] = 0
fcntl.ioctl(ser1, TIOCSRS485, buf)
#enable 485 chanel 2
fcntl.ioctl(ser2, TIOCGRS485, buf)
buf[0] |= SER_RS485_ENABLED|SER_RS485_RTS_AFTER_SEND
buf[1] = 0
buf[2] = 0
fcntl.ioctl(ser2, TIOCSRS485, buf)
#end of rs485_enable():
if __name__ == '__main__':
logger = modbus_tk.utils.create_logger("console")
rs485_enable()
#set modbus master
master = modbus_rtu.RtuMaster(
serial.Serial(port= '/dev/ttySC0',
baudrate=9600,
bytesize=8,
parity='N',
stopbits=1,
xonxoff=0)
)
master.set_timeout(5.0)
master.set_verbose(True)
logger.info("connected")
read = logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 5, 1))
print("Value is: ", read)

Pymodbus : Wrong byte count in response

We are requesting 14 responses from an RS485 device and sometimes the reply that we got doesn't have the 9 bytes that it is set-up. That is because it's replying sometimes in 3 arguments.
Normal:
CALL-> 01 04 00 00 00 02 71 CB
RESPONSE-> 01 04 04 43 59 E6 66 F4 59
Error:
CALL-> 01 04 00 00 00 02 71 CB
RESPONSE -> 01 04 04 43
59 CC CD AA 86
When the error happens i get this msg from pymodbus:
DEBUG:pymodbus.transaction: Incomplete message received, Expected 9 bytes Recieved 4 bytes !!!!
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x1 0x4 0x4 0x3e
DEBUG:pymodbus.framer.rtu_framer:Frame check failed, ignoring!!
DEBUG:pymodbus.framer.rtu_framer:Resetting frame - Current Frame in buffer - 0x1 0x4 0x4 0x3e
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
i've tried putting a sleep into the for so it dosn't colapse the device with calls but i get them either way. i've also read https://wingpath.co.uk/docs/modtest/troubleshoot.html
and they say this:
"Wrong byte count in response: XXX when expecting XXX"
The byte count in the response sent by the slave is not what was expected for the count that ModTest sent in the request.
Turn on tracing to get more information.
Check that your slave is functioning correctly.
If you want ModTest to accept the response even though it is incorrect, you could deselect Strict Checking.
But i don't know how to active tracing on PYMODBUS, the function is correct and the other one is for a lib that i am not using i think
THE CODE LOOKS LIKE THIS
from __future__ import division
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
from time import sleep
from pymodbus.constants import Endian # Nodig voor 32-bit float getallen (2 registers / 4 bytes)
from pymodbus.payload import BinaryPayloadDecoder # Nodig voor 32-bit float getallen (2 registers / 4 bytes)
from pymodbus.payload import BinaryPayloadBuilder # Nodig om 32-bit floats te schrijven naar register
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
#
method = "rtu"
port = "COM1"
baudrate = 2400
stopbits = 1
bytesize = 8
parity = "N"
timeout = 10 # I SET THIS TO 10 MAYBE IT WOULD HELP BUT DIDN'T
retries = 5 # SAME THING WITH THIS ONE
#
try:
client = ModbusClient(method = method, port = port, stopbits = stopbits, bytesize = bytesize, parity = parity, baudrate = baudrate, timeout = timeout, retries = retries)
connection = client.connect()
print (connection)
except:
print ("Modbus connectie error")
#
def 420 (y):
variables = [0,6,12,18,24,30,36,70,72,74,76,78,342,344]
labels = ["Voltage","Corriente","Potencia_Activa","Potencia_Aparente","Potencia_Reactiva","Factor_Potencia","Angulo_Fase","Frecuencia","Potencial_Activa_Consumida","Potencia_Activa_Inyectada","Potencia_Reactiva_Consumida","Potencia_Reactiva_Inyectada","Energia_Activa_Total","Energia_Reactiva_Total"]
unidades = ["V","A","W","VA","VAr","%","Grados","HZ","kWh","kWh","kVArh","kVArh","kWh","kVArh"]
LISTA = []
h = 0
hh = 0
for xx in variables:
try:
data = client.read_input_registers(xx, 2, unit=1)
decoder = BinaryPayloadDecoder.fromRegisters(data.registers, Endian.Big)
eastron = round(decoder.decode_32bit_float(), 3)
weaito = str(labels[h]) + " = " + str(eastron) + " " + str(unidades[hh])
LISTA.append(weaito)
h = h + 1
hh = hh + 1
sleep(0.5)
except:
print ("PICO")
sleep(1)
print(LISTA)
I Would love a way around the problem, maybe just consulting again until i get the right answer. I am not good with the try and except ones maybe there is the answer.
You seem to be experiencing a known issue with interchar spacing.
There is an easy workaround though. First, make sure you're on pymodbus version 2.2.0 (you can do that opening a command line terminal on Windows and typing pip list if you have the path setup correctly, otherwise you have to move to your scripts Python folder where pip.exe is stored).
Then change your code to add the strict argument declared to False:
....
client = ModbusClient(method = method, port = port, stopbits = stopbits, bytesize = bytesize, parity = parity, baudrate = baudrate, timeout = timeout, retries = retries)
client.strict = False #Use Modbus interchar spacing as timeout to prevent missing data for low baudrates
connection = client.connect()
...
This will define the character spacing according to the Modbus spec, to 1.5 times the bit time at the selected baudrate, instead of using the default from socket.interCharTimeout:
self._t0 = float((1 + 8 + 2)) / self.baudrate
self.inter_char_timeout = 1.5 * self._t0
If you can fix your issue with this solution, you should be able to reduce the overhead on your device reading the 28 registers you want in one go.
If your issue is not solved, I think you might have a hardware issue. I would advise you to put your code aside for a while and try reading registers with QModMaster or something similar to make sure your hardware is performing as intended. (you might be getting noise or grounding issues that cut your frames short, if you want some pointers on that front please edit your question to include more details on your hardware, i.e.: kind of devices and how you're connecting them).

Categories