Ethernet disconnects after two loops()

Hello,

I have a RPi connected to a W5100S over SPI and trying to connect it to AWS IoT (and keep it connected ofc...).
So it connects, sends a message then reconnects, not sure why.

Here's the code:

#include <Arduino.h>

 #define USE_THIS_SS_PIN   5u

#include <SPI.h>
#include <Ethernet.h>
#include <SSLClient.h>
#include <PubSubClient.h>
#include "certificates.h"     // This file must be regenerated at https://openslab-osu.github.io/bearssl-certificate-utility/
#include "aws_configuration.h"

//#define ETHERNET_LARGE_BUFFERS true
#define MQTT_PACKET_SIZE  1024


// Enter a MAC address and IP address for your controller below.
#define NUMBER_OF_MAC      20
byte mac[][NUMBER_OF_MAC] = {
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x02 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x03 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x04 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x05 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x06 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x07 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x08 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x09 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0B },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0C },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0D },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0E },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0F },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x10 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x11 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x12 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x13 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x14 },
};

// In case a fixed IP is needed
//IPAddress ip(192, 168, 2, 222);

// Google DNS Server IP or any other DNS server
//IPAddress myDns(8, 8, 8, 8);


void MQTTPublish(const char *topic, char *payload);
void sendState();

SSLClientParameters mTLS = SSLClientParameters::fromPEM(thing_certificate, sizeof thing_certificate, thing_key, sizeof thing_key);

char publishPayload[MQTT_PACKET_SIZE];

