nanoframework / Home

:house: The landing page for .NET nanoFramework repositories.
https://www.nanoframework.net
MIT License
861 stars 79 forks source link

Modbus library does not work with RS232 #1473

Closed JohnMasen closed 5 months ago

JohnMasen commented 5 months ago

Library/API/IoT binding

nanoFramework.IoT.Device.ModBus

Visual Studio version

VS2022

.NET nanoFramework extension version

2022.3.0.78

Target name(s)

No response

Firmware version

No response

Device capabilities

No response

Description

please do not change the serial port mode to RS485 ( _serialPort.Mode = SerialMode.RS485;), this blocks ModBUS over RS232 application. as the serial port was created by user, suggest do not change the options as it was intentional set to their value.

How to reproduce

Using this library on a modbus over RS232 does not work. I have to remove _serialPort.Mode = SerialMode.RS485; to make it back to work.

public Port(SerialPort port, int receivedBytesThreshold = 1)
        {
            _serialPort = port;
            _serialPort.Mode = SerialMode.RS485;

            if (receivedBytesThreshold != 1)
            {
                _serialPort.ReceivedBytesThreshold = receivedBytesThreshold;
            }
        }

Expected behaviour

No response

Screenshots

No response

Sample project or code

No response

Aditional information

No response

josesimoes commented 5 months ago

Clarification please: is this your code or code from one of our libraries?

JohnMasen commented 5 months ago

Hi josesimoes, Yes, the referenced code is from https://github.com/nanoframework/nanoFramework.IoT.Device/blob/develop/devices/Modbus/Port.cs

networkfusion commented 5 months ago

Modbus is not designed for RS232, given it is a point to point standard, where as Modbus is a multidrop bus standard. So by design out of the box, setting it to RS485 is correct.

JohnMasen commented 5 months ago

Hi networkfusion, Modbus is an application layer protocol, RS232 is physical interface. There's a large number of devices using Modbus Over Serial in the market, and according to [MODBUS over Serial Line], RS232 is a supported interface for ModBus:

"A new MODBUS solution over serial line should implement an electrical interface in accordance with EIA/TIA-485 standard ( also known as RS485 standard). This standard allows point to point and multipoint systems, in a “two-wire configuration”. In addition, some devices may implement a “Four-Wire” RS485-Interface. A device may also implement an RS232-Interface. "

image

josesimoes commented 5 months ago

@JohnMasen you are the 1st developer to report this issue. So far it's working for other users (including my company working with this library). This can be easily accomodated: add a new Port() constructor with Mode parameter. It won't break anything for existing applications and exposes this config for others that need to set it. We love PRs, so feel free to go ahead with this.

JohnMasen commented 5 months ago

@josesimoes Thanks for your advise, I'm working this, will PR it when the tests done.

JohnMasen commented 5 months ago

@josesimoes I found the Modbus library has another bug while testing my modifications. Issue description:Instead of wait a certain time, the library will do a dummy read as sleep function Here's a demo chart shows 2 different cases.

--  -- <-3.5 char timing -> <-- Data Frame -->
Case1 SendData Read dummy byte( use dummy read as sleep function) Read data  
Case2 SendData CPU work on other thread Read dummy byte( 1st byte was skpped) Read data

In case 2, the first byte was skipped. This happends when my device is running a web server as background service. It could also happends on multi-threaded application or low performance CPU device.

I fixed the issue by replacing the dummy read with timing check, but still needs more test to verify.

Question: Shall I create a new issue for this or we re-use this issue?

networkfusion commented 5 months ago

@JohnMasen feel free to reword the title of the issue and add PR's with the link back to this issue as you see fit (keeping each PR autonomous).

josesimoes commented 5 months ago

That would be a separate issue, please, as it's unrelated. Curious on how you're doing that timming, because the wait is really short...

JohnMasen commented 5 months ago

On 9600 transfer rate, each bit =1000/9600 (ms), 3.5 char=8(bit) 3.5=28 bits So total delay is 1000 / 9600 8 * 3.5 = 2.91667ms , I simply check if the time is 3ms after the send(use thread.sleep if not met the gap). Ideally it should be auto calculated by transfer rate, but this causes too many file changes. as 9600 is the slowest transfer rate, wait 3 ms should always be enough.

josesimoes commented 5 months ago

@JohnMasen care to raise that other issue so all the conversation about it can happen there? Otherwise it harms discoverability and gets confusing.

JohnMasen commented 5 months ago

No problem, I'll create another issue about this. I'll do this tonight.

JohnMasen commented 5 months ago

Issue #1476 created.

JohnMasen commented 5 months ago

As #1476 may cause communcation issue in multi-threaded RS232 scenario. I'll create a hot fix in following PR and do more investiation on this.