ESP32: ethernet enc28j60 with plain (HTTP) and SSL (HTTPS)

Spread the love

First of all, ESP32 already has a MAC peripheral, a TCP/IP stack, and the Arduino networking library duplicates this all for enc28j60. But I have a lot of w5500 and enc28j60 devices that work well.

ESP32 ethernet enc28j60 with plain HTTP and SSL HTTPS
ESP32 ethernet enc28j60 with plain HTTP and SSL HTTPS

Many people ask me for some examples of wired connections; I think the best choice is the w5500 series device, but enc28j60 can be sufficient for many purposes, have different form factors, and the price is very low. We’ll start to learn how to manage plain and SSL requests.

Device

The ENC28J60-I/SP is a stand-alone Ethernet Controller with an industry-standard serial peripheral interface (SPI). It is designed to serve as an Ethernet network interface for any controller equipped with SPI. The ENC28J60 meets all of the IEEE 802.3 specifications. It incorporates several packet filtering schemes to limit incoming packets. It also provides an internal DMA module for fast data throughput and hardware-assisted checksum calculation, used in various network protocols. Communication with the host controller is implemented via an interrupt pin and the SPI, with clock rates of up to 20MHz. Two dedicated pins are used for LED link and network activity indication.

  • Fully compatible with 10/100/1000Base-T networks
  • Integrated MAC and 10Base-T PHY
  • Supports one 10Base-T port with automatic
  • Polarity detection and correction
  • Supports full and half-duplex modes
  • Programmable automatic re-transmit on collision
  • Programmable padding and CRC generation
  • Programmable automatic rejection of erroneous packets
  • SPI interface with clock speeds up to 20MHz
  • 8kB transmit/receive packet dual port SRAM
  • Configurable transmit/receive buffer size
  • Hardware managed circular receive FIFO
  • Byte-wide random and sequential access with auto-increment
  • Medium Access Controller (MAC) supports uni-cast, multicast and broadcast packets

As already I say, this kind of device has a lot of form factors and sometimes was released as a shield.

The most common is the medium size one.

enc28j60 ethernet network modules
enc28j60 ethernet network modules

Then another very used is the mini version.

enc28j60 mini ethernet network modules
enc28j60 mini ethernet network modules

Here my selection of tested ethernet devices w5500 lite - w5500 - enc26j60 mini - enc26j60 - lan8720

Wiring

ESP32 DOIT DEV KIT v1 pinout
ESP32 DOIT DEV KIT v1 pinout

Here my selection of esp32 devices ESP32 Dev Kit v1 - Selectable - TTGO T-Display 1.14 ESP32 - NodeMCU V3 V2 ESP8266 Lolin32 - NodeMCU ESP-32S - WeMos Lolin32 CP2104 CH340 - ESP32-CAM programmer - ESP32-CAM bundle - ESP32-WROOM-32 - ESP32-S

This device uses an SPI interface; by default, I will use a base SPI interface.

ESP32 DOIT DevKit v1 enc26j60 wiring on breadboard
ESP32 DOIT DevKit v1 enc26j60 wiring on breadboard
ESP32enc28j60
D5CS
D18SCK
D19MISO
D23MOSI
3.3v (better with external 200mha)VCC
GNDGND

Pay attention not all devices have so much amper to power the enc28j60 device, so if you have trouble you must add an external power supply.

ESP32 DOIT DevKit v1 enc28j60 wiring external power supply breadboard
ESP32 DOIT DevKit v1 enc28j60 wiring external power supply breadboard

Library

There are also many libraries for this device, the most famous is UIPEthernet, but now have some problems with integrating more innovative programs, so we are going to use EthernetENC, which is fully compatible with Arduino Ethernet and It’s a modern version of UIP.

Arduino IDE esp32 EthernetENC library for enc28j60
Arduino IDE esp32 EthernetENC library for enc28j60

SSLClient

This library and device do not support SSL, so adding these features exists an alternate library named SSLClient that needs a little patch of Ethernet.

SSLClient adds TLS 1.2 functionality to any network library implementing the Arduino Client interface, including the Arduino EthernetClient and WiFiClient classes. SSLClient was created to integrate TLS seamlessly with the Arduino infrastructure using BearSSL as an underlying TLS engine. Unlike ArduinoBearSSL, SSLClient is entirely self-contained and does not require any additional hardware (other than a network connection). (cit.)