void blinks(int cnt) {
  for (int i = 0; i < cnt; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(250);
    digitalWrite(LED_BUILTIN, LOW);
    delay(250);
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (uint16_t i=0; i<length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  blinks(2);
}


EthernetClient ethClient;
SSLClient ethClientSSL(ethClient, TAs, (size_t)TAs_NUM, A3);
PubSubClient mqtt(AWS_IOT_ENDPOINT, 8883, callback, ethClientSSL);


void reconnect() {
  while (!mqtt.connected()) {
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Attempting MQTT connection...");
  
    if ( mqtt.connect( DEVICE_NAME ) ) {
      blinks(1);
      Serial.println("connected!");
      for (int i = 0; i < 3; i++) {
        Serial.print("Subscribing to: ");
        Serial.println(subscribeTopics[i]);
        mqtt.subscribe(subscribeTopics[i]);
        blinks(1);
        delay(100);
      }
      sendState(); // initial
      digitalWrite(LED_BUILTIN, HIGH);
    } else {
      blinks(3);
      digitalWrite(LED_BUILTIN, LOW);
      Serial.print("failed, rc=");
      Serial.print(mqtt.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}




void setup() {
  delay(500);
  // set the onboard led pin to output
  pinMode(LED_BUILTIN, OUTPUT);

  //Ethernet.init(USE_THIS_SS_PIN); 

  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  //while (!Serial);

  // start the Ethernet connection:
  uint16_t index = millis() % NUMBER_OF_MAC;
  if (Ethernet.begin(mac[index]) == 0) {
    delay(250);

    Serial.println("Failed to configure Ethernet using DHCP");
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      blinks(3);
    } else if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
      blinks(3);
    }
    // no point in carrying on, so do nothing forevermore:
    while (true) {
      delay(1);
    }
  }
  Serial.println("Ethernet connected.");

  ethClientSSL.setMutualAuthParams(mTLS);
  mqtt.setBufferSize(MQTT_PACKET_SIZE);
  blinks(1);
  Serial.println("Setup completed.");
}



void loop() {
  Ethernet.maintain();

  if (!mqtt.connected()) {
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Not connected to MQTT: ");
    Serial.println( mqtt.state() );
    if (!ethClient.connected() ) {
      Serial.println("Ethernet not connected!");
    }
    delay(5000);
    reconnect();
  }
  
  mqtt.loop();

  if (!mqtt.connected()){
    Serial.print("X");
  } else {
    Serial.print(".");
  }
}


void sendState(){
  strcpy(publishPayload, "{\"state\": {\"reported\": {\"powerState\":\"ON\"}}}");
  MQTTPublish(AWS_IOT_TOPIC, publishPayload);
}

void MQTTPublish(const char *topic, char *payload){
  mqtt.publish(topic, payload);
  Serial.print("Published [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.println(payload);
}

And the output:

Attempting MQTT connection...connected!
Subscribing to: $aws/things/DevBoard/shadow/name/controller/update/accepted
Subscribing to: $aws/things/DevBoard/shadow/name/controller/update/rejected
Subscribing to: $aws/things/DevBoard/shadow/name/controller/update/delta
Published [$aws/things/DevBoard/shadow/name/controller/update] {"state": {"reported": {"powerState":"ON"}}}
..XNot connected to MQTT: -3
Ethernet not connected!

... repeated indefinitely.

The client ID is unique, nothing else connects to the account. LAN connection is nice and stable. Ethernet doesn't actually get disconnected - I'm pinging it and never times out.

Any idea what might be going on? Am I doing something wrong?

I guess anything in this description is wrong. An Raspberry Pi usually isn't programmed using the Arduino IDE. Is it a Pico? Where is the wiring diagram?

This output shows a wrong message. That only means that the TCP connection isn't existing anymore.

What does that mean? Do you need that SS pin for the Ethernet? But that SS pin isn't set in the Ethernet library.

My (rather wild) guess from the information provided: problems with the TLS certificates.

Yes I meant pico.

The Pico is connected with this Ethernet v1 shield over SPI. The wiring's all good.

You're right, got rid of that. Thank you.

I'm not seeing any SSL-related errors though and the library is quite whiny.
Besides it does connect to AWS IoT (I'm watching the console) and sometimes even publishes some messages, eg:

Connecting MQTT: connected!
Subscribing to: $aws/things/DevBoard/shadow/update/accepted
Subscribing to: $aws/things/DevBoard/shadow/update/rejected
Subscribing to: $aws/things/DevBoard/shadow/get/accepted
Enqueued [$aws/things/Devboard/shadow/get] {}
. + Published [$aws/things/Devboard/shadow/get] {}
....XNot connected to MQTT: -3

Going to try some other MQTT lib to shake this feeling that PubSubClient kind of feels like abandonware...brb

It seems it's not the PubSub library as it does the same with the arduino-mqtt library, I've also tried:

  • a different power supplies: phone charger, computer USB, breadboard supply
  • different SPI frequencies from 2MHz up to 12 (W5100 is stable up to like 12 MHz)
  • lowering MAX_SOCK_NUM and using ETHERNET_LARGE_BUFFERS
  • ground the SD CS pin
  • different SPI pins
  • different network cable
  • different MAC address
  • fixed IP address
  • different network switch and router

... and it still exhibits the same behavior.

In the AWS console I see it connecting and immediately disconnecting with reason: CLIENT_ERROR.

This only happens when using SSL and trying to subscribe/publish to a topic.
If I connect to another host without SSL it works without any error, I can subscribe and publish to 20+topics.

The SSL library logs this:
(SSLClient)(SSL_INFO)(m_print_br_state): (SSLClient)(SSL_INFO)(m_print_br_state): State: Connection closed (SSLClient)(SSL_INFO)(available): Engine closed after update

At this point I'm guessing it can be one of the following:

  • SSL library (tried ArduinoBearSSL but couldn't get it to work)
  • Ethernet library (tried Ethernet and EthernetLarge, also the Wiznet-published library)
  • some W5100 chip hardware issue.

Would appreciate any suggestions!

From the picture I get the impression that you try to power the Ethernet Shield by the 3V3 pin. Your shield is a Chinese clone so my conclusion might be wrong, but the Arduino Ethernet Shield gets it's power only from the 5V pin and converts that internally to 3.3V. The 3V3 pin isn't connected at all.
You might ask why it works for some time. For a short time the power from the signal pins might be enough to send and receive some packets but it's not enough for constant operation.

Post the schematics of your Ethernet Shield, serious vendors offer schematics, otherwise you shouldn't buy!

You are right, it is a rubbish board. I've ordered some W5100S-EVB-Pico boards which are basically the same wiring I have on the breadboard save from the power block...hopefully they will arrive at some point this decade. I'll be back

I didn't say it's a rubbish board. But having no clue what the board does isn't a good basis to debug problems. You may try to power the current board by the 5V pin, that might help. If it doesn't I hope your newly ordered board comes with schematics...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.