Here up you can see an Arduino Nano v3 connected to the ethernet through an Enc28j60 breakout board powered directly from the USB. As you can see from the USB power meter tool the power consume is about 0.14A that is under 0.5A max of the standard pc USB ports. This current need came primarily from the Enc28j60 chip, while the Atmega328 is really low in power consumption. A separate voltage regulator using the AMS1117 3.3 regulates the input 5V to 3.3V for the purpose of the Enc28j60 Vcc while the SPI interface is 5V tolerant.
example | description |
---|---|
Basic (static ip) | Basic networking using static ip address |
Basic (dynamic) | Basic networking using dynamic ip address |
SRUDP | About SRUDP protocol |
SRUDP (echo client) | Echo client using SRUDP protocol |
SRUDP (echo server) | Echo server using SRUDP protocol |
SRUDP-TCP-Bridge | Connect to an SRUDP Arduino server through telnet using an SRUDP-TCP-Bridge application |
Arduino Servo | Drive arduino from C# using Arduino Servo Client |
To install the library just clone this git repository into your Documents/Arduino/libraries folder. All code excerpts in this page are parts of the SearchAThing.Arduino.Enc28j60.Examples release under MIT license by Lorenzo Delana (C) 2016.
//===========================================================================
// EXAMPLE : ex01-basic-static.ino
//===========================================================================
// Setup()
// - Allocate the enc28j60 driver
// - Allocate the network infrastructure manager
// - Set static-ip-mode parameters
// - Query a name through the dns server
// Loop()
// - Maintenance loop routine to keep working default packet handlers
// (arp,icmp,...)
//---------------------------------------------------------------------------
// Suggested defines for this example
//---------------------------------------------------------------------------
// SEARCHATHING_DISABLE;DEBUG;DEBUG_ASSERT;DPRINT_SERIAL
//
// SearchAThing.Arduino debug macro definitions
#include <SearchAThing.Arduino.Utils\DebugMacros.h>
//---------------------------------------------------------------------------
// Libraries
//---------------------------------------------------------------------------
#include <MemoryFree.h>
#include <SPI.h>
#include <SearchAThing.Arduino.Utils\Util.h>
using namespace SearchAThing::Arduino;
#include <SearchAThing.Arduino.Net\Checksum.h>
using namespace SearchAThing::Arduino::Net;
#include <SearchAThing.Arduino.Net\EthNet.h>
#include "Driver.h"
using namespace SearchAThing::Arduino::Enc28j60;
//---------------------------------------------------------------------------
// Global variables
//---------------------------------------------------------------------------
// network card driver
EthDriver *drv;
// network manager
EthNet *net;
//---------------------------------------------------------------------------
// Setup
//---------------------------------------------------------------------------
void setup()
{
// init
{
// network card init ( mac = 00:00:6c:00:00:[01] )
drv = new Driver(PrivateMACAddress(1));
// network manager init [static-mode]
net = new EthNet(drv, RamData::FromArray(IPV4_IPSIZE, 192, 168, 0, 40));
// static network parameters
net->SetNetmask(RamData::FromArray(IPV4_IPSIZE, 255, 255, 255, 0));
net->SetGateway(RamData::FromArray(IPV4_IPSIZE, 192, 168, 0, 1));
net->SetDns(RamData::FromArray(IPV4_IPSIZE, 8, 8, 8, 8));
net->SetBroadcastAddress(RamData::FromArray(IPV4_IPSIZE, 192, 168, 0, 255));
}
DPrint(F("MAC\t")); DPrintHexBytesln(net->MacAddress());
DPrint(F("IP\t")); DPrintBytesln(net->IpAddress());
DPrintln(F("setup done"));
DNewline();
DPrint(F("github ip = ")); DPrintBytesln(net->ResolveIP("github.com"));
PrintFreeMemory();
}
//---------------------------------------------------------------------------
// Loop
//---------------------------------------------------------------------------
void loop()
{
net->Receive(); // receive packet ( if any )
net->FlushRx(); // process packet using registered default handlers, then discard it
}
Program size: 13.752 bytes (used 45% of a 30.720 byte maximum) (4,84 secs) Minimum Memory Usage: 66 bytes (3% of a 2048 byte maximum)
MAC 00-00-6c-00-00-01
IP 192.168.0.40
setup done
github ip = 192.30.252.128
free blk=1014 frg=1151
- initialize the nic card driver using a private MAC address
- initialize the network subsystem using the driver and the static ip ( 192.168.0.40 )
- sets static network parameters
- netmask : 255.255.255.0
- gateway : 192.168.0.1
- dns : 8.8.8.8
- broadcast : 192.168.0.255
- resolve the "github.com" name using an internet dns through the local gateway due to the fact that the ip AND netmask != network address.
//======================================================================
// EXAMPLE : ex02-basic-dhcp.ino
//======================================================================
// Setup()
// - Allocate the enc28j60 driver
// - Allocate the network infrastructure manager
// - Set dynamic-ip-mode parameters
// - Query a name through the dns server
// Loop()
// - Maintenance loop routine to keep working default packet handlers (arp,icmp,...)
//----------------------------------------------------------------------
// Suggested defines for this example
//----------------------------------------------------------------------
// SEARCHATHING_DISABLE;DEBUG;DEBUG_ASSERT;DPRINT_SERIAL;USE_DHCP
//
// SearchAThing.Arduino debug macro definitions
#include <SearchAThing.Arduino.Utils\DebugMacros.h>
//----------------------------------------------------------------------
// Libraries
//----------------------------------------------------------------------
#include <MemoryFree.h>
#include <SPI.h>
#include <SearchAThing.Arduino.Utils\Util.h>
using namespace SearchAThing::Arduino;
#include <SearchAThing.Arduino.Net\Checksum.h>
using namespace SearchAThing::Arduino::Net;
#include <SearchAThing.Arduino.Net\EthNet.h>
#include "Driver.h"
using namespace SearchAThing::Arduino::Enc28j60;
//----------------------------------------------------------------------
// Global variables
//----------------------------------------------------------------------
// network card driver
EthDriver *drv;
// network manager
EthNet *net;
//----------------------------------------------------------------------
// Setup
//----------------------------------------------------------------------
void setup()
{
// init
{
// network card init ( mac = 00:00:6c:00:00:[01] )
drv = new Driver(PrivateMACAddress(1));
// network manager init [dynamic-mode]
net = new EthNet(drv);
}
DPrint(F("MAC\t")); DPrintHexBytesln(net->MacAddress());
net->PrintSettings(); // print network settings
DPrintln(F("setup done"));
DNewline();
DPrint(F("github ip = ")); DPrintBytesln(net->ResolveIP("github.com"));
PrintFreeMemory();
}
//----------------------------------------------------------------------
// Loop
//----------------------------------------------------------------------
void loop()
{
net->Receive(); // receive packet ( if any )
net->FlushRx(); // process packet using registered default handlers, then discard it
}
Program size: 16.388 bytes (used 53% of a 30.720 byte maximum) (1,11 secs) Minimum Memory Usage: 92 bytes (4% of a 2048 byte maximum)
MAC 00-00-6c-00-00-01
IP 192.168.0.40
HOST arduinotest.searchathing.com
DOMAIN searchathing.com
GW 192.168.0.1
BRD 192.168.0.255
DNS 192.168.0.1
NM 255.255.255.0
LEASE 600 (secs)
setup done
github ip = 192.30.252.120
free blk=933 frg=1070
- initialize the nic card driver using a private MAC address
- initialize the network subsystem using the driver and dynamic dhcp
- print current network settings
- resolve the "github.com" name
Information about this protocol can be found here
To run the SRUDP echo client on the Arduino successfully there is the need of a party server that can be another 2th Arduino running the SRUDP server or for simplicity you can use another VS instance running the SRUDP echo server app using C#. To start SRUDP server app in C#:
- clone the SearchAThing.Net and SearchAthing.Net.Apps projects from github
- open the Net.Apps project and right click on the SearchAthing.Net.SRUDP.EchoServer → Set as Startup Project
- set your pc ip address in the EchoServer.cs
- hit F5 and accept the firewall rule to allow local connections
//===========================================================================
// EXAMPLE : ex03-srudp-echo-client.ino
//===========================================================================
// Setup()
// - Allocate the enc28j60 driver
// - Allocate the network infrastructure manager
// - SRUDP client
// - Connect to remote endpoint
// - Send Data and received back
// - Disconnect
// Loop()
// - Maintenance loop routine to keep working default packet handlers
// (arp,icmp,...)
//---------------------------------------------------------------------------
// Suggested defines for this example
//---------------------------------------------------------------------------
// SEARCHATHING_DISABLE;DEBUG;DPRINT_SERIAL;USE_DHCP
//
// SearchAThing.Arduino debug macro definitions
#include <SearchAThing.Arduino.Utils\DebugMacros.h>
//---------------------------------------------------------------------------
// Libraries
//---------------------------------------------------------------------------
#include <MemoryFree.h>
#include <SPI.h>
#include <SearchAThing.Arduino.Utils\Util.h>
using namespace SearchAThing::Arduino;
#include <SearchAThing.Arduino.Net\EthNet.h>
using namespace SearchAThing::Arduino::Net;
#include <SearchAThing.Arduino.Net\SRUDP_Client.h>
using namespace SearchAThing::Arduino::Net::SRUDP;
#include "Driver.h"
using namespace SearchAThing::Arduino::Enc28j60;
//---------------------------------------------------------------------------
// Global variables
//---------------------------------------------------------------------------
// network card driver
EthDriver *drv;
// network manager
EthNet *net;
//---------------------------------------------------------------------------
// Setup
//---------------------------------------------------------------------------
void setup()
{
{
// init
{
// network card init ( mac = 00:00:6c:00:00:[01] )
drv = new Driver(PrivateMACAddress(1));
// network manager init [dynamic-mode]
net = new EthNet(drv);
}
DPrint(F("MAC\t")); DPrintHexBytesln(net->MacAddress());
net->PrintSettings(); // print network settings
DPrintln(F("setup done"));
DNewline();
}
//
auto remoteIp = RamData::FromArray(IPV4_IPSIZE, 192, 168, 0, 80);
auto remotePort = 50000;
Client client(net, IPEndPoint(remoteIp, remotePort));
client.Connect();
if (client.State() != ClientState::Connected)
{
DPrintln(F("unable to connect"));
}
else
{
auto i = 0;
while (i < 200)
{
char buf[50];
sprintf(buf, "Hi, there [%d]", i);
if (client.Write(RamData(buf)))
{
RamData res;
if (client.Read(res) == TransactionResult::Successful)
{
DPrint(F("received=[")); res.PrintAsChars(); DPrintln(F("]"));
++i;
}
}
else
DPrintln(F("write failed"));
}
client.Disconnect();
}
PrintFreeMemory();
}
//---------------------------------------------------------------------------
// Loop
//---------------------------------------------------------------------------
void loop()
{
net->Receive(); // receive packet ( if any )
net->FlushRx(); // process packet using registered default handlers, then
// discard it
}
Program size: 18.512 bytes (used 60% of a 30.720 byte maximum) (5,00 secs) Minimum Memory Usage: 96 bytes (5% of a 2048 byte maximum)
MAC 00-00-6c-00-00-01
IP 192.168.0.40
HOST arduinotest.searchathing.com
DOMAIN searchathing.com
GW 192.168.0.1
BRD 192.168.0.255
DNS 192.168.0.1
NM 255.255.255.0
LEASE 600 (secs)
setup done
received=[Hi, there [0]]
received=[Hi, there [1]]
received=[Hi, there [2]]
received=[Hi, there [3]]
...
received=[Hi, there [199]]
free blk=828 frg=954
- Setup network using dhcp.
- Connect the SRUDP server 192.168.0.80:50000
- Write a test string and print the received echo result for 200 times.
- Disconnect from the server.
If you have Wireshark installed you can view at the SRUDP protocol just by copy the srudp.lua file ( that you can find in the SearchAThing.Net/SRUDP folder ) into the dissector folder C:\Program Files\Wireshark\plugins\2.0.2
After that the dissector automatically enable for port=50000 so for the above test it will show something like this:
In the Info column there is information about the SRUDP protocol ID and type of packet while in the detail there is information about Data. Consider that each part maintain its own TX ID while the other part use the received ID only when respond with ACKs.
To run the SRUDP echo server on the Arduino successfully there is the need of a party client that can be another 2th Arduino running the SRUDP client or for simplicity you can use another VS instance running the SRUDP echo client app using C#. To start SRUDP client app in C#:
- clone the SearchAThing.Net and SearchAthing.Net.Apps projects from github
- open the Net.Apps project and right click on the SearchAthing.Net.SRUDP.EchoClient → Set as Startup Project
- set the arduino ip address in the EchoClient.cs
- hit F5
//===========================================================================
// EXAMPLE : ex04-srudp-echo-server.ino
//===========================================================================
// Setup()
// - Allocate the enc28j60 driver
// - Allocate the network infrastructure manager
// - SRUDP listener
// - Create a listener using current IP address as server endpoint
// - Associate an handler for client connections
// - Activate listener process
// - Register the listener process to the network subsystem
// Loop()
// - Maintenance loop routine to keep working default packet handlers
// (arp, icmp, ...)
// - listener process is included because registered into the network
// subsystem
//---------------------------------------------------------------------------
// Suggested defines for this example
//---------------------------------------------------------------------------
// SEARCHATHING_DISABLE;DEBUG;DPRINT_SERIAL;USE_DHCP
//
// SearchAThing.Arduino debug macro definitions
#include <SearchAThing.Arduino.Utils\DebugMacros.h>
//---------------------------------------------------------------------------
// Libraries
//---------------------------------------------------------------------------
#include <MemoryFree.h>
#include <SPI.h>
#include <SearchAThing.Arduino.Utils\Util.h>
using namespace SearchAThing::Arduino;
#include <SearchAThing.Arduino.Net\EthNet.h>
using namespace SearchAThing::Arduino::Net;
#include <SearchAThing.Arduino.Net\SRUDP_Client.h>
using namespace SearchAThing::Arduino::Net::SRUDP;
#include "Driver.h"
using namespace SearchAThing::Arduino::Enc28j60;
//---------------------------------------------------------------------------
// Global variables
//---------------------------------------------------------------------------
// network card driver
EthDriver *drv;
// network manager
EthNet *net;
//---------------------------------------------------------------------------
// Setup
//---------------------------------------------------------------------------
void setup()
{
// init
{
{
// network card init ( mac = 00:00:6c:00:00:[01] )
drv = new Driver(PrivateMACAddress(1));
// network manager init [dynamic-mode]
net = new EthNet(drv);
}
DPrint(F("MAC\t")); DPrintHexBytesln(net->MacAddress());
net->PrintSettings(); // print network settings
DPrintln(F("setup done"));
DNewline();
}
//
IPEndPoint remoteEndPoint = IPEndPoint(net->IpAddress(), 50000);
while (true)
{
auto client = Client::Listen(net, remoteEndPoint);
DPrint(F("client connected: ")); client.RemoteEndPoint().ToString().PrintAsChars(); DNewline();
while (client.State() == ClientState::Connected)
{
RamData data;
if (client.Read(data) == TransactionResult::Successful)
{
DPrint(F("Received [")); data.PrintAsChars(); DPrintln(F("]"));
while (client.Write(data) != TransactionResult::Successful)
{
DPrintln(F("write failed"));
}
}
else
DPrintln(F("read failed"));
}
DPrintln(F("client received a disconnect"));
PrintFreeMemory();
}
}
//---------------------------------------------------------------------------
// Loop
//---------------------------------------------------------------------------
void loop()
{
//net->Receive(); // receive packet ( if any )
//net->FlushRx(); // process packet using registered default handlers,
// then discard it
}
Program size: 17.528 bytes (used 57% of a 30.720 byte maximum) (0,73 secs) Minimum Memory Usage: 96 bytes (5% of a 2048 byte maximum)
MAC 00-00-6c-00-00-01
IP 192.168.0.40
HOST arduinotest.searchathing.com
DOMAIN searchathing.com
GW 192.168.0.1
BRD 192.168.0.255
DNS 192.168.0.1
NM 255.255.255.0
LEASE 600 (secs)
setup done
client connected: 192.168.0.80:57792
Received [Hi 0]
Received [Hi 1]
Received [Hi 2]
Received [Hi 3]
...
Received [Hi 199]
read failed
client received a disconnect
free blk=893 frg=1036
- Setup network using dhcp on the ip:50000
- Print information about connected remote client ip:port
- Loop while client connected
- Read and write back read data
To interact with an SRUDP arduino server through tcp telnet there is the need for a bridge application that can be found in the SearchAThing.Net.Apps. This application is design to run Windows or Linux (mono) by command line:
SearchAThing.Net.SRUDP.TCPBridge.ServerApp.exe <srv-ip> <srv-port> [srudp-rx-buffer-size]
The srv-ip and srv-port refer to a local server connection that the bridge will create to listen for TCP connections using follow SRUDP-TCP-Bridge protocol specifications. To run the bridge:
- Open the solution and select as Startup Project the SearchAThing.Net.SRUDPTCPBridge.Server
- Set the command line through the Project Properties ( in Debug mode ) under the Debug -> Command line arguments set . For example "192.168.0.80 51000".
- Hit F5 and accept the firewall rule for the local connections
Here is assumed that the Arduino run the SRUDP-Echo-Server ( 192.168.0.40:5000 ) and a pc in the network is running the SRUDP-TCP-Bridge ( 192.168.0.80:51000 ). I use telnet from cygwin to have the echo working by default.
$ telnet 192.168.0.80 51000
Trying 192.168.0.80...
Connected to 192.168.0.80.
Escape character is '^]'.
help
SRUDP TCP Wrapper v.0.5.0 info available at https://searchathing.com/?p=829
vers
OK
0.5.0
quit
OK
Connection closed by foreign host.
$ telnet 192.168.0.80 51000
Trying 192.168.0.80...
Connected to 192.168.0.80.
Escape character is '^]'.
conn 192.168.0.40 50000
OK
waln test1
OK
rbin
OK
5
test1quit
OK
Connection closed by foreign host.
MAC 00-00-6c-00-00-01
IP 192.168.0.40
HOST arduinotest.searchathing.com
DOMAIN searchathing.com
GW 192.168.0.1
BRD 192.168.0.255
DNS 192.168.0.1
NM 255.255.255.0
LEASE 600 (secs)
setup done
client connected: 192.168.0.80:59351
Received [test1]
read failed
...
read failed
client received a disconnect
free blk=893 frg=1036
item | description |
---|---|
telnet 192.168.0.80 51000 |
Connect to the SRUDP-TCP-Bridge |
conn 192.168.0.40 50000 |
Connect to the Arduino SRUDP echo server |
waln test1 |
Write an ASCII line "test1" |
rbin |
Read binary data. The use of "raln" not work here cause sent message not contains the newline and the received back message could not identified as a line without that, so here rbin ensure to read data even there is no newline |
quit |
close connection |
The arduino SRUDP server read failed messages are caused by the SRUDP echo server that expects some message until we issue the quit command to close the connection.
Arduino servo is an program for arduino that implement Servo commands over SRUDP protocol. There is also a C# client that allow you to connect any Arduino Servo thing through ethernet using the TcpClient. In order to do this there is the need to run an instance of a SRUDP-TCP-Bridge.
Control an arduino over the network allow you to read or write the Arduino Servo implemented functions. Arduino Servo is an engine for arduino that speak to outside world through the SRUDP protocol. Typographical conventions:
<nl>
represents a newline
To issue commands and read results use SRUDP read and write functions available in a client implementation of the protocol. Currently and arduino and a C# implementation of the SRUDP protocol already exists.
States from how much time the device is up.
Syntax
uptime<nl>
Return value
Retrieve the uptime in format days.milliseconds
OK<nl><days>.<milliseconds><nl>
Retrieve the quantity of available RAM in the Arduino. If is 0 then the total fragment memory sum is reported, otherwise (eg. is 1) the maximum contiguous block size is returned
Syntax
free <type><nl>
Return value
Return the sum of fragmented available ram if <type was 0, the maximum contiguous block otherwise.
OK<nl><free-ram-bytes><nl>
Set the port where the ds18b20 temperature sensor are connected. It must be a digital port
Syntax
ds18b20_setup <port><nl>
Return value
ds18b20 port setup completed
OK<nl>
Retrieve the count of ds18b20 sensor connected to the port configured.
Syntax
ds18b20_count<nl>
Return value
Return the quantity of temperature sensor detected
OK<nl><count><nl>
Error occurred: MissingSetup
ERR <err-msg><nl>
Retrieve the temperature (Celsius) of the sensor with given index ( first = 0 ).
Syntax
ds18b20_get <idx><nl>
Return value
Return the temperature (Celsius) converted from the device at the given index
OK<nl><temperature_C><nl>
Set a digital port mode for input ( = IN ) or output ( = OUT )
Syntax
digital_setup <port> <mode><nl>
Example
Set the D3 as output
digital_setup 3 OUT
Return value
Operation completed.
OK<nl>
An occurred: InvalidSyntax
ERR <err-msg><nl>
Set value of given digital port
Syntax
digital_write <port> <value><nl>
Example
Set the D3 to value 255
digital_setup 3 255
Return value
Operation completed.
OK<nl>
An occurred: InvalidSyntax
ERR <err-msg><nl>
Get value of given digital port
Syntax
digital_read <port><nl>
Return value
Return the digital port current value.
OK<nl><value><nl>
An occurred: InvalidSyntax
ERR <err-msg><nl>
Get value of given analog port. Note: use numeric value to specify the ( ex. A2 = 2 ).
Syntax
analog_read <port><nl>
Return value
Return the analog port current value.
OK<nl><value><nl>
An occurred: InvalidSyntax
ERR <err-msg><nl>
Get value of given analog port for as many samples specified. Note: use numeric value to specify the ( ex. A2 = 2 ).
Syntax
analog_read_pack <port> <samples-count><nl>
Return value
Each 10bit sample will be stored in two bytes, so will be 2x bytes
OK<nl><data-pack>
An occurred: InvalidSyntax, OutOfMemory, SamplesOutOfPkt
ERR <err-msg><nl>
using SearchAThing.Net.SRUDP.TCPBridge.ServoClient;
using System;
namespace SearchAThing.Arduino.Servo.ClientTest
{
class Program
{
static void Main(string[] args)
{
var client = new ServoClient("192.168.0.80", 51000, "192.168.0.40", 50000);
while (true)
{
var a = client.AnalogRead(0);
Console.SetCursorPosition(0, 0);
Console.WriteLine($"a={a} v={a / 1023.0 * 4.52}");
}
}
}
}
- establish a connection to an Arduino servo 192.168.0.40:50000 by using the SRUDP-TCP-Bridge 192.168.0.80:51000
- forever loop
- read value from adc and convert to voltage