Author Topic: direct logic 05 and ModbusRTU com driver  (Read 22114 times)

fohdeesha

  • Newbie
  • *
  • Posts: 46
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #15 on: August 23, 2014, 06:25:35 AM »
So I just tested v3.6.6, and everything is working perfectly!

I can now read and write everything without issue. I can read single coils and write them with no problem. Thanks so much for working on this so quickly! AdvancedHMI just became compatible with a LOT more PLC's : )

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #16 on: August 23, 2014, 06:41:21 AM »
Thanks for the testing and feedback. The ModbusRTU driver sat unfinished for over a year because it was not easy for me to test. I finally decided to release it "as is" in hopes of getting feedback so I could get it finished up. Appreciate the help and patience in getting it finished. The next unfinished driver I hope to get completed soon is for all the Omron PLCs.

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #17 on: August 23, 2014, 08:09:19 AM »
Dear Archie Pleas Have a look to the attached File
thanks

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #18 on: August 23, 2014, 08:31:10 AM »
Dear fohdeesha  try to write single register (function 6) it will not work not fixed yet you will have always the value 1 written into register

I mentioned how I solved this point  in my previews reply
 
also try to use more than eight coil registers in series  let us  say 24 coil registers in series (10001 -10024)  it will not work because of the bug I just mentioned

for me with the Points I posted the code now it is working great for

function (0x01) Read  Coils   
function (0x02) Read  Discrete Inputs
function (0x03) Read  Holding register
function (0x04) Read  Input register
function (0x05) Write Single Coil
function (0x06) Write Single Register


still have to test the rest of the Modbus RTU functions which are  the

Write Multiple Coils (0x0f)
Write Multiple Registers (0x10)

Thanks




     
« Last Edit: August 23, 2014, 08:44:59 AM by neptun2002 »

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #19 on: August 23, 2014, 08:34:27 AM »
Dear Archie Pleas Have a look to the attached File
thanks
This was addressed and fixed in version 3.66

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #20 on: August 23, 2014, 09:00:16 AM »
Sure There is some Thing wrong with me Archi I checked again I am Testing Ver 3.66 now I can see the code as Follows

public ModbusPDUFrame(byte[] packet, int length, int offset)
{
    this.FullPacket = new List<byte>();
    if (offset < 0)
    {
        offset = 0;
    }
    this.m_FunctionCode = packet[0 + offset];              '<--------------------------------------------------- This One
    if ((this.m_FunctionCode >= 0x80) && (packet.Length > 1))
    {
        this.m_ExceptionCode = packet[1 + offset];
    }
    else
    {
        this.m_ExceptionCode = 0;
    }
    this.m_EncapsulatedData = new List<byte>();
    if ((length + offset) > packet.Length)
    {
        length = packet.Length - offset;
    }
    int num2 = length - 1;
    for (int i = 2 + offset; i <= num2; i++)
    {
        this.m_EncapsulatedData.Add(packet);
    }
}


Thanks

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #21 on: August 23, 2014, 09:12:20 AM »
Sure There is some Thing wrong with me Archi I checked again I am Testing Ver 3.66 now I can see the code as Follows
The fix was done in the ModbudRTUFrame, so it would not affect any other classes that use the ModbusPDUFrame:
Code: [Select]
       '**********************************
        '* Extract data from a packet
        '**********************************
        Public Sub New(ByVal packet() As Byte, ByVal length As Integer)
            m_StationAddress = packet(0)

            m_PDU = New Modbus.ModbusPDUFrame(packet, packet.Length - 2, 1)  <----------
        End Sub

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #22 on: August 23, 2014, 12:43:51 PM »
Yes Archie I saw it But Now every thing I gut Right before is wrong

I think we have to change every call of this function the same way to solve the problem also I wonder as we know from the structure of the Modbus telegram that is the second byte is the function code so what is the necessity to have the offset in this case as we need the function code itself nothing else ??!!

Thank you so much Dear

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #23 on: August 23, 2014, 01:26:14 PM »
Yes Archie I saw it But Now every thing I gut Right before is wrong

I think we have to change every call of this function the same way to solve the problem also I wonder as we know from the structure of the Modbus telegram that is the second byte is the function code so what is the necessity to have the offset in this case as we need the function code itself nothing else ??!!
ModbusTCP does not have the same packet, so if the offset was changed in ModbusPDU, then the class could not be used to extract ModbusTCP packets.

