B4A Library TCP_MODBUS LIBRARY

alan1968

Active Member
Licensed User
I share my lib

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
Dim plc(4) As Modbus_B4A_120815 '4 plc
Dim timer1 As Timer
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
timer1.Initialize("timer1",250)
timer1.Enabled=True
DisableStrictMode
Log(plc(0).Set_plc("192.168.2.50",1,502,2000))'wago
Log(plc(1).Set_plc("192.168.2.56",255,502,2000))'phoenix
Log(plc(2).Set_plc("192.168.2.58",1,502,2000))'wago
Log(plc(3).Set_plc("192.168.2.60",255,502,2000))'phoenix
plc(3).Connect
plc(2).Connect
plc(1).Connect
plc(0).Connect

End Sub

Sub Activity_Resume
Log(plc(0).Set_plc("192.168.2.50",1,502,2000))'wago
Log(plc(1).Set_plc("192.168.2.56",255,502,2000))'phoenix
Log(plc(0).Set_plc("192.168.2.58",1,502,2000))'wago
Log(plc(1).Set_plc("192.168.2.60",255,502,2000))'phoenix
plc(3).Connect
plc(2).Connect
plc(1).Connect
plc(0).Connect
End Sub

Sub Activity_Pause (UserClosed As Boolean)
plc(3).Disconnect
plc(2).Disconnect
plc(1).Disconnect
plc(0).Disconnect
End Sub

Sub timer1_tick
If plc(0).isConnect=True Then Log(plc(0).TCP_ReadCoils(512,16))'wago (Qx0 to Qx15)
If plc(1).isConnect=True Then Log(plc(1).TCP_ReadMultipleRegisters(16,8))'zelio %MW16 to %MW23
If plc(2).isConnect=True Then Log(plc(2).TCP_ReadInputDiscretes(0,16))'phoenix
If plc(3).isConnect=True Then Log(plc(3).TCP_ReadMultipleRegisters(12288,16))'wago (%MW0 to %MW15)
End Sub

Sub DisableStrictMode
   Dim jo As JavaObject
   jo.InitializeStatic("android.os.Build.VERSION")
   If jo.GetField("SDK_INT") > 9 Then
     Dim policy As JavaObject
     policy = policy.InitializeNewInstance("android.os.StrictMode.ThreadPolicy.Builder", Null)
     policy = policy.RunMethodJO("permitAll", Null).RunMethodJO("build", Null)
     Dim sm As JavaObject
     sm.InitializeStatic("android.os.StrictMode").RunMethod("setThreadPolicy", Array(policy))
   End If
End Sub
 

Attachments

Mr Mo

Member
Licensed User
Thanks for sharing @alan1968 (1968 is a well known year)!
May we have more information about the return value of the read functions?
 

alan1968

Active Member
Licensed User
This sample code read 100 Words (%MW0 to %MW99) into Wago 750-881

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
Dim plc As Modbus_B4A_120815 
Dim timer1 As Timer
Dim adr(65536) As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
timer1.Initialize("timer1",1000)
timer1.Enabled=True
DisableStrictMode
Log(plc.Set_plc("192.168.2.50",1,502,2000))'wago
plc.Connect
End Sub

Sub Activity_Resume
Log(plc.Set_plc("192.168.2.50",1,502,2000))'wago
plc.Connect
End Sub

Sub Activity_Pause (UserClosed As Boolean)
plc.Disconnect
End Sub

Sub timer1_tick
If plc.isConnect=True Then ReadMultipleRegisters(12288,100) 'adress 12288 =%MW0 wago read 100 Words
End Sub

Sub ReadMultipleRegisters(ref As Int, cont As Int)
Dim string_modbus As String
Dim nb_byte As Int
Dim hex As String
Dim dhex As String
string_modbus=plc.TCP_ReadMultipleRegisters(ref,cont)
cont=0
If string_modbus<> "ERROR" Then
string_modbus=Mid(string_modbus,28,string_modbus.Length-27)
nb_byte=string_modbus.Length/3
For i=0 To nb_byte-1 Step 2
dhex=""
hex=Mid(string_modbus,1+(3*i),3).Trim
dhex=hex
hex=Mid(string_modbus,1+(3*(i+1)),3).Trim
dhex=dhex & hex
adr(ref+cont)=plc.HexadecimalToDecimal(dhex)
Log((ref+cont)&":" & adr(ref+cont))
cont=cont+1
Next
Else
Log("Error ReadMultipleRegisters")
End If
End Sub

Sub DisableStrictMode
   Dim jo As JavaObject
   jo.InitializeStatic("android.os.Build.VERSION")
   If jo.GetField("SDK_INT") > 9 Then
     Dim policy As JavaObject
     policy = policy.InitializeNewInstance("android.os.StrictMode.ThreadPolicy.Builder", Null)
     policy = policy.RunMethodJO("permitAll", Null).RunMethodJO("build", Null)
     Dim sm As JavaObject
     sm.InitializeStatic("android.os.StrictMode").RunMethod("setThreadPolicy", Array(policy))
   End If
End Sub

Sub Mid(Text As String, start As Int, Length As Int) As String
   Try
   Return Text.SubString2(start-1,start+Length-1)
   Catch
   End Try
End Sub
 

oreleon

New Member
Licensed User
This sample code read 100 Words (%MW0 to %MW99) into Wago 750-881

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
Dim plc As Modbus_B4A_120815
Dim timer1 As Timer
Dim adr(65536) As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
timer1.Initialize("timer1",1000)
timer1.Enabled=True
DisableStrictMode
Log(plc.Set_plc("192.168.2.50",1,502,2000))'wago
plc.Connect
End Sub

