Forum: Mikrocontroller und Digitale Elektronik Arduino Nano mit Ethernetshield: TCP-Verbindung bricht ab


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich arbeite an einem Projekt, wo Schaltkommandos per TCP zu einem 
Arduino Nano mit Ethernetshield gesendet werden sollen. UDP fällt leider 
aus, weil die Übertragung später mal aus einer Webseite heraus erfolgen 
soll, da gibts nur TCP.

Es funktioniert ja im Prinzip auch, aber nach jeweils 4..5 Kommandos 
kommt keine Datenübertragung mehr zustande. Erst ein Hard-Reset hilft.

Dabei ist es egal, ob ich die einmal aufgemachte TCP-Verbindung offen 
lasse, oder (wie z.B. ein Browser) öffne, übertrage und dann schiesse. 
In beiden Fällen kann ich leider immer nur eine begrenzte Anzahl 
übertragen.

Der Empfang erfolgt im loop()-Bereich mit diesem Code-Schnipsel. Der 
Algorithmus zur Befehlserkennung funktioniert mit Serial und 
Serial.read() über Stunden einwandfrei. Es muss schon ein spezielles 
Netzwerkproblem sein.
1
EthernetClient client = server.available();
2
 
3
        while(client.available())
4
        {
5
          
6
          cmd[0]=cmd[1];cmd[1]=cmd[2];cmd[2]=cmd[3];cmd[3]=cmd[4];cmd[4]=cmd[5];
7
          
8
          cmd[5]=client.read();
9
10
          if(cmd[0]=='<' && cmd[5]=='>')
11
          {
12
            param=100*(cmd[2]-48)+10*(cmd[3]-48)+(cmd[4]-48); 
13
            client.print(String(cmd));       
14
            switch(cmd[1])
15
            {
16
              case 'L': laser(param); break;
17
              case 'H': hmov(param); break;
18
              case 'V': vmov(param); break;
19
              case 'B': blnk=param; break;
20
            }
21
          }
22
          
23
        }
24
        client.stop();

Wo ist der Fehler ... bzw. wie halte oder bekomme ich dieses Code-Stück 
zuverlässig? Danke für Tips.

Nachtrag: Könnte es ein Speicher-Problem sein? Beim Compilieren erhalte 
ich die Info: "Der Sketch verwendet 21670 Bytes (70%) des 
Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 1270 Bytes (62%) des dynamischen Speichers, 
778 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
"

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Ich vermute den Fehler woanders. Du solltest erst mal ein 
Beispielprogramm versuchen dass garantiert ok ist um Hardwarefehler 
auszuschließen.

Und gewöhne Dir an, vollständige (ausführbare) Quelltexte zu posten, 
allerdings auf möglichst wenig Zeilen reduziert, wo das Problem mit 
nachvollziehbar ist.

von Jim M. (turboj)


Lesenswert?

Frank E. schrieb:
> Nachtrag: Könnte es ein Speicher-Problem sein?

Zur Beantwortung müssten wir Deinen vollständigen Source Code sehen...

von Fred R. (Firma: www.ramser-elektro.at/shop) (fred_ram)


Lesenswert?

Dazu kommt, das diese Shields nicht gerade einem Router nahe kommen :-/

von Frank K. (fchk)


Lesenswert?

Frank E. schrieb:

> Globale Variablen verwenden 1270 Bytes (62%) des dynamischen Speichers,
> 778 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Das reicht ja nicht mal für einen kompletten Ethernet-Frame von 1.5k.


fchk

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Frank K. schrieb:
> Frank E. schrieb:
>
>> Globale Variablen verwenden 1270 Bytes (62%) des dynamischen Speichers,
>> 778 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
>
> Das reicht ja nicht mal für einen kompletten Ethernet-Frame von 1.5k.
>
> fchk

Der landet m.E. auch zunächst nur im Puffer des ENC28j69. Daraus wird 
mittels client.read() byteweise gelesen. Oder?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Wenn die Software auf µIP oder lwIP basiert, dass liest sie immer den 
ganzen Puffer am Stück aus. Allerdings bin ich gewohnt, dass der dazu 
nötige Speicher statisch reserviert wird.

Wenn den Controller tatsächlich nur 2kB RAM hat, dann ist der wirklich 
zu klein, um sinnvoll Ethernet nutzen zu können.

Zur Not kannst du versuchen, kleinere Puffer zu benutzen, aber das ist 
dann auch wieder mit zahlreichen Haken verbunden. Als mindest-Controller 
empfehle ich einen ATmgea664.

von Joachim B. (jar)


Lesenswert?

Stefan U. schrieb:
> Als mindest-Controller
> empfehle ich einen ATmgea664.

644? -> – 4 Kbytes Internal SRAM

also ehrlich wer will denn da sparen, ich plädiere für einen m1284p mit 
16 KB SRAM, ist in meinem Pollin Webserver auf AVR Basis auch drin.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

ne ne ne ... Leute. Bleiben wir mal bitte beim Thema Nano.

Ich habe ein anderes Projekt, ebenfalls mit dem Nano und genau diesem 
Ethernetshield mit der selben Lib, allerdings per UDP, das läuft seit 2 
Jahren völlig problemlos.

Es muss schon mit TCP zusammenhängen. Ein Bug in der Library 
UIPEthernet.h ist ja evtl. auch nicht völlig aiuszuschließen ... 
allerdings hätte man dazu etwas im Web finden/lesen müssen ...