And yes, you are right, every call to the PDU class from the RTU class has to be changed (which is only one other location).

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #24 on: August 23, 2014, 01:35:54 PM »
Now I get it Back to work Just subtract The One we Added to offset

Public Sub New(ByVal packet As Byte(), ByVal lengthOfThePacket As Integer, ByVal offset As Integer)
            Me.FullPacket = New List(Of Byte)
            If (offset < 0) Then
                offset = 0
            End If
            Me.m_FunctionCode = packet((0 + offset))

            If ((Me.m_FunctionCode >= &H80) AndAlso (packet.Length > 1)) Then
                Me.m_ExceptionCode = packet((1 + offset - 1))
            Else
                Me.m_ExceptionCode = 0
            End If
            Me.m_EncapsulatedData = New List(Of Byte)
            If ((lengthOfThePacket + offset - 1) > packet.Length) Then
                lengthOfThePacket = (packet.Length - offset - 1)
            End If

            Dim newPacketLength As Integer = ((lengthOfThePacket + offset - 1) - 1)
            Dim i As Integer = (2 + offset - 1)
            Do While (i <= newPacketLength)
                Me.m_EncapsulatedData.Add(packet(i))
                i += 1
            Loop

        End Sub


I think the best way Is to make a new method especially for RTU

Now with these changes I have Good result


« Last Edit: August 23, 2014, 01:44:30 PM by neptun2002 »

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #25 on: August 23, 2014, 02:27:45 PM »
            Me.m_FunctionCode = packet((0 + offset))

            If ((Me.m_FunctionCode >= &H80) AndAlso (packet.Length > 1)) Then
                Me.m_ExceptionCode = packet((1 + offset - 1))
            Else
                Me.m_ExceptionCode = 0
            End If
There is a problem with this code. It will set the Exception code to the same value as the function code. The exception code is in the data byte position.

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #26 on: August 24, 2014, 02:41:10 AM »
Yes You are Right About this point Archie. I did not take care enough to this point as it is not affect the run in normal condition so as I suggested yesterday I found that adding a new version of ModbusPDUFrame Dedicated for RTU and Leave the Old one for TCP  as is will be one possibility and the code should be like this





Namespace MfgControl.AdvancedHMI.Drivers.Modbus
    Public Class ModbusPDUFrame

'***************** The old Method Dedicated For TCP And whatever other callers need AS Is no thing changed
        Public Sub New(ByVal packet As Byte(), ByVal length As Integer, ByVal offset As Integer)
            Me.FullPacket = New List(Of Byte)
            If (offset < 0) Then
                offset = 0
            End If
            Me.m_FunctionCode = packet((0 + offset))
            If ((Me.m_FunctionCode >= &H80) AndAlso (packet.Length > 1)) Then
                Me.m_ExceptionCode = packet((1 + offset))
            Else
                Me.m_ExceptionCode = 0
            End If
            Me.m_EncapsulatedData = New List(Of Byte)
            If ((length + offset) > packet.Length) Then
                length = (packet.Length - offset)
            End If
            Dim num2 As Integer = (length - 1)
            Dim i As Integer = (2 + offset)
            Do While (i <= num2)
                Me.m_EncapsulatedData.Add(packet(i))
                i += 1
            Loop
        End Sub
        '***************************************************************
        '***************** The New Added One Dedicated For RTU tailored on the RTU Requirements
        Public Sub New(ByVal packet As Byte(), ByVal lengthOfThePacket As Integer, ByVal offset As Integer, ByVal It_Is_RTU As Integer)
            Me.FullPacket = New List(Of Byte)
            If (offset < 0) Then
                offset = 0
            End If
            Me.m_FunctionCode = packet(1)

            If ((Me.m_FunctionCode >= &H80) AndAlso (packet.Length > 1)) Then
                Me.m_ExceptionCode = packet(2)
            Else
                Me.m_ExceptionCode = 0
            End If
            Me.m_EncapsulatedData = New List(Of Byte)
            If ((lengthOfThePacket) > packet.Length) Then
                lengthOfThePacket = (packet.Length)
            End If

            Dim newPacketLength As Integer = (lengthOfThePacket - 1)
            Dim i As Integer = 2
            Do While (i <= newPacketLength)
                Me.m_EncapsulatedData.Add(packet(i))
                i += 1
            Loop

        End Sub
        'Stop **********************************************************************************



