Simple data transfer network with ENC28J60/Arduino (Uno)

Hi!

I hope somebody can help me and I'm sorry if I use the wrong terms!

I'm trying to build a huge network (around 10 Arduinos) connected by ethernet cable RJ45 (straight or crossover?).
Why ethernet cable? Because the transmission distance will be around 100m.
Also I will try to power it by PoE so the network switch will have PoE (optional).

So, I found a lot of guides on building a web server but it really confuses me. I just want to send small data from one (slave) arduino to (master) arduino and back-and-forth. I don't need any internet connection or webserver.

Maybe this drawing helps with the idea:

Is this feasible?

I tried using the EtherCard and EthernetENC library but nothing works. With Ethercard I get this output:

[testDHCP]
MAC: 74:69:69:2D:30:31
Setting up DHCP
DHCP failed
My IP: 0.0.0.0
Netmask: 0.0.0.0
GW IP: 0.0.0.0
DNS IP: 0.0.0.0

People also recommended to use UDP but I don't understand it. Why do I still need an IP address etc.?

Thanks in advance for any help! I hope this project works!

can you give more details of what you wish to do with the data when it is received?
you mention a webserver? how would you connect to the webserver? using another ethernet connection?
I am none too sure that a nano would support 10 concurrent TCP connections - you may require something like an ESP32 or even a Raspberry pi

TCP is a reliable protocol with flow control and error correction
UDP is a connectionless protocol- the client sends a datagram which may be received maybe not (similar to posting a letter - it may arrive it may not)

Sorry for mentioning a web server. I was just trying to highlight that there is so much information about ENC28J60 and webservers but I don't need it. I just want to use the property of ethernet/RJ45 cable to have a wired transmission distance of 100m.

The idea is to have sensors (Arduino slaves) collect small data and then send them to the central control (Arduino master) and it will just display the information on a display.

The network switch is to merge all the data lines of the slaves to the master. Please correct me if this is wrong.

I was going to use Arduino Nano but I think it's better to use Arduino Uno.

So tl,dr I want to have a "I2C network" but with very long data lines.

Take a look at CAN, It will work great and is much simpler. You would then need to switch to a bus configuration instead of the star format unless you use a special CAN switch designed to do this. Cory Fowler has posted a library that by using the two examples send and receive you can accomplish what you want. I have been experimenting with CAT5 and can where pair 1 goes to the sensor, pair 2 comes back. at the hub the next cable is connected where pair 2 from the previous connects to pair 1 of the outgoing. Can modules can be purchased for less then $5US from many china suppliers. In the end that leaves two pair for power.

both use the ATmega328P processor so no different in performance - the UNO has more pins available
an alternative to a wired network is long range low power wireless such as LoRa - have a look at post decimals-strings-and-lora where nanos equiped with sensors transmit data to a central master node for display

Thank you for the answer. This sounds great but I "have to" use a star topology otherwise I'd theoretically need 1km bus length which is not feasible.

Oh, that is really helpful information! I will use and Arduino Nano then. And I have to use a wired network. Do you think this idea is even possible with ENC28J60?

Ethernet is designed to work over long distances - use good quality cable
you considered using PoE - would you also attempt to power the nano with the PoE? if so check it works otherwise you need to power the nano speratly
maybe worth looking at Mini ENC28J60 Webserver module Ethernet Shield board for Arduino Nano
what will the remote nanos be doing?
would UDP be OK? is it critical if you loose the odd packet?
would the master poll the remote devices or would they transmit at regular intervals

That module is sick! I will buy some of those.

And I will use a CAT6a cable. I've read somewhere it's a good cable to use with PoE.
And yes, I'd like to power the Nano with PoE but I was thinking about using PoE splitter/injector because the ENC28J60 doesn't support PoE. Am I wrong?
I didn't include splitter/injector into the drawing because it'd overcomplicate my drawing and it's optional. Awesome but optional.