Sub Activity_Resume
Log(plc.Set_plc("192.168.2.50",1,502,2000))'wago
plc.Connect
End Sub

Sub Activity_Pause (UserClosed As Boolean)
plc.Disconnect
End Sub

Sub timer1_tick
If plc.isConnect=True Then ReadMultipleRegisters(12288,100) 'adress 12288 =%MW0 wago read 100 Words
End Sub

Sub ReadMultipleRegisters(ref As Int, cont As Int)
Dim string_modbus As String
Dim nb_byte As Int
Dim hex As String
Dim dhex As String
string_modbus=plc.TCP_ReadMultipleRegisters(ref,cont)
cont=0
If string_modbus<> "ERROR" Then
string_modbus=Mid(string_modbus,28,string_modbus.Length-27)
nb_byte=string_modbus.Length/3
For i=0 To nb_byte-1 Step 2
dhex=""
hex=Mid(string_modbus,1+(3*i),3).Trim
dhex=hex
hex=Mid(string_modbus,1+(3*(i+1)),3).Trim
dhex=dhex & hex
adr(ref+cont)=plc.HexadecimalToDecimal(dhex)
Log((ref+cont)&":" & adr(ref+cont))
cont=cont+1
Next
Else
Log("Error ReadMultipleRegisters")
End If
End Sub

Sub DisableStrictMode
   Dim jo As JavaObject
   jo.InitializeStatic("android.os.Build.VERSION")
   If jo.GetField("SDK_INT") > 9 Then
     Dim policy As JavaObject
     policy = policy.InitializeNewInstance("android.os.StrictMode.ThreadPolicy.Builder", Null)
     policy = policy.RunMethodJO("permitAll", Null).RunMethodJO("build", Null)
     Dim sm As JavaObject
     sm.InitializeStatic("android.os.StrictMode").RunMethod("setThreadPolicy", Array(policy))
   End If
End Sub

Sub Mid(Text As String, start As Int, Length As Int) As String
   Try
   Return Text.SubString2(start-1,start+Length-1)
   Catch
   End Try
End Sub
 

oreleon

New Member
Licensed User
Hello Alan,
Thank you for sharing this. I have not had a chance to use this yet as I only came across this today. Can this lib also handle the RTU protocol?
Regards, John.
 

Mr Mo

Member
Licensed User
Hello Alan,

Many thanks for the reply. All it's ok for me now.
Just at last two questions, when you write :
B4X:
.TCP_ReadMultipleRegisters(ref As Int, cont As Int)
.TCP_ReadCoils(ref as Int, cont as Int)
.TCP_ReadInputDiscretes(ref as Int, cont as Int)
What are the limit for ref?
The data are sent and received in a string... could it be possible to have alternate functions with data passed by array?

Regards,
Mo
 
Last edited:

alan1968

Active Member
Licensed User
hi Mr Mo,
Hello Alan,
Thank you for sharing this. I have not had a chance to use this yet as I only came across this today. Can this lib also handle the RTU protocol?
Regards, John.
hi!
no this lib work only in modbus tcp,but i see for add rtu protocol
 

alan1968

Active Member
Licensed User
Hello Alan,

Many thanks for the reply. All it's ok for me now.
Just at last two questions, when you write :
B4X:
.TCP_ReadMultipleRegisters(ref As Int, cont As Int)
.TCP_ReadCoils(ref as Int, cont as Int)
.TCP_ReadInputDiscretes(ref as Int, cont as Int)
What are the limit for ref?
The data are sent and received in a string... could it be possible to have alternate functions with data passed by array?

Regards,
Mo
Hi Mo!
Ref (start address) :depends on plc
 

jinyistudio

Active Member
Licensed User
Hi alan

I put ReadMultipleRegisters in timer1(Every 30 second call one time).
Why, I must call connect again when i called ReadMultipleRegisters every time ?

B4X:
Sub AppStart (Args() As String)
    Log(plc.Set_plc(plcip,1,502,2000)) 'wago
    plc.Connect  
    StartMessageLoop
End Sub

Sub ControlPLC
    If plc.isConnect=True Then
        ReadMultipleRegisters(0,32) 'adress 12288 =%MW0 wago read 100 Words
    Else
        plc.Disconnect
        plc.Connect
    End If
End Sub

Sub timer1_tick
    timer1.Enabled=False
  
    If plcTick>=3 Then
        ControlPLC
        plcTick=0
    End If
  
  
    tick = tick + 1
    If tick >= 10 Then
        plcTick=plcTick+1 '每秒+1
        tick=0
        Log("tick")
    End If
    timer1.Enabled=True
End Sub
 
Last edited:

skyracer90

Member
Licensed User
Hello Alan,
Thanks for your Modbus driver. I know the protocol, but I save now the whole programming thanks to your contribution. If you or someone else is interested in the protocol for an S7-Communication (RFC1006), let me know. Here it is in German
Language perfectly documented.
I do not know if I can share the link here? Sorry! Anywhere can find this in the www
http://www.bj-ig.de/service/verfuegbare-dokumentationen/s7-kommunikation/index.html
Plaese accept the Work of this Guys....
Great this Docu, I testet it and it's work...
If any body use it... Please look at the ConnectionRequest at Byte(18) (Byte Count beginns with Zero!) witch your CPU !Rack&Slot!. I,am using at via an Siemens CP 343-1
Best regards,
Rainer
P.S. Have you any Docu's about your Lib?
 
Top