B4R Tutorial Ethernet / Network Tutorial

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
This example uses an Ethernet shield to connect to a server. In this case the server is implemented with B4J, though you can easily implement a similar server with B4A or B4i.

Whenever the user clicks on a connected button the event will be sent to the server.

The first step is to connect to the network.
We can assign a static address to the board or ask the network DHCP service to assign an address automatically.
B4X:
'eth is an Ethernet object.
If eth.InitializeDHCP(MacAddress) = False Then
     Log("Error connecting to network.")
     Return
End If
MacAddress is a 6 bytes array with the device mac address. On some boards the address is written on the board. You can use any valid value you like. Just make sure that it is unique in the local network.

The next step is to connect to the server with an EthernetSocket object:
B4X:
Sub Connect(unused As Byte)
   If ethClient.ConnectIP(serverIp, serverPort) = False Then
     Log("trying to connect again")
     CallSubPlus("Connect", 1000, 0)
     Return
   End If
   Log("Connected to server")
   astream.Initialize(ethClient.Stream, "Astream_NewData", "Astream_Error")
End Sub
This code will try to connect. If it fails it will try again after one second.

The AsyncStreams object is initialized after a successful connection.

Sending the data:
B4X:
Sub Btn_StateChanged (State As Boolean)
   If ethClient.Connected Then
     Dim s As Byte
     If State Then s = 1 Else s = 0
     astream.Write(Array As Byte(s))
   End If
End Sub
AsyncStreams events:
B4X:
Sub Astream_NewData (Buffer() As Byte)
   Log("Received from server: ", Buffer) 'pass the array of bytes. Don't convert to string.
End Sub

Sub Astream_Error
   Log("error")
   ethClient.Close
   CallSubPlus("Connect", 1000, 0) 'try to reconnect
End Sub
The B4J code (non-ui program):
B4X:
Sub Process_Globals
   Private astream As AsyncStreams
   Private server As ServerSocket
End Sub

Sub AppStart (Args() As String)
   server.Initialize(51042, "server")
   server.Listen
   StartMessageLoop
End Sub

Sub server_NewConnection (Successful As Boolean, NewSocket As Socket)
   Log("new connection")
   astream.Initialize(NewSocket.InputStream, NewSocket.OutputStream, "Astream")
   server.Listen
End Sub

Sub Astream_NewData (Buffer() As Byte)
   If Buffer(0) = 0 Then
     Log("Button is down.")
   Else
     Log("Button is up.")
   End If
   astream.Write("Thank you for this useful information.".GetBytes("UTF8"))
End Sub
The B4R program is attached.
 

Attachments

Last edited:

Cableguy

Expert
Licensed User
ub Astream_NewData (Buffer() As Byte)
Log("Received from server: ", Buffer) 'pass the array of bytes. Don't convert to string.
End Sub
should be:

B4X:
Sub Astream_NewData (Buffer() As Byte)
   Log("Received from server: ", Buffer) 'pass the array of bytes. Don't convert to string.
End Sub
 

Mostez

Active Member
Licensed User
This example uses an Ethernet shield to connect to a server
Hi Erel,
Would you please confirm the compatibility of this Ethernet shield with your code. If not would you please recommend one to try. One last question, is it possible to access the built in SD card with rSD library as they sharing the same SPI bus.

Thanks
 

Erel

Administrator
Staff member
Licensed User
Yes, it is compatible.
One last question, is it possible to access the built in SD card with rSD library as they sharing the same SPI bus.
It is not so simple, but possible. You should use a board with more flash space such as the Mega. I've tested it successfully with this code:
B4X:
Sub Process_Globals
   Public Serial1 As Serial
   Private astream As AsyncStreams
   Private eth As Ethernet
   Private ethClient As EthernetSocket
   Private btn As Pin
   Private serverIp() As Byte = Array As Byte(192, 168, 0, 6)
   Private MacAddress() As Byte = Array As Byte(0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED)
   Private const serverPort As UInt = 51042
   Private sd As SD
   Private pin10, pin4 As Pin
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   Dim pin53 As Pin
   pin53.Initialize(53, pin53.MODE_OUTPUT)
   pin10.Initialize(10, pin10.MODE_OUTPUT)
   pin4.Initialize(4, pin4.MODE_OUTPUT)
   SetSD(False)
   If eth.InitializeDHCP(MacAddress) = False Then
     Log("Error")
     Return
   Else
     Log("Connected")
   End If
   btn.Initialize(btn.A0, btn.MODE_INPUT_PULLUP)
   btn.AddListener("Btn_StateChanged")
   Connect(0)
   SetSD(True)
   Log("Initialize result: ", sd.Initialize(4))
   SetSD(False)
End Sub

Sub SetSD(state As Boolean)
   pin10.DigitalWrite(state)
   pin4.DigitalWrite(Not(state))
End Sub

Sub Btn_StateChanged (State As Boolean)
   If ethClient.Connected Then
     Dim s As Byte
     If State Then s = 1 Else s = 0
     astream.Write(Array As Byte(s))
   End If
   SetSD(True)
   For Each f As File In sd.ListFiles("/")
     Log(f.Name)
   Next
   SetSD(False)
End Sub

Sub Connect(unused As Byte)
   If ethClient.ConnectIP(serverIp, serverPort) = False Then
     Log("trying to connect again")
     CallSubPlus("Connect", 1000, 0)
     Return
   End If
   Log("Connected to server")
   astream.Initialize(ethClient.Stream, "Astream_NewData", "Astream_Error")
End Sub

Sub Astream_NewData (Buffer() As Byte)
   Log("Received from server: ", Buffer) 'pass the array of bytes. Don't convert to string.
End Sub