So, the idea is to have something like trip wires installed everywhere and when it gets triggered the remote (slave) Nano sends data to the central (master) Nano. And occasionally the master makes a request to the remote Nano to test if it still works.

I think I have a fundamental misunderstanding of ENC28J60.

You NEED to have a connection to the Internet otherwise no matter the connection/wiring it doesn't work. I thought you can just have a "standalone network" made with Arduinos and a network switch but this is not feasible. Please correct me if this is wrong.

at present I am running some UDP tests on a couple of ENC28J60 modules attached to a router without an internet connection

I'm so confused lol. But thanks for the answer.

I will do some more trial and error and see if I get my head straight.

UDP chat program for ENC28J60
run two copies change localIP and remoteIP to match

// UDP chat program using  ENC28J60  tested on UNO and Nano
// **** change IP addresses and ports to suit requirements *****

#include <EthernetENC.h>  // for  ENC28J60
#include <EthernetUdp.h>  // for UDP

// *****   IP of this machine and remote machine *********
IPAddress localIP(192, 168, 1, 177);
IPAddress remoteIP(192, 168, 1, 176);

// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 10000;   // local port to listen on
unsigned int remotePort = 10000;  // remote port to transmiit too

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
    ;
  Serial.println("\nEthernet UDP chat program");
  // Check for Ethernet hardware present

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);  // Most Arduino shields
                      //Ethernet.init(5);   // MKR ETH Shield
                      //Ethernet.init(0);   // Teensy 2.0
                      //Ethernet.init(20);  // Teensy++ 2.0
                      //Ethernet.init(15);  // ESP8266 with Adafruit FeatherWing Ethernet
                      //Ethernet.init(33);  // ESP32 with Adafruit FeatherWing Ethernet
  //displayMACaddress(mac);
  mac[5] = localIP[3];  // change default MAC address
  displayMACaddress(mac);
  // start the Ethernet
  Ethernet.begin(mac, localIP);
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) delay(1);  // do nothing, no point running without Ethernet hardware
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  Udp.begin(localPort);  // start UDP
  Serial.print("Ethernet UDP started ");
  displayIPaddress(localIP, localPort);
  //Serial.println(UDP_TX_PACKET_MAX_SIZE);
}

void loop() {
  Udp.begin(localPort);
  // if Serial text entered transmit as a datagram
  if (Serial.available()) {
    Udp.begin(localPort);
    char text[20] = { 0 };
    Serial.readBytesUntil('\n', text, 24);
    Serial.print("Transmitting to ");
    displayIPaddress(remoteIP, remotePort);
    Serial.println(text);
    Udp.beginPacket(remoteIP, remotePort);  // transmit datagram
    Udp.print(text);
    Udp.endPacket();
  }
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    displayIPaddress(Udp.remoteIP(), Udp.remotePort());
    // read the packet into packetBuffer
    char packetBuffer[100] = { 0 };      // buffer to hold incoming packet,
    Udp.read(packetBuffer, packetSize);  //UDP_TX_PACKET_MAX_SIZE);     // receive datagram
    Serial.print("Contents: ");
    Serial.println(packetBuffer);
    // if (strcmp(packetBuffer, "OK") != 0) {
    // send a reply to the IP address and port that sent us the packet we received
    //   Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    // Udp.write("OK");
    //  Udp.endPacket();
    //}
  }
  delay(10);
}

// print IPAdress and port
void displayIPaddress(const IPAddress address, unsigned int port) {
  Serial.print(" IP ");
  for (int i = 0; i < 4; i++) {
    Serial.print(address[i], DEC);
    if (i < 3) Serial.print(".");
  }
  Serial.print(" port ");
  Serial.println(port);
}

void displayMACaddress(byte address[]) {
  Serial.print("MAC address ");
  for (int i = 0; i < 6; i++) {
    Serial.print("0x");    
    Serial.print(address[i], HEX);
    if (i < 5) Serial.print(".");
  }
  Serial.println();
}

serial monitor output of IP 192.168.1.177