Arduino esp32 ethernet w5500 SSLClient library manager
Arduino esp32 ethernet w5500 SSLClient library manager

SSLClient with EthernetENC

I tried this library with some other libraries, and I noticed that UIPEthernet did not work, but EthernetENC works correctly without doing anything.

Buffer extension

I also notice that you probably must change something to get good stability.

In SSLClient.h, you must change this line.

unsigned char m_iobuf[2048];

to

unsigned char m_iobuf[BR_SSL_BUFSIZE_BIDI];

Code

Now we try to do a simple WebRequest with a native client. But first, we write the code needed for the connection, we try to ask the IP to the DHCP server, and if It fails, we start a connection with a static IP.

Initialize device

Ethernet uses the default SPI interface by default, so first, we must ser the correct SS pin (probably not needed).

    // 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

This board’s different from LAN8720 (the default device for esp32) and needs a MAC address.

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

Then we try to make a DHCP request.

    if (Ethernet.begin(mac)) { // Dynamic IP setup
        Serial.println("DHCP OK!");
    }

But If it fails, we try to make a static IP connection with these parameters

// Set the static IP address to use if the DHCP fails to assign
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1

and here is the connection code

		Serial.println("Failed to configure Ethernet using DHCP");
		// Check for Ethernet hardware present
		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.");
		}

		IPAddress ip(MYIPADDR);
		IPAddress dns(MYDNS);
		IPAddress gw(MYGW);
		IPAddress sn(MYIPMASK);
		Ethernet.begin(mac, ip, dns, gw, sn);
		Serial.println("STATIC OK!");

Simple HTTP request

First of all, we’ll try to make a simple HTTP request. I chose an online service created to test this kind of request to do this test.

I will use a simple service from httpbin.org, and you can use the same REST API in HTTP and HTTPS.

Remember that HTTP work on port 80 and HTTPS on 443, so to query the endpoint on the 443 port, you must validate a certificate.

To make our connection, we use the basic EthernetClient.

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

And then, we try to connect and ask for a GET endpoint.

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("Connected!");
    // Make a HTTP request:
    client.println("GET /get HTTP/1.1");
    client.println("Host: httpbin.org");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

In the loop, wait for a response from the server.

  // if there are incoming bytes available
  // from the server, read them and print them:
  int len = client.available();

And then read the response and put it on Serial output.

  if (len > 0) {
    byte buffer[80];
    if (len > 80) len = 80;
    client.read(buffer, len);
    if (printWebData) {
      Serial.write(buffer, len); // show in the serial monitor (slows some boards)
    }
    byteCount = byteCount + len;
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    endMicros = micros();
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    Serial.print("Received ");
    Serial.print(byteCount);
    Serial.print(" bytes in ");
    float seconds = (float)(endMicros - beginMicros) / 1000000.0;
    Serial.print(seconds, 4);
    float rate = (float)byteCount / seconds / 1000.0;
    Serial.print(", rate = ");
    Serial.print(rate);
    Serial.print(" kbytes/second");
    Serial.println();

    // do nothing forevermore:
    while (true) {
      delay(1);
    }
  }

And finally, the complete sketch.

/*
 Web client with enc28j60 and EthernetENC

 This sketch connects to a test website (httpbin.org)
 and try to do a GET request, the output is printed
 on Serial

 by Renzo Mischianti <www.mischianti.org>

 https://www.mischianti.org

 */

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

// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
//char server[] = "www.google.com";    // name address for Google (using DNS)
char server[] = "httpbin.org";    // name address for Google (using DNS)

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// Set the static IP address to use if the DHCP fails to assign
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

// Variables to measure the speed
unsigned long beginMicros, endMicros;
unsigned long byteCount = 0;
bool printWebData = true;  // set to false for better speed measurement