Sub Astream_Error
   Log("error")
   ethClient.Close
   CallSubPlus("Connect", 1000, 0)
End Sub
There were cases where the SD failed to initialize. It only started working again after I reconnected the USB cable.
 

RAFA BRAVO

Member
Licensed User
because I can't connect, and I'm in a loop in this if?


Sub Connect (unused As Byte)
If ethClient.ConnectIP (serverIp, serverPort) = False Then
Log ("trying to connect again")
CallSubPlus ("Connect", 1000, 0)
Return
End if
Log ("Connected to server")
astream.Initialize (ethClient.Stream, "Astream_NewData", "Astream_Error")
End Sub
 

thetahsk

Active Member
Licensed User
We need more Information about your MCU, Ethernetshield, the installed libs in Arduino IDE, version B4R, version Arduino IDE.
Try to compile an Arduino Ethernet Example from the Arduino IDE and check if it's working.

Use code Tags from the Insert menue.

B4X:
Log("use code tags")
 
Last edited:

RAFA BRAVO

Member
Licensed User
this is the board i use:
https://www.industrialshields.com/e...c-arduino-ethernet-21-ios-analog-digital-plus
version Arduino ide: 1.8.10
version B4R: 2.5.1.0

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial
    Dim eth As Ethernet
    Private ethClient As EthernetSocket
    Private astream As AsyncStreams
    Private serverIp() As Byte = Array As Byte(192, 168, 0, 16)
    Private MacAddress() As Byte = Array As Byte(0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED)
    Private const serverPort As UInt = 51042
    Private ser As B4RSerializator
    Private timer1 As Timer
    Private PIND0, PIND1, PIND2, PIND3, PIND4, PIND5, PIND6, PIND7 As Pin
   
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    If eth.InitializeDHCP(MacAddress) = False Then
        Log("Error connecting to network.")
        Return
    Else
        Log("Connected to network. My ip address: ", eth.LocalIp)
    End If
    timer1.Initialize("SEND0", 100)
    Connect(0)
End Sub

Sub Connect(unused As Byte)
    If ethClient.ConnectIP(serverIp, serverPort) = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        Return
    End If
    Log("Connected to server")
    astream.Initialize(ethClient.Stream, "Astream_NewData", "Astream_Error")
End Sub

Sub SEND0
    If PIND0.DigitalRead=True Then
        Dim output As String = "7seg0"
    End If
   
    If PIND1.DigitalRead=True  Then
        Dim output As String = "7seg1"
    End If
   
    If PIND2.DigitalRead=True  Then
        Dim output As String = "7seg2"
    End If
   
    If PIND6.DigitalRead=True  Then
        Dim output As String = "7seg3"
    End If
   
    If PIND7.DigitalRead=True  Then
        Dim output As String = "7seg4"
    End If
   
    astream.Write(ser.ConvertArrayToBytes(Array(output)))
   
End Sub

Sub astream_NewData (Buffer() As Byte)
    Dim be(10) As Object 'used as a storage buffer.
    Dim objects() As Object = ser.ConvertBytesToArray(Buffer, be)
'    Log("Recieved:")
    For Each o As Object In objects
        Log(o)
        Select Case o
            Case  "OUTPUT1 T"
                PIND3.DigitalWrite(True)
            Case  "OUTPUT1 F"
                PIND3.DigitalWrite(False)
            Case  "OUTPUT2 T"
                PIND4.DigitalWrite(True)
            Case  "OUTPUT2 F"
                PIND4.DigitalWrite(False)
            Case  "OUTPUT3 T"
                PIND5.DigitalWrite(True)
            Case  "OUTPUT3 F"
                PIND5.DigitalWrite(False)
        End Select
    Next
End Sub

Sub Astream_Error
    Log("Error")
    timer1.Enabled = False
    ethClient.Close
    CallSubPlus("Connect", 1000, 0)
End Sub
 

RAFA BRAVO

Member
Licensed User
the program does not leave this if
B4X:
  If ethClient.ConnectIP(serverIp, serverPort) = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        Return
    End If
 

thetahsk

Active Member
Licensed User
installing the industrial shields board the ethernet2.h library is installed
Update your B4R Version to the latest release and use the enhanced ethernet library because your board use the W5500 chip.
Don't forget to call the InitCS(Byte CSPin) function. The CS/SS pin is 10 on your Mega2560 Board.
 
Last edited:

RAFA BRAVO

Member
Licensed User
thetahsk said::
Don't forget to call the InitCS(Byte CSPin) function. The CS/SS pin is 10 on your Mega2560 Board.

I don't understand this last step
 

thetahsk

Active Member
Licensed User
thetahsk said::
Don't forget to call the InitCS(Byte CSPin) function. The CS/SS pin is 10 on your Mega2560 Board.

I don't understand this last step
before calling the eth.InitializeAdvanced(....) function, call InitCS(10)
 

RAFA BRAVO

Member
Licensed User
rEthernetadvanced library, has no XML file?
I can't select it in B4R, I can only use the rEthernet library.
you can better show how to call the InitCS () function?
thanks.
 

RAFA BRAVO

Member
Licensed User
I have the following errors when compiling with the rEthernetadvanced library


logs::
rEthernetAdvanced.cpp:18:19: error: 'class EthernetClass' has no member named 'linkSpeed'; did you mean 'linkStatus'?
   return Ethernet.linkSpeed();


Is it correct to call the function InitCS ()?

B4X:
Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    eth.InitCS(10)
    If eth.InitializeDHCP(MacAddress) = False Then
        Log("Error connecting to network.")
        Return
    Else
        Log("Connected to network. My ip address: ", eth.LocalIp)
    End If
    timer1.Initialize("SEND0", 100)
    Connect(0)
End Sub
 
Status
Not open for further replies.
Top