ljean / modbus-tk

Create Modbus app easily with Python
Other
566 stars 212 forks source link

Modbus RTU controlling DIR pin #132

Open krupis opened 3 years ago

krupis commented 3 years ago

Hello. I am new to this library and Modbus in general. I want to set up my Raspberry PI device as a master and send various commands to ESP32 devices. I have slave code running on my ESP32 devices already and confirmed that is working properly.

I have connected raspberry PI GPIO14(TX) and GPIO15(RX) as well as Direction pin to GPIO23 to my signal analizer and Im trying to test whether its working as expected. When I can confrim that its working, I will then connect the RS485 driver and try to communicate with my slave devices.

I am using this code for testing:


#!/usr/bin/env python
# -*- coding: utf_8 -*-
"""
 Modbus TestKit: Implementation of Modbus protocol in python
 (C)2009 - Luc Jean - luc.jean@gmail.com
 (C)2009 - Apidev - http://www.apidev.fr
 This is distributed under GNU LGPL license, see license.txt

import serial

import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu

PORT = '/dev/serial0'
#PORT = '/dev/ttyp5'

def main():
    """main"""
    logger = modbus_tk.utils.create_logger("console")
    try:
        #Connect to the slave
        master = modbus_rtu.RtuMaster(
            serial.Serial(port=PORT, baudrate=9600, bytesize=8, parity='N', stopbits=1, xonxoff=0)
        )
        master.set_timeout(5.0)
        master.set_verbose(True)
        logger.info("connected")

       logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 10, output_value=99))

        #send some queries
        #logger.info(master.execute(1, cst.READ_COILS, 0, 10))
        #logger.info(master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 8))
        #logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 100, 3))
        #logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 100, 12))
        #logger.info(master.execute(1, cst.WRITE_SINGLE_COIL, 7, output_value=1))
        #logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 100, output_value=54))
        #logger.info(master.execute(1, cst.WRITE_MULTIPLE_COILS, 0, output_value=[1, 1, 0, 1, 1, 0, 1, 1]))
        #logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 100, output_value=xrange(12)))

    except modbus_tk.modbus.ModbusError as exc:
        logger.error("%s- Code=%d", exc, exc.get_exception_code())

if __name__ == "__main__":
    main()

As you can see from the code below, I am trying to write value 99 to register offset 10

Initially I had a lot of problems with the serial port. I could not figure out what serial port I have to use, i have tried the following: '/dev/ttyS0' and '/dev/ttyAMA0' both with bad results.

Then somoene suggested me to use '/dev/serial0' and that worked fine! I could finally see the data that I am trying to send on my logic analyzer

The main concern with this example code I have is how do I control the direction pin of my raspbery PI? When I write data i need to toggle it HIGH, when I read it has to be LOW

Can someone clarify to me how exactly I need to control it?

DmitrySidorow commented 3 years ago

Use RPI.GPIO library. Set HIGH before self._serial.write(response) and set LOW after self._serial.flush() https://github.com/ljean/modbus-tk/blob/14c70f2c3c794b7e2944762f408b98e7bc77a8fe/modbus_tk/modbus_rtu.py#L299

In my case, it works

DmitrySidorow commented 3 years ago

If you have already found your solution, could you please share it too ☺️

krupis commented 3 years ago

If you have already found your solution, could you please share it too ☺️

I have quit the idea of controlling the DIR pin on raspberry as this is not a common thing to do. There are 2 solutions to avoid controlling DIR pin:

  1. I would advise you to look at automatic DIR control circuitry such as : image

  2. Use USB to modbus converter which does not require you to control dir pin. It is being controlled internally such as:

image

As you can see there is no DIR pin. Just RX and TX, which for my application was all I needed.