B4R Question b4r modbus, possible?

barx

Well-Known Member
Licensed User
Longtime User
b4r, esp8266, modbus communication (over rs485).

Any way to do it?

I have a rs485 to ttl adaptor,

Cheers
 

barx

Well-Known Member
Licensed User
Longtime User
I have just had the device delivered today, it will be the weekend before I get time to play with it. Will report back, thanks
 
Upvote 0

barx

Well-Known Member
Licensed User
Longtime User
Still trying, but not getting anywhere fast. Not determined if it software or hardware issue though. I can connect the device directly to pc with usb <-> rs485 adaptor and read the data but not get any with arduino as yet. getting a response of 224 but cannot find what that means. Will keep trying.
 
Upvote 0

barx

Well-Known Member
Licensed User
Longtime User
After looking through the source for the lib, I had been search for 224 when in fact I needed to search the hex value E0 'Invalid Slave ID'.
The ID is set to 1, the device is set to '1'.
I tried 0, then I get a 225 error - Invalid Function.

The mind boggles.
 
Upvote 0

rodmcm

Active Member
Licensed User
I'll throw this code for assistance. It is for a Modbus connection to a Dwyer Temp Controller Type 16B written in B4R
Once you send a command or setpoint(SV) the Dwyer immediately responds with the send bytes (in the case of a command)
or the measured value (MV) if requested.

You will see that I predetermined the byte stream from the Dwyer information for each type of command

I used a simple numeric key to gate the return
B4X:
'This code is for the DwyerController and its modbus interconnection

'The Dwyer controller responds immediately to the command

'Each command is provided with a key that allows the gating of the returned Information

' Data transmission is from a serial out of an ESP32 via a MAX 3486
' Data is read back on the same serial

 

Sub Process_Globals
    'Set commands
    'Get_MV      Gets the measured value
    'Set_SV         Sents the SV, you have to  Add_CRC_Values
    'Set_Run     Sets the controller to run
    'Set_Stop     Stops the controller
    
    Dim Get_MV(8) As Byte =  Array As Byte(0x01,0x03,0x10,0x00,0x00,0x01,0x80,0xCA)
    Dim Set_SV(8) As Byte =   Array As Byte(0x01,0x06,0x10,0x01,0x00,0x00,0x00,0x00)                                   '' add data 2 bytes, setting unit 0.1, add CRC
    Dim Set_Run(8) As Byte  = Array As Byte(0x01,0x05,0x08,0x14,0xFF,0x00,0xCE,0x5E) '1,5,8,20,255,0,206,94
    Dim Set_Stop(8) As Byte = Array As Byte(0x01,0x05,0x08,0x14,0x00,0x00,0x8F,0xAE) '1,5,8,20,00,143,174
End Sub

'-----------------------------------------------------------------
' This function extracts the reading returned in a 03 call
' The function checks that the returned function has 03 as
' the second location and that the CRC is correct   ( I did not implement this here)
' It then extracts the value read and returns the amswer
' It will only return up To three bytes of information
' This is based on knowing the length of the return from
' the number of bytes in buf[2]
'-----------------------------------------------------------------
Sub Extract_RX_Value (Buf() As Byte) As Int                      ' extracts the value
    'Log("Extact MV value ")
    Dim Val As Int
'    Dim CRC_Calc As UInt=0
'    Dim CRC_Return As UInt=0
'    CRC_Return = Bit.Or(Bit.ShiftLeft(Buf(4+Buf(2)),8), Buf(3+Buf(2)))         ' the last two bytes (reversed)
'    Dim x As Int = 3+Buf(2)
'    CRC_Calc = CRC16_2(Buf,x)                                    ' 3+the value buf[2] gives the length
'    If Buf(1) = 0x03 And CRC_Return=CRC_Calc  Then                 ' ensures that buf[1]==command 0x03
    If Buf(1) = 0x03 Then
        Select Buf(2)
            Case 1
                Val = Buf(3)
            Case 2
                Val = Bit.Or(Bit.ShiftLeft(Buf(3),8),Buf(4))
            Case 3
                Val = Bit.Or(Bit.ShiftLeft(Buf(3),16), Bit.ShiftLeft(Buf(4),8))
                Val = Bit.Or(Val,Buf(5))
        End Select
        If Val<30000 And Val>0 Then
            Return Val/10+1                        ' this Controller sends temp x 10
        Else
            Return 9999
        End If
    Else
        Return 9999                                 ' error in message(FC Or CRC)
    End If
    
End Sub