Ethernet UDP chat program
MAC address 0xDE.0xAD.0xBE.0xEF.0xFE.0xB1
Ethernet cable is not connected.
Ethernet UDP started  IP 192.168.1.177 port 10000
Transmitting to  IP 192.168.1.176 port 10000
hello from 177 test 1

Transmitting to  IP 192.168.1.176 port 10000
from 177 test2

Received packet of size 15
From  IP 192.168.1.176 port 10000
Contents: hello from 176

Received packet of size 24
From  IP 192.168.1.176 port 10000
Contents: from 176 test 2 12345678
Received packet of size 3
From  IP 192.168.1.176 port 10000
Contents: 90

Transmitting to  IP 192.168.1.176 port 10000
hello from 177 test 3 ab
Transmitting to  IP 192.168.1.176 port 10000
cdef

Serial monitor output of 192.168.1.176

Ethernet UDP chat program
MAC address DE.AD.BE.EF.FE.B0
Ethernet cable is not connected.
Ethernet UDP started  IP 192.168.1.176 port 10000
Received packet of size 22
From  IP 192.168.1.177 port 10000
Contents: hello from 177 test 1

Received packet of size 15
From  IP 192.168.1.177 port 10000
Contents: from 177 test2

Transmitting to  IP 192.168.1.177 port 10000
hello from 176

Transmitting to  IP 192.168.1.177 port 10000
from 176 test 2 12345678
Transmitting to  IP 192.168.1.177 port 10000
90

Received packet of size 24
From  IP 192.168.1.177 port 10000
Contents: hello from 177 test 3 ab
Received packet of size 5
From  IP 192.168.1.177 port 10000
Contents: cdef

Received packet of size 28
From  IP 192.168.1.68 port 62397
Contents: hello from Java on PC test 1
Received packet of size 25
From  IP 192.168.1.68 port 61422
Contents: hello from pc java test 2

note that 192.168.1.176 is also receiving UDP datagrams from a Java program running on a PC
output of Java program

F:\temp>java UDPchat
chat program: IP address BB-DELL2/192.168.1.68 port 10000
hello from Java on PC test 1
Sending to 192.168.1.176 socket 10000 data: hello from Java on PC test 1
hello from pc java test 2
Sending to 192.168.1.176 socket 10000 data: hello from pc java test 2

the Java program

// UDPchat.java - simple peer-to-peer chat program using UDP
//           - given remote IP address can send strings using UDP datagrams 
//           - will also wait for datagrams and display contents
// remote IP and port are specified via command line - default IP is 127.0.0.1 (i.e. localhost) and port is 1000  
//
// e.g. to send datagrams to IP 146.227.59.130 port 1006
// java chat 146.227.59.130 1006

import java.io.*;
import java.util.*;
import java.net.*;

public class UDPchat extends Thread
{
   private final static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   int port=10000;//999;//10001;// 100006                             // port to send/receive datagrams on
   String remoteIPaddress= "192.168.1.176";//"169.254.144.20";//("192.168.1.8");//127.0.0.1");      // IP to send datagrams

   // constructor, parameter is command line parameters
   public UDPchat(String args[]) throws Exception
    {
    // get remote IP address and port from command line parameters
    if (args.length > 0)    remoteIPaddress =  (args[0]);           // get IPaddress
    if (args.length > 1)    port = Integer.parseInt(args[1]);        // get port number
    System.out.println("chat program: IP address " + InetAddress.getLocalHost().toString() + " port " + port );
    
    start();        // start thread to receive and display datagrams

    // loop waiting for keyboard input, send datagram to remote IP                
    while(true)
      try
        {
        String s = in.readLine();                       // read a String
        System.out.println("Sending to " + remoteIPaddress + " socket " + port + " data: " + s);
        byte[] data = s.getBytes();                                     // convert to byte array
        DatagramSocket theSocket = new DatagramSocket();                // create datagram socket and the datagram
        DatagramPacket   theOutput = new DatagramPacket(data, data.length, InetAddress.getByName(remoteIPaddress), port);
        theSocket.send(theOutput);                                      // and send the datagram
       }
      catch (Exception e) {System.out.println("Eroor sending datagram " + e);}
    }