Wird wohl nur irgend eine fiese Kleinigkeit sein ...

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Das erste was ich mal umschreiben wuerde:
> cmd[0]=cmd[1];cmd[1]=cmd[2];cmd[2]=cmd[3];cmd[3]=cmd[4];cmd[4]=cmd[5];

Sorry, aber sowas geht gar nicht...
1
for (uint8_t i = 0; i < 5; i++) {
2
    cmd[i] = cmd[i + 1];
3
}

Und dann solltest du mal die Doku lesen...
https://www.arduino.cc/en/Reference/ClientRead
1
Returns
2
3
The next byte (or character), or -1 if none is available.

Und jetzt schauen wir uns nochmal deinen Code an:
1
while (client.available()) {
2
    for (uint8_t i = 0; i < 5; i++) {
3
        cmd[i] = cmd[i + 1];
4
    }
5
6
    cmd[5] = client.read();
7
8
    if (cmd[0] == '<' && cmd[5] == '>') {
9
        ...
10
    }
11
}

Jetzt musst Du wissen, ob es zu Problemen fuehren kann, wenn das Array 
cmd mit -1 gefuellt wird. Wir wissen ja nicht wie dein weiterer Code 
aussieht.

Ich wuerds umschreiben zu:
1
while (client.available()) {
2
    int8_t tmp = client.read();
3
    if (tmp != -1) {
4
        for (uint8_t i = 0; i < 5; i++) {
5
            cmd[i] = cmd[i + 1];
6
        }
7
8
        cmd[5] = tmp;
9
        if (cmd[0] == '<' && cmd[5] == '>') {
10
            ...
11
        }
12
    }
13
}
Ob das was mit deinem Problem zu tun hat? Keine Ahnung. Ob's logisch 
richtig ist? Keine Ahnung, du zeigst deinen Code ja nicht...

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Kaj G. schrieb:
> Das erste was ich mal umschreiben wuerde:
>> cmd[0]=cmd[1];cmd[1]=cmd[2];cmd[2]=cmd[3];cmd[3]=cmd[4];cmd[4]=cmd[5];
>
> Sorry, aber sowas geht gar nicht...
> for (uint8_t i = 0; i < 5; i++) {
>     cmd[i] = cmd[i + 1];
> }
> ...


Danke für deine Mühe, aber das kann nicht die Ursache sein. Ich benutze 
exakt den selben Code in Verbindung mit Serial & Serial.read().

Auch auf Senderseite verwende ich für beide Übertragungswege die gleiche 
Kommando-Erzeugung und sende jeweils mal per Serial oder per Socket.

Über Serial funktioniert der Code stundenlang ohne Probleme. Mag ja 
sein, dass meine Auswertung nicht optimal ist ... aber wegen der 6 
Zuweisungen finde ich eine Schleife jetzt nicht unbedingt zwingend. Wenn 
es 20 wären ... ja dann :-)

Inzwischen habe ich aber auch einen Verdacht in Richtung Macbook/OSX und 
Xojo. Frühere Projekte habe ich mit der 2016er Version gemacht, das 
heutige mit einer von 2017. Möglicherweise werden Sockets da irgendwie 
ausgebremst. Ich werde das Morgen nochmal mit Windows testen, vlt. suche 
ich auch nur an der falschen Stelle.

Ich habe beobachtet, dass die Aktivitäts-LED am Ethernetshield immer 
dann, wenn es nicht mehr funktionierte, auch nicht mehr synchron zu den 
Sendungen blinkte. Und zeitweise blinkte diese LED wiederum erheblich 
heftiger als das normale Broadcast-Geflimmere im heimischen LAN so 
üblich ist, obwohl ich garnicht sendete ...

Die meiste Zeit habe ich das Macbook im WLAN und der Arduino hing per 
Kabel am Switch. Aber auch eine direkte Kabelverbindung zwischen Macbook 
und Arduino brachte keine grundlegende Änderung. Allerdings ließ sich 
der Arduino auch nur sehr selten erfolgreich Pingen ... das änderte sich 
auch nicht mit einem anderen, zweiten Ethernetshield ...

: Bearbeitet durch User
von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich habe dann doch noch wireshark angemacht ... und da kommt für die IP 
des Arduino einfach garnix, wenn ich mein Sendetool anwerfe.

Gebe ich die Adresse des Arduino in den Browser ein, sehe ich zumindest 
ARPs vom Macbook für die Adresse ... aber die weden nicht beantwotet ...

Nachtrag: Wenn ich mit meinem Tool auf die Adresse 255.255.255.255 
(Broadcast) sende, dann gibt splötzlich Datenverkehr aufzuzeichnen ...

ok, ist spääät ...

: Bearbeitet durch User
von Christian M. (Gast)


Lesenswert?

Frank E. schrieb:
> Ein Bug in der Library UIPEthernet.h ist ja evtl. auch nicht völlig
> aiuszuschließen ..

Genau das! Die hat Bugs!

Gruss Chregu

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Frank E. schrieb:
> Danke für deine Mühe, aber das kann nicht die Ursache sein.
Ich hab auch nicht gesagt, das die Zuweisung was mit deinem Problem zu 
tun hat. Ist nur unschoen. Aber jeder wie er mag :o)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.