Namespace MfgControl.AdvancedHMI.Drivers.ModbusRTU
    Public Class ModbusRTUFrame

 Public Sub New(ByVal packet As Byte(), ByVal length As Integer, ByVal RTU As Integer)
            Me.FullPacket = New List(Of Byte)
            Me.m_StationAddress = packet(0)
            '***********************************
            Dim Offset As Integer = 1
            Dim Is_It_RTU As Integer = 1
            '***********************************
            Me.m_PDU = New ModbusPDUFrame(packet, packet.Length, Offset, Is_It_RTU)
        End Sub



Namespace ModbusRTU
    Public Class ModbusRTUCom

            Dim IT_IS_RTU As Integer = 1
            Dim RTU As New ModbusRTUFrame(New List(Of Byte)(e.RawData).ToArray, e.RawData.Count, IT_IS_RTU)


Now It is work Great

Thank you so much dear
« Last Edit: August 24, 2014, 04:41:59 AM by neptun2002 »

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #27 on: August 27, 2014, 11:02:25 PM »
Version 3.67 has been posted that fixes a writing problem to holding registers such as address 40001

neptun2002

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #28 on: August 28, 2014, 04:45:25 AM »
Thank you so much Archie for your efforts in this project

I tested the new version its work great when number of elements is les than 8 that means one byte so I made a small change and it is working great now

thanks



        Private Function ExtractData(ByVal RawData As List(Of Byte), ByVal startByte As Integer, ByVal address As ModbusAddress) As String()
            Dim values(address.NumberOfElements - 1) As String

            Dim NumberOfBytes As Integer = CInt(Math.Ceiling(address.BitsPerElement / 8))
            Dim i As Integer
            While i < address.NumberOfElements And (startByte + i) < Math.Floor(RawData.Count / NumberOfBytes)
                'Dim HexByte1 As String = Chr(RawData(startByte + i * NumberOfBytes)) & Chr(RawData(startByte + (i * NumberOfBytes) + 1))
                If NumberOfBytes > 1 Then
                    'Dim HexByte2 As String = Chr(RawData(startByte + (i * NumberOfBytes) + 2)) & Chr(RawData(startByte + (i * NumberOfBytes) + 3))
                    If Not m_TreatDataAsHex Then
                        values(i) = CStr(RawData(startByte + i * NumberOfBytes) * 256 + RawData(startByte + i * NumberOfBytes + 1))
                    Else
                        values(i) = CalculationsAndConversions.ByteToHex(RawData(startByte + i * NumberOfBytes)) & CalculationsAndConversions.ByteToHex(RawData(startByte + i * NumberOfBytes + 1))
                    End If
                Else
                    If Not m_TreatDataAsHex Then
                        If address.BitsPerElement > 1 Then
                            values(i) = CStr(RawData(startByte + i * NumberOfBytes)) '  + 1)) removed 21-AUG-14
                        Else
                            '* It is a bit read, so extract from the byte
                            Dim BitNumber As Integer = 0


                            '**The Bug********************************************************************************************
                            'While ((i + BitNumber) < address.NumberOfElements) And (BitNumber < 15)                                                 '<------------This one Because it is byte
                            'values(i + BitNumber) = CStr((((RawData(startByte + i * NumberOfBytes)) And CByte(2 ^ BitNumber)) > 0))  '<------------This one the location of the bit in the array
                            '**The Bug********************************************************************************************


                            '**The New Code ********************************************************************************************
                            While ((i + BitNumber) < address.NumberOfElements) And (BitNumber < 8)               '< 15)
                                values((i * 8) + BitNumber) = CStr((((RawData(startByte + i * NumberOfBytes)) And CByte(2 ^ BitNumber)) > 0))
                                '**The New Code ********************************************************************************************

                                BitNumber += 1
                            End While
                        End If
                    Else
                        values(i) = CalculationsAndConversions.ByteToHex(RawData(startByte + i * NumberOfBytes))
                    End If
                    End If

                i += 1
            End While

            Return values
        End Function
 
« Last Edit: August 28, 2014, 05:00:21 AM by neptun2002 »

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: direct logic 05 with the modbus RTU comm driver questions.
« Reply #29 on: September 01, 2014, 05:14:37 PM »
I fixed and reworked a number of things with the ModbusRTU driver. It's now more responsive and recovers quickly from a loss of communications. It seems to be quite stable now with version 3.68