   // thread run method, receives datagram and display contents as a string
   public void run()                
        {
          try
              {
              // open DatagramSocket to receive 
              DatagramSocket ds = new DatagramSocket(port);
              // loop forever reading datagrams from the DatagramSocket
              while (true)
                 {
                 byte[] buffer = new byte[65507];                       // array to put datagrams in
                 DatagramPacket dp = new DatagramPacket(buffer, buffer.length); // DatagramPacket to hold the datagram
                 ds.receive(dp);                                     // wait for next datagram
                 String s = new String(dp.getData(),0,dp.getLength());        // get contenets as a String
                 System.out.println("UDP datagram length " + s.length()+ "  from IP " + dp.getAddress() + " received: " + s );
                 }
              }
          catch (SocketException se) {System.err.println("chat error " + se); }
          catch (IOException se) {System.err.println("chat error " + se);}
          System.exit(1);                                                       // exit on error
        }


public static void main(String args[]) throws Exception
{
   UDPchat c=new UDPchat(args);
}

}

1 Like

I just thought you might like to know, this is from TI one of the transceiver makers.
Can baud rate cable length?
Texas Instruments has done some practical experiments years ago at different baud rates to test the maximum allowed cable lengths.
...
Maximum cable lengths.

Baud rate Maximum cable length
9600 500 ft
4800 1000 ft
2400 3000 ft
1 Like

I think that is wrong, but i'm no networking guru. From my limited knowledge on LANs, I don't see why you can't have a network switch and a bunch of Arduinos - aka a private wired network.

Is there something that you need that would require a connection to the wider internet - maybe access to a time server or the like?

a more realistic example transmitting BME280 sensor data over Ethernet
the BME280 data is tranmitted as a structure in binary, e.g.

// UDP_BME280_transmitter using  ENC28J60  to transmit BME280 data over Ethernet UDP
// **** change IP addresses and ports to suit requirements *****

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme;  // I2C

// structure to hold BME280 data
struct BME280Data {
  float temperature, pressure, humidity;
} BME280data;

#include <EthernetENC.h>  // for  ENC28J60
#include <EthernetUdp.h>  // for UDP

// *****   IP of this machine and remote machine *********
IPAddress localIP(192, 168, 1, 177);
IPAddress remoteIP(192, 168, 1, 176);

// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 10000;   // local port to listen on
unsigned int remotePort = 10000;  // remote port to transmiit too

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
    ;
  Serial.println("\nUDP_BME280_transmitter using  ENC28J60  to transmit BME280 data over Ethernet UDP");
  int status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1)
      ;
  }

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);    // Most Arduino shields
                        //displayMACaddress(mac);
  mac[5] = localIP[3];  // change default MAC address
  displayMACaddress(mac);
  // start the Ethernet
  Ethernet.begin(mac, localIP);
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) delay(1);  // do nothing, no point running without Ethernet hardware
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  Udp.begin(localPort);  // start UDP
  Serial.print("Ethernet UDP started ");
  displayIPaddress(localIP, localPort);
  //Serial.println(UDP_TX_PACKET_MAX_SIZE);
}

void loop() {
  // read BME sensor values every two seconds
  static long timer = millis() + 5000;
  if (millis() - timer > 2000) {
    printBE280();                                 // read and print BME280 data
    timer = millis();
    Udp.begin(localPort);
    Serial.print("Transmitting BME280 data to ");
    displayIPaddress(remoteIP, remotePort);       
    Serial.println();
    Udp.beginPacket(remoteIP, remotePort);        // transmit the data 
    Udp.write((char *)&BME280data, sizeof(BME280data));
    Udp.endPacket();
  }
   // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    displayIPaddress(Udp.remoteIP(), Udp.remotePort());
    // read the packet into packetBuffer
    char packetBuffer[100] = { 0 };      // buffer to hold incoming packet,
    Udp.read(packetBuffer, packetSize);  //UDP_TX_PACKET_MAX_SIZE);     // receive datagram
    Serial.print("Contents: ");
    Serial.println(packetBuffer);
     }
  delay(10);
}