void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println("Begin Ethernet");

    // 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

    if (Ethernet.begin(mac)) { // Dynamic IP setup
        Serial.println("DHCP OK!");
    }else{
        Serial.println("Failed to configure Ethernet using DHCP");
        // Check for Ethernet hardware present
        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.");
        }

    	  IPAddress ip(MYIPADDR);
    	  IPAddress dns(MYDNS);
    	  IPAddress gw(MYGW);
    	  IPAddress sn(MYIPMASK);
    	  Ethernet.begin(mac, ip, dns, gw, sn);
		  Serial.println("STATIC OK!");
    }
    delay(5000);


    Serial.print("Local IP : ");
    Serial.println(Ethernet.localIP());
    Serial.print("Subnet Mask : ");
    Serial.println(Ethernet.subnetMask());
    Serial.print("Gateway IP : ");
    Serial.println(Ethernet.gatewayIP());
    Serial.print("DNS Server : ");
    Serial.println(Ethernet.dnsServerIP());

   Serial.println("Ethernet Successfully Initialized");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("Connected!");
    // Make a HTTP request:
    client.println("GET /get HTTP/1.1");
    client.println("Host: httpbin.org");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
  beginMicros = micros();
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  int len = client.available();
  if (len > 0) {
    byte buffer[80];
    if (len > 80) len = 80;
    client.read(buffer, len);
    if (printWebData) {
      Serial.write(buffer, len); // show in the serial monitor (slows some boards)
    }
    byteCount = byteCount + len;
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    endMicros = micros();
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    Serial.print("Received ");
    Serial.print(byteCount);
    Serial.print(" bytes in ");
    float seconds = (float)(endMicros - beginMicros) / 1000000.0;
    Serial.print(seconds, 4);
    float rate = (float)byteCount / seconds / 1000.0;
    Serial.print(", rate = ");
    Serial.print(rate);
    Serial.print(" kbytes/second");
    Serial.println();

    // do nothing forevermore:
    while (true) {
      delay(1);
    }
  }
}

The result is this.

Begin Ethernet
DHCP OK!
Local IP : 192.168.1.138
Subnet Mask : 255.255.255.0
Gateway IP : 192.168.1.1
DNS Server : 192.168.1.1
Ethernet Successfully Initialized

Connected!
HTTP/1.1 200 OK 
Date: Wed, 09 Mar 2022 11:15:49 GMT
Content-Type: application/json 
Content-Length: 197
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "args": {}, 
  "headers": {
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-62288c65-1fe4f19070d3ab7c773aee09"
  }, 
  "origin": "82.51.127.46", 
  "url": "http://httpbin.org/get"
}

disconnecting.
Received 422 bytes in 0.2663, rate = 1.58 kbytes/second

HTTPS request

ESP32 WeMos LOLIN32 enc28j60 mini
ESP32 WeMos LOLIN32 enc28j60 mini

