Ethernet.begin(mac) klappt nur mit Beispielcode WebClient

Leute ich bin am verzweifeln!

Ich habe mir sehr viel Mühe geben einen Code für meine Rollos zu schreiben. Der hat mittlerweile fast 11.000 Zeilen. Daher verzichte ich diesen komplett zu Posten.
Kompilieren und Hochladen klappt:
Der Sketch verwendet 194192 Bytes (76%) des Programmspeicherplatzes. Das Maximum sind 253952 Bytes.
Globale Variablen verwenden 5047 Bytes (61%) des dynamischen Speichers, 3145 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

Ich habe einen Mega 2560 mit einem AZ-Delivery Ethernet Schield W5100.

Meinen Sketch habe ich bereits am laufen gehabt und gesichert, bevor ich (6 Wochen später, also jetzt) marginale Änderungen vorgenommen habe. Der Arduino versorge ich nun auch nicht mehr über den normalen Stecker, sondern direkt über den 5V Power Supply Pin.

Nachdem ich nun das neue Setup in Betrieb nehmen wollte, habe ich Probleme mit der Ethernet lib. (Ein ähnliches Problem oder gar das Gleiche hatte ich schon mal vor ca. einem halben Jahr. Da der Code damals noch kürzer war, konnte ich auf einen zuvor gehenden Stand zurückspringen).

Der Sketch bleibt immer an der gleichen Stelle hängen: Ethernet.begin(mac). (habe aber schon mit Ethernet.begin(mac, ip) versucht, ohne Erfolg).
An der ConnectBox habe ich die MAC Adresse statisch im DHCP konfiguriert (dynamisch auch schon ohne Erfolg probiert).

Das kuriose an der Sache, der Beispielcode WebClient läuft ohne Probleme (warum ich die schon erwähnte PowerSupply Änderung ausschließe).

Anbei nochmal der Code:

/*
  Web client

 This sketch connects to a website (http://www.google.com)
 using an Arduino Wiznet Ethernet shield.

 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13

 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe, based on work by Adrian McEwen

 */

#include <SPI.h>
#include <Ethernet.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)

// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192, 168, 0, 177);
IPAddress myDns(192, 168, 0, 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() {
  // 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

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // start the Ethernet connection:
  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin(mac) == 0) {
    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.");
    }
    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip, myDns);
  } else {
    Serial.print("  DHCP assigned IP ");
    Serial.println(Ethernet.localIP());
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.print("connecting to ");
  Serial.print(server);
  Serial.println("...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.print("connected to ");
    Serial.println(client.remoteIP());
    // Make a HTTP request:
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    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);
    }
  }
}

Ich habe akribisch (sofern das überhaupt noch möglich ist) die entscheidenden Stellen verglichen. ICH FINDE ABER KEINEN UNTERSCHIED! Trotzdem läufts bei meinem Code nicht. Nur mit einem sehr alten Stand.

Anbei die entscheidenden Stellen ohne das langweilige drumherum:

#include <SPI.h> //Ethernet Shield kommuniziert via SPI mit Arduino
#include <Ethernet.h>
#include <PubSubClient.h> // http://knolleary.net/arduino-client-for-mqtt/
#include <Wire.h> //Notwendig für I2C Kommunikation
#include <OneButton.h> //singleClick, doubleClick & longPress Erkennung

//MAC Adresse des Ethernet Shields
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(192, 168, 0, 225);
//Ethernet Client zur Kommunikation des MQTT Clients
EthernetClient client;

PubSubClient mqttClient(server, 1883, callback, client);

void setup()
{
  //Serieller Port für Debug aktivieren
  Serial.begin(9600);
  Serial.println (F("Zurücksetzen der I2C DI Module"));
  Wire.begin(); 


  Wire.beginTransmission(I2C_DI6);   // Start transmission to PCF8574
  Wire.write(0xFF);                  // All Bits are Inputs
  Wire.endTransmission();            // End
  Serial.println (F("Zurücksetzen I2C_DI6 erfolgt"));
      
  // Initialisierung des Ethernets
  Ethernet.begin(mac);
  Serial.println (F("test1"));
  Serial.println(Ethernet.localIP());
  Serial.println (F("test2"));
}

Loop und die vielen Variablendefinitionen habe ich hier ausgespart. Wie schon gesagt, wäre sehr lang.
Ich sehe im Seriellen Monitor zuletzt: Zurücksetzen I2C_DI6 erfolgt
Test1 sehe ich schon garnicht, daher muss hier was mit der Initialisierung schief gehen, was allerdings mit dem Beispielcode klappt.

Kann es an der Größe meines Sketches liegen, dass die Ethernet.h nicht sauber arbeitet?
Habe auch mal einen leeren Sketch drauf geladen und paar Resets durchgeführt um etwas aufzuräumen, half natürlich nicht.

Ich bin mittlerweile ratlos und wäre über einen Tipp sehr dankbar, was ich noch untersuchen kann.

Gruß,
kamil

Vorher, also vor Ethernet.begin(mac) die Pins 4, 10 und 53 auf output stellen. Die Pins 4 und 10 High setzen.

// give the Ethernet shield a second to initialize:
delay(1000);

Ist vielleicht nervig, kann aber helfen.

Leider ohne Erfolg :confused:

  Wire.beginTransmission(I2C_DI6);   // Start transmission to PCF8574
  Wire.write(0xFF);                  // All Bits are Inputs
  Wire.endTransmission();            // End
  Serial.println (F("Zurücksetzen I2C_DI6 erfolgt"));

  pinMode(4, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(53, OUTPUT);
  digitalWrite(4, HIGH);
  digitalWrite(10, HIGH);
      
  // Initialisierung des Ethernets
  Ethernet.begin(mac);
    // give the Ethernet shield a second to initialize:
  delay(10000);
  Serial.println (F("test1"));
  Serial.println(Ethernet.localIP());
  Serial.println (F("test2"));

Habe hier zwar 10s, mit 1s lief es aber auch nicht.

Noch eine Idee?

Ich habe weiter in der Ethernet Lib gegraben und habe nun feststellen müssen, dass mit meinem Code es nicht möglich ist auf das MR register zuzugreifen. Was allerdings möglich ist mit dem Beispielcode.

Das Codesnipsel stammt aus der w5100.cpp.

Weiß einer, was es mit dem MR register auf sich hat, und warum ein Zugriff nicht möglich sein könnte?
Die Serial.println Ausgaben sind von mir, um die Ursache einzukreisen.

// Soft reset the Wiznet chip, by writing to its MR register reset bit
uint8_t W5100Class::softReset(void)
{
	uint16_t count=0;
Serial.println("w5100_12");
	//Serial.println("Wiznet soft reset");
	// write to reset bit
	writeMR(0x80);
	// then wait for soft reset to complete
Serial.println("w5100_writeMR wurde durchgeführt");	
	do {
		uint8_t mr = readMR();
		Serial.print("mr=");
		Serial.println(mr, HEX);
		if (mr == 0) return 1;
		delay(1);
	} while (++count < 20);
	return 0;

Auch wenn nicht nachvollziehbar: Lösung war den kompletten und teilweise identischen Block zur Initialisierung des Ethernets aus dem Beispiel Sketch in meinen zu kopieren. Sehr merkwürdig, aber läuft.

Geister?
:o :o :o