// print IPAdress and port
void displayIPaddress(const IPAddress address, unsigned int port) {
  Serial.print(" IP ");
  for (int i = 0; i < 4; i++) {
    Serial.print(address[i], DEC);
    if (i < 3) Serial.print(".");
  }
  Serial.print(" port ");
  Serial.println(port);
}

void displayMACaddress(byte address[]) {
  Serial.print("MAC address ");
  for (int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(address[i], HEX);
    if (i < 5) Serial.print(".");
  }
  Serial.println();
}

void printBE280() {
  Serial.print("Temperature = ");
  Serial.print(BME280data.temperature = bme.readTemperature());
  Serial.println(" *C");

  // Convert temperature to Fahrenheit
  /*Serial.print("Temperature = ");
  Serial.print(1.8 * bme.readTemperature() + 32);
  Serial.println(" *F");*/

  Serial.print("Pressure = ");
  Serial.print(BME280data.pressure = bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(BME280data.humidity = bme.readHumidity());
  Serial.println(" %");

  Serial.println();
}

receiver reads a packet and displays the contents

// UDP_BME280_receiver using  ENC28J60  to receive BME280 data over Ethernet UDP
// **** change IP addresses and ports to suit requirements *****

#include <EthernetENC.h>  // for  ENC28J60
#include <EthernetUdp.h>  // for UDP

// *****   IP of this machine and remote machine *********
IPAddress localIP(192, 168, 1, 176);
IPAddress remoteIP(192, 168, 1, 177);

// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 10000;   // local port to listen on
unsigned int remotePort = 10000;  // remote port to transmiit too

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
    ;
  Serial.println("\nUDP_BME280_receiver using  ENC28J60 to receive BME280 data over Ethernet UDP");
  // Check for Ethernet hardware present

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);  // Most Arduino shields
  //displayMACaddress(mac);
  mac[5] = localIP[3];  // change default MAC address
  displayMACaddress(mac);
  // start the Ethernet
  Ethernet.begin(mac, localIP);
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) delay(1);  // do nothing, no point running without Ethernet hardware
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  Udp.begin(localPort);  // start UDP
  Serial.print("Ethernet UDP ready on ");
  displayIPaddress(localIP, localPort);
  //Serial.println(UDP_TX_PACKET_MAX_SIZE);
}

// structure to hold BME280 data
struct BME280Data {
  float temperature, pressure, humidity;
} BME280data;


void loop() {
  Udp.begin(localPort);
  // if there's BME280 data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    displayIPaddress(Udp.remoteIP(), Udp.remotePort());     // check packet is correct size
    if (packetSize == sizeof(BME280data)) {
      Serial.println("received BME data");
      // read the packet into packetBuffer
      Udp.read((char *)&BME280data, sizeof(BME280data));    // receive datagram
      printBE280();                                         // and dispay BME280 data
    }
  }
  delay(10);
}

// print IPAdress and port
void displayIPaddress(const IPAddress address, unsigned int port) {
  Serial.print(" IP ");
  for (int i = 0; i < 4; i++) {
    Serial.print(address[i], DEC);
    if (i < 3) Serial.print(".");
  }
  Serial.print(" port ");
  Serial.println(port);
}

void displayMACaddress(byte address[]) {
  Serial.print("MAC address ");
  for (int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(address[i], HEX);
    if (i < 5) Serial.print(".");
  }
  Serial.println();
}

void printBE280() {
  Serial.print("Temperature = ");
  Serial.print(BME280data.temperature);
  Serial.println(" *C");

  Serial.print("Pressure = ");
  Serial.print(BME280data.pressure);
  Serial.println(" hPa");

  Serial.print("Humidity = ");
  Serial.print(BME280data.humidity);
  Serial.println(" %");
  Serial.println();
}

transmitter serial monitor output

