Leider haben alle im Internet gefundenen Code-Brocken nicht das gewünschte Ergebnis gebracht.
Ich bekomme zwar einen Aufruf in die Interruptroutine - aber leider nur einmal nach einem Reset.
Board ist ein Mega 2560 und Shield ein Ethernet W5100 mit SD. Per Polling kein Problem, sollte aber per IRQ getriggert werden, da in der Loop andere Dinge erledigt werden, die dann unterbrochen werden sollen. Danke für funktionierende Hinweise oder Code.
Wenn du mal ein wenig genauer beschreiben könntest, was du mit dem IRQ erreichen möchtest, dann könnte man dir evtl. auch helfen.
Ich habe lange Zeit mit dem W5100 gearbeitet und das ohne Probleme, zwar mit einem Uno.
Also wo genau ist dein Problem ?
Du hast mein volles Mitgefühl!
Ich habe eine Loop, die regelmäßige Aufgaben erledigt. Diese sind zeitintensiv. Das Ganze ist ein Webserver mit den entsprechenden Dateien (HTML, CSS, JS, PNG) und Konfiguration auf SD Card.
Im Pollmodus funktioniert alles bestens - ausser das durch die anderen Aktionen die Ausführung beeinträchtigt wird. Im schlechtesten Fall bis zu einem Timeout. Aus diesem Grund wollte ich die Ethernet Schnittstelle über den IRQ bearbeiten. Der Request löst auch einen IRQ aus und die Interrupt-Routine wird aufgerufen. Aber leider nur einmal. Es sieht so aus, als ob der Interrupt nicht zurückgesetzt wird. Trotz allen Versuchen, die Register im W5100 zurückzusetzen, hatte ich keinen Erfolg.
Entferne jedes delay. Und schon läuft es wie geschmiert.
Da wir deinen Sketch nicht kennen, bleibt uns nur weiteres Raten.
Ja, so sollte das sein.
Das allerdings nicht. Vermute mal, da machst du etwas falsch.
#include <StreamLib.h>
#include <BufferedPrint.h>
#include <FreeStack.h>
#include <MinimumSerial.h>
#include <RingBuf.h>
#include <SdFat.h>
#include <SdFatConfig.h>
#include <sdios.h>
#include <Ethernet.h>
#include <utility/w5100.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,178,100);
bool showDirectory = false;
const int ETHERNET_CS = 10;
bool withDHCP = true;
uint16_t port = 80;
#include "Config.h"
EthernetServer server(port);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println(F("SD card initialized."));
//String cf = "Config.cnf";
String cf = "";
bool bRet = ReadConfigFile(cf);
if (bRet == true) {
Serial.println(F("Config file read."));
}
Ethernet.init(ETHERNET_CS);
if (withDHCP) {
if(Ethernet.begin(mac) == 0) {
Serial.println(F("Failed to configure Ethernet using DHCP"));
Ethernet.begin(mac, ip);
}
else {
Serial.println(F("IP address from DHCP"));
ip = Ethernet.localIP();
}
}
else {
Ethernet.begin(mac, ip);
}
W5100.writeIMR(0xEF);
W5100.writeRMSR(0x55);
W5100.writeTMSR(0x55);
attachInterrupt(digitalPinToInterrupt(2), gotMessage, FALLING);
server.begin();
Serial.println();
Serial.println(F("Connected to network."));
Serial.printf(F("To access the server, enter \"http://%s/\" in web browser.\n"),ip.toChar());
W5100.writeSnIR(1,4);
}
/* IRQ from Ethernet */
void gotMessage()
{
byte ir = W5100.readIR();
Serial.printf(F("Got Message on IR: %d\n"),ir);
// bis hier einmal nach Reset
// das nachfolgende sollte eigentlich den IRQ zurücksetzen und der Loop signalisieren
// Daten empfangen
byte snIR = W5100.readSnIR(ir);
SIRflag++;
W5100.writeSnIR(ir, 0);
Serial.println(snIR,HEX);
// oder vielleicht die Daten auch lesen
}
void loop()
{
// hier sollte vom IRQ das flag gesetzt werden
if(SIRflag) {
W5100.writeSnIR(1,0xFF);
W5100.writeIR(0xFF);
SIRflag--;
// das ist quasi ein Teil der Auswertung (nicht vollständig) anstatt polling
Serial.println("Recv Loop");
EthernetClient client = server.available();
if(client) {
// while (client.connected()) {
if( client.available()) {
if (client.find(' ')) {
char req[100];
int l = client.readBytesUntil(' ', req, sizeof(req)-1);
req[l] = 0;
client.find((char*) "\r\n\r\n");
String fnStr = String(req);
Serial.println(fnStr);
}
}
// }
client.stop();
}
Serial.println("Recv Loop finishes");
}
// put your main code here, to run repeatedly:
// hier wäre dann der normale Loop-Code
delay(1000);
}
Dein ernst?
Na klar mein Ernst!
Der Code funktioniert einmal mit folgendem output:
SD card initialized.
Config.cnf
Can't open config file
IP address from DHCP
Connected to network.
To access the server, enter "http://192.168.178.45/" in web browser.
Got Message on IR: 1
0
Recv Loop
/
Recv Loop finishes
Die loop läuft natürlich weiter - IRQ kommt halt nicht mehr. Deswegen brauche ich mehr Infos von Leuten die sich mit dem IRQ des W5100 auskennen.
Ich bin raus.
Das war ja auch nicht die Antwort die ich erwartet habe.
Der delay ist ja nur Ersatz für die Bearbeitung in der richtigen Loop die unterschiedlich lange laufen könnte.
Du verstehst es nicht !
Dein Sketch kann nur sauber und schnell laufen
Wenn kein delay() drin ist.
Wenn du die Antworten bestimmen willst, bist du hier vielleicht an der falschen Adresse.
Keiner hier hat irgendwas gegen Interrupts einzuwenden, wenn sie denn nötig sind.
Warum sie bei dir nötig sind, hast du noch nicht wirklich dargelegt.
Wir alle wissen, dass Interrupts, falsch eingesetzt, mehr Probleme schaffen, als sie lösen.
Stichworte: ATOMIC_BLOCK und volatile
z.B. du nutzt Serial in der ISR. Das ist ein offenes Messer, da muss man nur noch den falschen Zeitpunkt erwischen.
Das ist doch schon mal ein Ansatzpunkt!
Um "quasi parallel" zu einem delay() arbeiten zu können, bieten sich Interrupts, oder eben yield() an. Wobei es kritisch, ist Netzverkehr, und auch Serial, in einem Interrupt abzuhandeln, aber in yield() dagegen eher kein Problem darstellt.
Ich weiß, damit scheuche ich wieder einen Haufen yield() Gegner auf. Aber zu jeder Art von Multitasking, und sei es auch noch so primitiv, oder komplex/ausgereift, gehört irgendein dem yield() entsprechendes Konzept.
Und genau das willst du ja....
Nebenläufigkeiten.
Die Ausgabe in der ISR ist ja nur zum Test. Im richtigen Programm, wenn es mal läuft, wird's die ja nicht geben.
Mein Problem ist es halt, dass der Webclient mehrere Files anfordert (HTML, CSS, JS, PNG) nacheinander. Wenn ich die normale Loop-Aufgaben nicht unterbrechen kann durch die Webanfragen, kann es zu eventuell zu einem Timeout kommen oder die Antwortzeiten sind zu lange. Die Probleme mit Interruptprogrammierung sind mir nach 45 Jahren Programmierung mehr als geläufig. Die letzten 20 Jahre habe ich nur .NET in allen Varianten programmiert. Jetzt wollte ich halt mal mit den Spielzeugen ein bisschen mir die Zeit vertreiben. Ich finde halt keine Anleitung für den W5100 was wann gemacht werden muss um mehrere Interrupte hintereinander zu empfangen. Und das war und ist meine Anfrage ans Forum.
Ich will deine Erfahrungen und Kompetenzen nicht klein reden.
Aber dennoch, ist Arduino für dich ein neues Gebiet.
Und da lässt sich eben nicht alles ohne Reflektion übertragen.
Beispiel:
Das Problem habe ich von Anfang an schon so verstanden!
Jetzt hast du dir einen Lösungsweg ausgedacht:
Hier sollte dir zu denken geben:
Wenn das noch nie einer gemacht hat, es nicht üblich ist das so zu tun, dann könnte es Alternativen geben.
Ich sage dir: Es gibt Alternativen!
Das Forum, also u.A. ich, sagt dir: Wähle eine Alternative.
Es sagt zudem: Du hast dich zu früh auf einen Weg eingeschossen.
Es wäre unverantwortlich, von mir, dich auf deinem, aus meiner Sicht falschen Weg, zu bestärken.
Du siehst mein Dilemma:
Selbst wenn ich wüsste, wie es geht, würde ich es dir wohl nicht sagen.
Deine Lösung wäre eine Insellösung.
z.B. was passiert, wenn du auf eine andere Topologie umstellst?
Einen andern µC verwendest
Eine andere Ethernet Hardware
Von Lan auf Modbus oder WLAN.
Dann ist alles für die Katz. Und du stehst wieder vor dem selben Problem.
Was wäre der aus meiner Sicht richtige Weg?
Es muss ohne Interrupts funktionieren!
Wenn das sichergestellt ist, dann kann man über die Interrupts nachdenken, um die Sache zu optimieren.
Die Lösung ohne IRQ habe ich ja schon funktionierend. Sowohl auf dem Mega2560 mit Ethernet als auch auf dem ESP8266 mit WLAN. Immer mit den Webseiten auf SD-Card. Wenn in der Loop keine anderen Aufgaben erledigt werden - gibt es auch keine Zeitprobleme. Ich wollte aber noch andere Steuerungen erledigen. Ist ja auch kein Problem wenn keine Webanfragen kommen. Aber um diese zu priorisieren, sollte der Webrequest per Interrupt erfolgen.
Denk Fehler, SPI ist schnell nur die SD Karten nicht, da hilft ein IRQ auch nicht. je nach dem was zu lesen ist dauert noch mall was. SD Karten sind nicht geeignet mehrere Sachen auf einmal machen, zwei reqest auf andere Dateien, dan unter umständen haste 500 ms oder mehr weg
Es geht auch nicht um die Lesegeschwindigkeit der SD-Card. Die wird nur nach dem Webrequest gelesen. Die Reaktionszeit ist schon ok. Nur die sonstige Bearbeitung in der Loop soll von dem Webrequest unterbrochen werden.
ESP ist sau schnell im vergleich mit mega ( habe beide ) und hab noch nicht erlebt das irgend was gestopt wurde außer wen man for Schleifen benutzt aber auch das geht anders erledigen IRQ auf den kleinen dinger zusätzlich benutzen bringt mehr Probleme als nutzen schon 50% der Bibliotheken nuten die, das darf man nicht vergessen
dann wartet derESP Mega bis es fertig wird dafür sollte schon SPI sorgen bis die SD fertig wird erst mall testen. Es scheint so aus das Du falsche Hardware rausgesucht hast. Eine Erdbeere ist mehr geeignet.