Now, if we change the endpoint to port 443, we will request a secure server with SSL encryption.

  if (client.connect(server, 443)) {
    Serial.println("Connected!");
    // Make a HTTP request:
    client.println("GET /get HTTP/1.1");
    client.println("Host: httpbin.org");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

And we obtain this response.

Begin Ethernet
DHCP OK!
Local IP : 192.168.1.138
Subnet Mask : 255.255.255.0
Gateway IP : 192.168.1.1
DNS Server : 192.168.1.1
Ethernet Successfully Initialized
 
Connected!
HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Wed, 09 Mar 2022 11:23:16 GMT
Content-Type: text/html
Content-Length: 220
Connection: close

<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
</body>
</html>

Disconnecting.
Received 370 bytes in 0.4333, rate = 0.85 kbytes/second

So the problem is that request and response messages aren’t transmitted using SSL (Secure Sockets Layer) or its successor TLS (Transport Layer Security). To add this feature, we are going to use SSLClient.

Retrieve certificate

To use an SSL, we need the server certificate, but in this case, SSLClient uses a trick given by BearSSL implementation. This minimal x509 verification engine allows using of Trust Anchors.

I add a simple online generator that you can find here.

You must only write the site’s address (httpbin.org) in the first input box, click Generate code, copy the code, and put it inside a file called trust_anchors.h and put it inside the sketch folder.

BearSSL certificate trust anchor retriever online

Here is the content of trust_anchors.h.

#ifndef _CERTIFICATES_H_
#define _CERTIFICATES_H_

#ifdef __cplusplus
extern "C"
{
#endif

/* This file is auto-generated by the pycert_bearssl tool.  Do not change it manually.
 * Certificates are BearSSL br_x509_trust_anchor format.  Included certs:
 *
 * Index:    0
 * Label:    Starfield Class 2 Certification Authority
 * Subject:  OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\, Inc.,C=US
 * Domain(s): httpbin.org
 */

#define TAs_NUM 1

static const unsigned char TA_DN0[] = {
    0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
    0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a,
    0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20,
    0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, 0x73,
    0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03,
    0x55, 0x04, 0x0b, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65,
    0x6c, 0x64, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43,
    0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
    0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79,
};

static const unsigned char TA_RSA_N0[] = {
    0xb7, 0x32, 0xc8, 0xfe, 0xe9, 0x71, 0xa6, 0x04, 0x85, 0xad, 0x0c, 0x11,
    0x64, 0xdf, 0xce, 0x4d, 0xef, 0xc8, 0x03, 0x18, 0x87, 0x3f, 0xa1, 0xab,
    0xfb, 0x3c, 0xa6, 0x9f, 0xf0, 0xc3, 0xa1, 0xda, 0xd4, 0xd8, 0x6e, 0x2b,
    0x53, 0x90, 0xfb, 0x24, 0xa4, 0x3e, 0x84, 0xf0, 0x9e, 0xe8, 0x5f, 0xec,
    0xe5, 0x27, 0x44, 0xf5, 0x28, 0xa6, 0x3f, 0x7b, 0xde, 0xe0, 0x2a, 0xf0,
    0xc8, 0xaf, 0x53, 0x2f, 0x9e, 0xca, 0x05, 0x01, 0x93, 0x1e, 0x8f, 0x66,
    0x1c, 0x39, 0xa7, 0x4d, 0xfa, 0x5a, 0xb6, 0x73, 0x04, 0x25, 0x66, 0xeb,
    0x77, 0x7f, 0xe7, 0x59, 0xc6, 0x4a, 0x99, 0x25, 0x14, 0x54, 0xeb, 0x26,
    0xc7, 0xf3, 0x7f, 0x19, 0xd5, 0x30, 0x70, 0x8f, 0xaf, 0xb0, 0x46, 0x2a,
    0xff, 0xad, 0xeb, 0x29, 0xed, 0xd7, 0x9f, 0xaa, 0x04, 0x87, 0xa3, 0xd4,
    0xf9, 0x89, 0xa5, 0x34, 0x5f, 0xdb, 0x43, 0x91, 0x82, 0x36, 0xd9, 0x66,
    0x3c, 0xb1, 0xb8, 0xb9, 0x82, 0xfd, 0x9c, 0x3a, 0x3e, 0x10, 0xc8, 0x3b,
    0xef, 0x06, 0x65, 0x66, 0x7a, 0x9b, 0x19, 0x18, 0x3d, 0xff, 0x71, 0x51,
    0x3c, 0x30, 0x2e, 0x5f, 0xbe, 0x3d, 0x77, 0x73, 0xb2, 0x5d, 0x06, 0x6c,
    0xc3, 0x23, 0x56, 0x9a, 0x2b, 0x85, 0x26, 0x92, 0x1c, 0xa7, 0x02, 0xb3,
    0xe4, 0x3f, 0x0d, 0xaf, 0x08, 0x79, 0x82, 0xb8, 0x36, 0x3d, 0xea, 0x9c,
    0xd3, 0x35, 0xb3, 0xbc, 0x69, 0xca, 0xf5, 0xcc, 0x9d, 0xe8, 0xfd, 0x64,
    0x8d, 0x17, 0x80, 0x33, 0x6e, 0x5e, 0x4a, 0x5d, 0x99, 0xc9, 0x1e, 0x87,
    0xb4, 0x9d, 0x1a, 0xc0, 0xd5, 0x6e, 0x13, 0x35, 0x23, 0x5e, 0xdf, 0x9b,
    0x5f, 0x3d, 0xef, 0xd6, 0xf7, 0x76, 0xc2, 0xea, 0x3e, 0xbb, 0x78, 0x0d,
    0x1c, 0x42, 0x67, 0x6b, 0x04, 0xd8, 0xf8, 0xd6, 0xda, 0x6f, 0x8b, 0xf2,
    0x44, 0xa0, 0x01, 0xab,
};

static const unsigned char TA_RSA_E0[] = {
    0x03,
};

static const br_x509_trust_anchor TAs[] = {
    {
        { (unsigned char *)TA_DN0, sizeof TA_DN0 },
        BR_X509_TA_CA,
        {
            BR_KEYTYPE_RSA,
            { .rsa = {
                (unsigned char *)TA_RSA_N0, sizeof TA_RSA_N0,
                (unsigned char *)TA_RSA_E0, sizeof TA_RSA_E0,
            } }
        }
    },
};

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* ifndef _CERTIFICATES_H_ */

Add SSLClient wrapper

Now we are going to add the SSLClient library and the trust_anchors.h file.

#include <SPI.h>
#include <EthernetENC.h>
#include <SSLClient.h>
#include "trust_anchors.h"

Then apply the wrapper EthernetClient with all the references of Trust Anchors. The file contains generated trust anchor array names TAs with length. TAs_NUM.

// Choose the analog pin to get semi-random data from for SSL
// Pick a pin that's not connected or attached to a randomish voltage source
const int rand_pin = A5;

// Initialize the SSL client library
// We input an EthernetClient, our trust anchors, and the analog pin
EthernetClient base_client;
SSLClient client(base_client, TAs, (size_t)TAs_NUM, rand_pin);

And we change the port to 443 (HTTPS).

  // if you get a connection, report back via serial:
  if (client.connect(server, 443)) {
    Serial.print("connected to ");
    // Make a HTTP request:
    client.println("GET /get HTTP/1.1");
    client.println("Host: httpbin.org");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

Here is the complete sketch.

/*
 Web SSL client  with enc28j60, 
 EthernetENC and SSLClient

 This sketch connects to a test website (httpbin.org)
 and try to do a secure GET request on port 443,
 to do the SSL request we use SSLClient with the
 site Trust Anchor
 the output is printed on Serial

 by Renzo Mischianti <www.mischianti.org>

 https://www.mischianti.org

 */

#include <SPI.h>
#include <EthernetENC.h>
#include <SSLClient.h>
#include "trust_anchors.h"

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
//char server[] = "www.google.com";    // name address for Google (using DNS)
char server[] = "httpbin.org";    // name address for Google (using DNS)

// Set the static IP address to use if the DHCP fails to assign
#define MYIPADDR 192,168,1,28
#define MYIPMASK 255,255,255,0
#define MYDNS 192,168,1,1
#define MYGW 192,168,1,1

// Choose the analog pin to get semi-random data from for SSL
// Pick a pin that's not connected or attached to a randomish voltage source
const int rand_pin = A5;

// Initialize the SSL client library
// We input an EthernetClient, our trust anchors, and the analog pin
EthernetClient base_client;
SSLClient client(base_client, TAs, (size_t)TAs_NUM, rand_pin);

// Variables to measure the speed
unsigned long beginMicros, endMicros;
unsigned long byteCount = 0;
bool printWebData = true;  // set to false for better speed measurement

void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println("Begin Ethernet");

    // 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

    if (Ethernet.begin(mac)) { // Dynamic IP setup
        Serial.println("DHCP OK!");
    }else{
        Serial.println("Failed to configure Ethernet using DHCP");
        // Check for Ethernet hardware present
        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.");
        }

    	  IPAddress ip(MYIPADDR);
    	  IPAddress dns(MYDNS);
    	  IPAddress gw(MYGW);
    	  IPAddress sn(MYIPMASK);
    	  Ethernet.begin(mac, ip, dns, gw, sn);
		  Serial.println("STATIC OK!");
    }
    delay(5000);


    Serial.print("Local IP : ");
    Serial.println(Ethernet.localIP());
    Serial.print("Subnet Mask : ");
    Serial.println(Ethernet.subnetMask());
    Serial.print("Gateway IP : ");
    Serial.println(Ethernet.gatewayIP());
    Serial.print("DNS Server : ");
    Serial.println(Ethernet.dnsServerIP());

   Serial.println("Ethernet Successfully Initialized");
  // if you get a connection, report back via serial:
  if (client.connect(server, 443)) {
    Serial.print("connected to ");
    // Make a HTTP request:
    client.println("GET /get HTTP/1.1");
    client.println("Host: httpbin.org");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
  beginMicros = micros();
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  int len = client.available();
  if (len > 0) {
    byte buffer[80];
    if (len > 80) len = 80;
    client.read(buffer, len);
    if (printWebData) {
      Serial.write(buffer, len); // show in the serial monitor (slows some boards)
    }
    byteCount = byteCount + len;
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    endMicros = micros();
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    Serial.print("Received ");
    Serial.print(byteCount);
    Serial.print(" bytes in ");
    float seconds = (float)(endMicros - beginMicros) / 1000000.0;
    Serial.print(seconds, 4);
    float rate = (float)byteCount / seconds / 1000.0;
    Serial.print(", rate = ");
    Serial.print(rate);
    Serial.print(" kbytes/second");
    Serial.println();

    // do nothing forevermore:
    while (true) {
      delay(1);
    }
  }
}

Now when we execute the sketch, we obtain this output.

Begin Ethernet
DHCP OK!
Local IP : 192.168.1.138
Subnet Mask : 255.255.255.0
Gateway IP : 192.168.1.1
DNS Server : 192.168.1.1 
Ethernet Successfully Initialized

connected to HTTP/1.1 200 OK
Date: Wed, 09 Mar 2022 11:55:33 GMT
Content-Type: application/json
Content-Length: 198
Connection: close 
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: * 
Access-Control-Allow-Credentials: true

{
  "args": {}, 
  "headers": {
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-622895b5-05f3c1351d694e66175a5335"
  }, 
  "origin": "82.51.127.46", 
  "url": "https://httpbin.org/get"
}
 
disconnecting.
Received 423 bytes in 0.2611, rate = 1.62 kbytes/second

Thanks

I use this SSLClient library in my EMailSender library to use Gmail SMTP server (SSL) with Ethernet. Unfortunately, SSL connections need quite a bit of resource, and only Arduino SAMD, STM32, and ESP32 have so many resources.

  1. ESP32: pinout, specs and Arduino IDE configuration
  2. ESP32: integrated SPIFFS Filesystem
  3. ESP32: manage multiple Serial and logging
  4. ESP32 practical power saving
    1. ESP32 practical power saving: manage WiFi and CPU
    2. ESP32 practical power saving: modem and light sleep
    3. ESP32 practical power saving: deep sleep and hibernation
    4. ESP32 practical power saving: preserve data, timer and touch wake up
    5. ESP32 practical power saving: external and ULP wake up
    6. ESP32 practical power saving: UART and GPIO wake up
  5. ESP32: integrated LittleFS FileSystem
  6. ESP32: integrated FFat (Fat/exFAT) FileSystem
  7. ESP32-wroom-32
    1. ESP32-wroom-32: flash, pinout, specs and IDE configuration
  8. ESP32-CAM
    1. ESP32-CAM: pinout, specs and Arduino IDE configuration
    2. ESP32-CAM: upgrade CamerWebServer with flash features
  9. ESP32: use ethernet w5500 with plain (HTTP) and SSL (HTTPS)
  10. ESP32: use ethernet enc28j60 with plain (HTTP) and SSL (HTTPS)
  11. How to use SD card with esp32
  12. esp32 and esp8266: FAT filesystem on external SPI flash memory
  1. Firmware and OTA update management
    1. Firmware management
      1. ESP32: flash compiled firmware (.bin)
      2. ESP32: flash compiled firmware and filesystem (.bin) with GUI tools
    2. OTA update with Arduino IDE
      1. ESP32 OTA update with Arduino IDE: filesystem, firmware, and password
    3. OTA update with Web Browser
      1. ESP32 OTA update with Web Browser: firmware, filesystem, and authentication
      2. ESP32 OTA update with Web Browser: upload in HTTPS (SSL/TLS) with self-signed certificate
      3. ESP32 OTA update with Web Browser: custom web interface
    4. Self OTA uptate from HTTP server
      1. ESP32 self OTA update firmware from the server
      2. ESP32 self OTA update firmware from the server with version check
      3. ESP32 self-OTA update in HTTPS (SSL/TLS) with trusted self-signed certificate
    5. Non-standard Firmware update
      1. ESP32 firmware and filesystem update from SD card
      2. ESP32 firmware and filesystem update with FTP client
  1. Integrating LAN8720 with ESP32 for Ethernet Connectivity with plain (HTTP) and SSL (HTTPS)

Spread the love

4 Responses

  1. cagatay says:

    Hello my dear friend, thank you for your useful work.
    Is it possible to use firebase database using ethernet module with esp32?

  2. Yi says:

    Hi, may i know. Will this work with the ESP32-A1s?
    I’ve wired accordingly. The esp fail at the line if (Ethernet.begin(mac)). Doesn’t work with Fix IP too.
    DNS and gateway is correctly pointing to the router

    However the “Ethernet.hardwareStatus() == EthernetNoHardware” seems to be working. As when i purposely swap the SI with SO it did print out the error

    • Hi Yi,
      there are 2 possibility:

      • The device enc28j60 isn’t a good module
      • The power supply or connection isn’t stable and you can’t retrieve the IP (power supply need a good amperage)

      Bye Renzo

Leave a Reply

Your email address will not be published. Required fields are marked *