UDP_BME280_transmitter using  ENC28J60  to transmit BME280 data over Ethernet UDP
MAC address 0xDE.0xAD.0xBE.0xEF.0xFE.0xB1
Ethernet cable is not connected.
Ethernet UDP started  IP 192.168.1.177 port 10000
Temperature = 22.63 *C
Pressure = 1018.91 hPa
Approx. Altitude = -46.98 m
Humidity = 42.88 %

Transmitting BME280 data to  IP 192.168.1.176 port 10000

Temperature = 22.65 *C
Pressure = 1018.87 hPa
Approx. Altitude = -46.65 m
Humidity = 42.80 %

Transmitting BME280 data to  IP 192.168.1.176 port 10000

Temperature = 22.66 *C
Pressure = 1018.82 hPa
Approx. Altitude = -46.28 m
Humidity = 42.79 %

Transmitting BME280 data to  IP 192.168.1.176 port 10000

Temperature = 22.64 *C
Pressure = 1018.78 hPa
Approx. Altitude = -45.95 m
Humidity = 42.53 %

receiver serial monitor output

UDP_BME280_receiver using  ENC28J60 to receive BME280 data over Ethernet UDP
MAC address 0xDE.0xAD.0xBE.0xEF.0xFE.0xB0
Ethernet UDP ready on  IP 192.168.1.176 port 10000
Received packet of size 12
From  IP 192.168.1.177 port 10000
received BME data
Temperature = 22.63 *C
Pressure = 1018.91 hPa
Humidity = 42.88 %

Received packet of size 12
From  IP 192.168.1.177 port 10000
received BME data
Temperature = 22.65 *C
Pressure = 1018.87 hPa
Humidity = 42.80 %

Received packet of size 12
From  IP 192.168.1.177 port 10000
received BME data
Temperature = 22.66 *C
Pressure = 1018.82 hPa
Humidity = 42.79 %

Received packet of size 12
From  IP 192.168.1.177 port 10000
received BME data
Temperature = 22.64 *C
Pressure = 1018.78 hPa
Humidity = 42.53 %
1 Like

I've tried the "UDP chat program for ENC28J60" code and changed the CS pin to 53 due to Arduino Mega 2560. This is the only thing I changed about the code:

// UDP chat program using  ENC28J60  tested on UNO and Nano
// **** change IP addresses and ports to suit requirements *****

#include <EthernetENC.h>  // for  ENC28J60
#include <EthernetUdp.h>  // for UDP

// *****   IP of this machine and remote machine *********
IPAddress localIP(192, 168, 1, 177);
IPAddress remoteIP(192, 168, 1, 176);

// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 10000;   // local port to listen on
unsigned int remotePort = 10000;  // remote port to transmiit too

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
    ;
  Serial.println("\nEthernet UDP chat program");
  // Check for Ethernet hardware present

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(53);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH Shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit FeatherWing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit FeatherWing Ethernet
  //displayMACaddress(mac);
  mac[5] = localIP[3];  // change default MAC address
  displayMACaddress(mac);
  // start the Ethernet
  Ethernet.begin(mac, localIP);
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) delay(1);  // do nothing, no point running without Ethernet hardware
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  Udp.begin(localPort);  // start UDP
  Serial.print("Ethernet UDP started ");
  displayIPaddress(localIP, localPort);
  //Serial.println(UDP_TX_PACKET_MAX_SIZE);
}

void loop() {
  Udp.begin(localPort);
  // if Serial text entered transmit as a datagram
  if (Serial.available()) {
    Udp.begin(localPort);
    char text[20] = { 0 };
    Serial.readBytesUntil('\n', text, 24);
    Serial.print("Transmitting to ");
    displayIPaddress(remoteIP, remotePort);
    Serial.println(text);
    Udp.beginPacket(remoteIP, remotePort);  // transmit datagram
    Udp.print(text);
    Udp.endPacket();
  }
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    displayIPaddress(Udp.remoteIP(), Udp.remotePort());
    // read the packet into packetBuffer
    char packetBuffer[100] = { 0 };      // buffer to hold incoming packet,
    Udp.read(packetBuffer, packetSize);  //UDP_TX_PACKET_MAX_SIZE);     // receive datagram
    Serial.print("Contents: ");
    Serial.println(packetBuffer);
    // if (strcmp(packetBuffer, "OK") != 0) {
    // send a reply to the IP address and port that sent us the packet we received
    //   Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    // Udp.write("OK");
    //  Udp.endPacket();
    //}
  }
  delay(10);
}

