B4R Question RS485 ModBus Master

peacemaker

Expert
Licensed User
Longtime User
Hi, All

Anyone already tried to implement Master side of Modbus protocol over RS485 interface ?
Any shared code (even to be paid) ?
 

peacemaker

Expert
Licensed User
Longtime User
Some sensor. But the universal Master module is needed.

Seems, i have just made an update, basing on Slave module.:
B4X:
Private Sub Process_Globals
......
Private Master As Boolean = True
End Sub

#Region Master subs
'Requests from Master to Slave with ID
'Operation: 1/2/3/4 = Read Coil Status/Read Input Status/Read Holding Registers/Read Input Registers
'Reading starting FirstRegister from registers qty of RegistersNumber
Public Sub MasterRequest(toSlaveID As Byte, Operation As Byte, FirstRegister As UInt, RegistersNumber As UInt)
    Dim b(6) As Byte    'command
    b(0) = toSlaveID
    b(1) = Operation
    Dim ui(1) As UInt
    ui(0) = FirstRegister
    Dim a(2) As Byte = bc.UIntsToBytes(ui)
    b(2) = a(1)
    b(3) = a(0)
 
    ui(0) = RegistersNumber
    Dim a2(2) As Byte = bc.UIntsToBytes(ui)
    b(4) = a2(1)
    b(5) = a2(0)
    WriteMaster(b)    'send command + CRC
End Sub
#End region

Private Sub Receive (Buffer() As Byte)
    Dim raw_len As UInt = Buffer.Length
    If raw_len > 3 Then
        bc.ArrayCopy2(Buffer,0,Sa,0,1)
        bc.ArrayCopy2(Buffer,1,Fc,0,1)
        Dim Sc As UInt = HexToInt(Fc)    'command
    End If

    If Not(Master) Then
        If raw_len > 5 Then
            bc.ArrayCopy2(Buffer,2,Fr,0,2)
            bc.ArrayCopy2(Buffer,4,Nr,0,2)
            Dim Sr As UInt = HexToInt(Fr)    'first register address
            Dim Sn As UInt = HexToInt(Nr)    'registers qty
        End If
      
        Select Sc
            Case 1
                If Sr >= FCR And Sr < FCR+CO.Length Then Read_Coil_Status(Sr,Sn)
            Case 2
                If Sr >= FDI And Sr < FDI+DI.Length Then Read_Input_Status(Sr,Sn)
            Case 3
                If Sr >= FHR And Sr < FHR+HR.Length Then Read_Holding_Registers(Sr,Sn)
            Case 4
                If Sr >= FIR And Sr < FIR+IR.Length Then Read_Input_Registers(Sr,Sn)
            Case 5
                If Sr >= FCR And Sr < FCR+HR.Length Then Force_Single_Coil(Sr,Sn)
            Case 16
                If Sr >= FHR And Sr < FHR+HR.Length Then Preset_Multiple_Registers(Buffer,Sr,Sn)
            Case Else
        End Select
    Else    'response from Slave
        Master = False
        'Log("From Slave: ", bc.HexFromBytes(Buffer))
        Dim c(Buffer.Length - 2) As Byte
        bc.ArrayCopy2(Buffer, 0, c, 0, c.Length)
        Dim CalculatedCRC(2) As Byte = CRC(c)
        'Log("Calculated CRC = ", bc.HexFromBytes(CalculatedCRC))
        Dim ReceivedCRC(2) As Byte
        bc.ArrayCopy2(Buffer, Buffer.Length - 2, ReceivedCRC, 0, ReceivedCRC.Length)
        If bc.ArrayCompare(ReceivedCRC, CalculatedCRC) = 0 Then
            Main.Modbus_NewData(c)    'pass the received data block to a needed module
        Else
            Log("CRC error, response was ignored")
        End If
    End If
End Sub

Private Sub WriteMaster(Data() As Byte)
    Master = True
    Dim d() As Byte = JoinBytes(Array(Data,CRC(Data)))
    Log("Writing: ", bc.HexFromBytes(d))
    sstream.Write(d)
End Sub
 
Last edited:
Upvote 0

Similar Threads

Top