'----------------------------------------------------------------------
' Returns the CRC For a selection of bytes
' buf is the Array the Information is in
' length is the number of bytes in the Array To
' use For the CRC calculation
'----------------------------------------------------------------------
Sub CRC16_2(Buf() As Byte, len As Int) As UInt
    Dim CRC2 As UInt  = 0xFFFF
    For pos = 0 To len-1
        CRC2=Bit.XOR(CRC2,Buf(pos))
        For i = 8 To 1 Step -1
            If Bit.And(CRC2,0x0001) <> 0 Then
                CRC2=Bit.ShiftRight(CRC2,1)   ' Shift CRCright And XOR 0xA001
                CRC2=Bit.XOR(CRC2, 0xA001)
            Else                              ' Else LSB is Not set
                CRC2=Bit.ShiftRight(CRC2,1)
            End If
        Next
    Next
    Return CRC2
End Sub

'-----------------------------------------------------------------
' This adds the two CRC values in the correct location
' at the end of the Buf file (locations 6 and 7)
' The Buf file has to have two extra locations for the
' addition. len is the same call As the CRC
' calculate value
'-----------------------------------------------------------------
Sub Add_CRC_Values(CRC2 As UInt, len As Int)
    Set_SV(len)   = Bit.And(CRC2,0x00FF)
    Set_SV(len+1) = Bit.And(Bit.ShiftRight(CRC2,8), 0x00FF)
End Sub


'-----------------------------------------------------------------
'Returns True if two arrays are identical, used to ensure
'send and recieve are the same
'-----------------------------------------------------------------------
Sub Array_Test(Buf1() As Byte, Buf2() As Byte) As Boolean
    'Log("AddTest1")
    Dim Test As Boolean= True
    If Buf1.Length<>Buf2.Length Then
        Test = False
        Return Test
    End If

    For pos = 0 To Buf1.Length-1
        If Buf1(pos) <> Buf2(pos) Then
            Test=False
        End If
    Next
    Return Test
End Sub


'-----------------------------------------------------------------
'Send an Array To the Controller via a serial RTX2 via a MAX 3486

'The change of the Mod Read/Write pin timing  is quite sensitive as the
'Dywer return is very fast and you can miss it
'-----------------------------------------------------------------
Sub Send_To_Controller(Buf() As Byte)
    'log("Send to Controller")
    Main.ModbusPin.DigitalWrite(True)      'sets Max3485 To transmit
    Delay(15)                            'settle time
    Main.SendRTX2(Buf)
    Delay(10)                            'settle time
    Main.ModbusPin.DigitalWrite(False)  'sets Max3485 To recieve
End Sub


'-----------------------------------------------------------------
'Send temperature setpoint to Controller
' The send stream has to be adjusted by the temperature SP required
'-----------------------------------------------------------------
Sub SendSP(SPTemp As Int)
    Log ("SendingSP  ", SPTemp )
    SPTemp = SPTemp*10                                         ' Controller setting is in 0.1 degrees
    Set_SV(4) = Bit.And(Bit.ShiftRight(SPTemp,8),0xFF)         ' add hex value To transmit file
    Set_SV(5) = Bit.And(SPTemp,0xFF)                           ' add hex value To transmit file
    Add_CRC_Values(CRC16_2(Set_SV,6),6)                           ' Calculates the CRC And appends To end of the control file
    Send_To_Controller(Set_SV)                                 ' send the SV To the Controller.
End Sub


'-----------------------------------------------------------------
' Sends RunSignal to Controller
'-----------------------------------------------------------------
Sub SendStartSignal
    Log ("Control-Sending Start Signal")
    Send_To_Controller(Set_Run)               ' Sends a start Signal
End Sub

'-----------------------------------------------------------------
' Sends the SP to the Controller
'-----------------------------------------------------------------
Sub SendSPValue(SP As Int)
    Log ("Control -Sending SV Value")
    SendSP(SP)
End Sub

'-----------------------------------------------------------------
' Responds To what is returned from the modbus recieve
' The response should be the same as the send got the run/stop/SV commmands
' The response is gated by the number of the Control sent
' Control numbers         
'  1          Get the MV 
'  2          Run Signal Sent
'  3          Stop Signal Sent
'  4          SV Sent
'-----------------------------------------------------------------
Sub  Check_ControlRX(Buffer() As Byte, ControlNo As Int)
    Select ControlNo
        Case  1
            Dim x As Int  = Extract_RX_Value(Buffer)
            If x =9999 Then      'checks For error
                Log("Current MV error")
            Else
                Main.CurrentMV=x
                Log("Current MV is  :  ",Main.CurrentMV)
            End If
        Case  2
            If Array_Test(Set_Run, Buffer) Then
                Log("Controller Running")
            End If
        Case 3
            If Array_Test(Set_Stop, Buffer) Then
                Log("Controller Stopped")
            End If
        Case 4
            If Array_Test(Set_SV, Buffer) = True Then
                Log( "SV sent to controller")   
            End If
    End Select
End Sub
 
Upvote 0

rodmcm

Active Member
Licensed User
This Panasonic manual has a clear description of the Modbus protocol
 

Attachments

  • KT4 Communication Manual.pdf
    169.4 KB · Views: 388
Upvote 0
Top