// print IPAdress and port
void displayIPaddress(const IPAddress address, unsigned int port) {
  Serial.print(" IP ");
  for (int i = 0; i < 4; i++) {
    Serial.print(address[i], DEC);
    if (i < 3) Serial.print(".");
  }
  Serial.print(" port ");
  Serial.println(port);
}

void displayMACaddress(byte address[]) {
  Serial.print("MAC address ");
  for (int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(address[i], HEX);
    if (i < 5) Serial.print(".");
  }
  Serial.println();
}

The connections between Arduino and ENC28J60 are:

Arduino ENC28J60


GND GND
3.3V 3.3V
53 CS
52 SCK
51 SI
50 SO

I've tried to plug the Ethernet cable in these configurations:



[TBH I don't exactly know the difference between a router and a switch (and a hub) but I was going to figured it out later.]

The problem is I get this on the serial monitor:

Ethernet UDP chat program
MAC address 0xDE.0xAD.0xBE.0xEF.0xFE.0xB1
Ethernet cable is not connected.
Ethernet UDP started  IP 192.168.1.177 port 10000

I've tried 3 different cables (CAT6a, CAT5e, CAT5). This only matters later on when I want to use PoE but still I used 3 different cables and I used them to connect my laptop to the home router and I got access to the Internet. Also I tried the example LinkStatus.ino and I get this:

/*
  Link Status
  This sketch prints the ethernet link status. When the
  ethernet cable is connected the link status should go to "ON".
  NOTE: Only WizNet W5200 and W5500 are capable of reporting
  the link status. W5100 will report "Unknown".
  Hardware:
   - Ethernet shield or equivalent board/shield with WizNet 5200/5500
  Written by Cristian Maglie
  This example is public domain.
*/

#include <SPI.h>
#include <EthernetENC.h>

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(53);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet

  Serial.begin(115200);
}

void loop() {
  auto link = Ethernet.linkStatus();
  Serial.print("Link status: ");
  switch (link) {
    case Unknown:
      Serial.println("Unknown");
      break;
    case LinkON:
      Serial.println("ON");
      break;
    case LinkOFF:
      Serial.println("OFF");
      break;
  }
  delay(1000);
}
Link status: ON
Link status: ON
Link status: ON
Link status: ON
Link status: ON

I'm so confused now. The cables are working. The only difference, I see, is:

// *****   IP of this machine and remote machine *********
IPAddress localIP(192, 168, 1, 177);
IPAddress remoteIP(192, 168, 1, 176);

// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 10000;   // local port to listen on
unsigned int remotePort = 10000;  // remote port to transmiit too
  mac[5] = localIP[3];  // change default MAC address
  displayMACaddress(mac);
  // start the Ethernet
  Ethernet.begin(mac, localIP);
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) delay(1);  // do nothing, no point running without Ethernet hardware
  }

So, is there anything going wrong in the initialisation and that's why even the linkStatus() doesn't work anymore or am I using the hardware wrong?

And again thanks for the help so far!

This makes CAN bus very interesting. I will keep this as a fallback plan in case the current idea doesn't work out. 2400 baud rate is plenty for my project.

if you look at the results of the example code I posted it always displayed

Ethernet cable is not connected.

just ignore it and try running a copy of the chat program on another UNO or mega remembering to change the IP address and they should be able to communicate

1 Like

Oh shoot, I'm so dumb. I thought I shouldn't try any further if the cable is not even recognized. Will report!