Jump to content

Massive "reset" Probleme nach Update auf Protokoll 2.0


remotecontrol

Recommended Posts

Soooo, ich konnte das reproduzieren. Konnte den schuldigen auch ausfindig machen: Das Servo Brick. Oder spezifischer: Die VelocityReached und PositionReached Callbacks des Servo Bricks.

 

Du hattest in dem Testprogramm die Velocity aufs Maximum gesetzt und dann mehrere Servos in sehr kurzen Abständen mit kleinen Positionsveränderungen gesteuert. Dadurch war bei jedem setzen eines Stellwerts immer sofort die neue Position und die volle Velocity erreicht. D.h. es gab für jedes Servo quasi immer zwei Nachrichten die zu senden waren.

 

Dadurch haben sich Stück für Stück Nachrichten im Ringbuffer aufgestaut, bis er voll war. Danach haben sie sich dann im Buffer der WIFI Extension aufgestaut, bis er voll war.

 

Und dann passiert etwas böses: Das WIFI Modul nimmt die TCP/IP Pakete an, schreibt soviel in den Buffer wie er kann und schmeißt den Rest weg. An der Stelle hab ich dann verloren, sobald ich diese Daten abarbeite lese ich Schrott und dann tritt das Verhalten auf was du beschrieben hast.

 

Lösung für dein spezifisches Problem: VelocityReached und PositionReached Callbacks an/abschaltbar machen. Ich hab mal eine Servo Brick Firmware angehägt bei der die Callbacks anschaltbar sind, Default ist aus. Damit kann ich mit deinem Testprogramm keine Probleme mehr erzeugen.

 

Wenn das bei dir funktioniert würde ich das auch noch für die *Reached Callbacks von DC und Stepper Brick implementieren. Das stand übrigens sowieso schon auf der TODO Liste :o.

brick_servo_firmware_2_0_1-beta1.bin

Link to comment
Share on other sites

Hallo Borg,

 

die Totalausfälle sind weg :), ich konnte keinen mehr reproduzieren.

 

Allerdings laufen die Servo jetzt wesentlich 'ruckliger' :-\.

Bei gleichmäßiger Datenübertragung sollten sich die Servos einigermaßen gleichmäßig bewegen. Hier hatte ich in der alten Version vereinzelt kleine bis mittlere Ruckler. Jetzt habe ich fast nie eine flüssige Bewegung. Es ruckt ca. im 5 Hz Takt, auch wenn ich die Daten langsamer übertrage.

 

Über USB läuft es schööön flüssig -> liegt also an der WLAN-Kommunikation. Der Effekt war in der alten Version aber wesentlich geringer.

 

Ist noch was anderes verändert, was das bewirken kann?

Oder schlägt jetzt ggf. der 200ms Sekunden-Delay (TcpNoDelay - von Stack zurück zum Client) zu, weil weniger Responses vom Stack zurück gesendet werden? Es ruckelt irgendwie zu gleichmäßig.

 

Viele Grüße

Link to comment
Share on other sites

Ich denke du rufst da einfach so viele Setter auf, dass das Betriebssystem die in ein großes Paket bündelt. Dadurch kommen die Daten dann immer so schubweise an.

 

Du musst also eigentlich sicherstellen, dass das setzen einer Position schon ausgeführt wurde wenn du die neue rausschickst. Das geht z.B. in dem du ReponseExpected aktivierst für setPosition:

((BrickServo)device).setResponseExpected(BrickServo.FUNCTION_SET_POSITION, true);

 

In Zeile 91 in DeviceItem.java. Da gibt es vermutlich eine bessere Stelle für :).

 

Dann siehst du auch, dass die Queue vollläuft und du eigentlich zuviele Nachrichten schickst. Ich glaube ich würde versuchen die setPosition Aufrufe auf ein 10ms Intervall zu minimieren.

 

Ich versuche nochmal herauszufinden ab wo genau die Messages schubweise durchgehen, aber ich bezweifle das es etwas ist was wir beeinflussen können :(.

Link to comment
Share on other sites

Man merkt den Effekt schon wenn ich Commands unter 30ms sende.

 

Ich kann mir zwar nicht so recht vorstellen, dass das Betriebssystem hier solche Effekte rein bringt (das würde den TCP_NODELAY ja gerade aushebeln), aber ganz ausschließen kann ich es auch nicht.

 

Der Aufruf von setResponseExpected(BrickServo.FUNCTION_SET_POSITION, true) bringt schon mal eine deutliche Verbesserung (bedeutet aber auch, das jegliche Kommunikation zum Stack brav seriell abgearbeitet wird - oder?).

 

Ein erster Test sieht soweit gut aus :). Was mir aber auffällt: ich setze ja im Abstand von 1-2 Sekunden Monoflop Impulse für 0,2s Dauer auf ein Quad-Relais. Die werden sehr schnell gesendet, da sie ohne Response sind. Aber gerade wenn der Monoflop aktiv ist und setResponseExpected für Servo auch, scheinen die Servos träge zu reagieren und immer wenn der Monoflop ein ist, hakt es kurz.

 

Was macht der Master in der Zeit, wo der Monoflop ein ist? Kann der Relais-Monoflop überhaupt eine Servo-Response blockieren? Wenn ich diesen Effekt noch weg bekomme, wäre die Kommunikation ausreichend.

Link to comment
Share on other sites

Hab' nochmal was ausprobiert: Stack per USB+brickd am PC-1. Von anderem PC/Tablet per WLAN auf PC-1 verbunden: läuft relativ flüssig.

 

Direkt per WLAN gegen den Stack ruckt stark (jeweils ohne setResponseExpected). Also kann es eigentlich nicht am Betriebssystem liegen, das dort Pakete gebündelt werden. Völlig überlastet kann der Stack auch nicht sein, sonst würde es bei Anschluß über USB nicht so sauber laufen.

Link to comment
Share on other sites

Also es ist definitiv so, dass die Daten zum Teil gebündelt bei der WIFI Extension ankommen, hier meine Debug Ausgabe:

poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll
poll

[31, 9, 77, e4, b, 4, 50, 0, 0, fd, 2, poll
31, 9, 77, e4, b, 4, 60, 0, 5, 3, fd, poll
31, 9, 77, e4, b, 4, 70, 0, 1, 2a, 3, poll
31, 9, 77, e4, b, 4, 80, 0, 4, d6, fc, poll
31, 9, 77, e4, b, 4, 90, 0, 0, 2a, 3, poll
31, 9, 77, e4, b, 4, a0, 0, 5, d6, fc, poll
31, 9, 77, e4, b, 4, b0, 0, 1, 57, 3, poll
31, 9, 77, e4, b, 4, c0, 0, 4, a9, fc, poll
31, 9, 77, e4, b, 4, d0, 0, 0, 57, 3, poll
31, 9, 77, e4, b, 4, e0, 0, 5, a9, fc, poll
31, 9, 77, e4, b, 4, f0, 0, 1, 84, 3, poll
31, 9, 77, e4, b, 4, 10, 0, 4, 7c, fc, poll
31, 9, 77, e4, b, 4, 20, 0, 0, 84, 3, poll
31, 9, 77, e4, b, 4, 30, 0, 5, 7c, fc, ]
poll

 

Die "polls" sind im 1ms takt und wenn Daten da sind, werden sie mit ausgegeben. "[" und "]" geben ein einzelnes TCP/IP Paket an.

 

Da ist also eine ganz Zeit nichts und dann auf einmal kommt 14x setPosition.

 

Im Anhang das ganze nochmal in Wireshark. Dort sieht man die ganzen setPosition (die 77 Byte großen Pakete). Die gehen also eine ganz Zeit lang einzeln durch und dann auf einmal kommt ein Paket der Größe 209 wo die besagte Vielzahl an setPositions drin ist (siehst du auch unten im Payload, dort ist mehrfach 31 09 77..  drin).

 

D.h. die Pakete werden wirklich so vom Betriebssytem losgeschickt.

 

Jetzt muss ich dir allerdings recht geben: Wenn ich die Wi-Fi Strecke extern aufbaue von PC nach PC und dann über USB kommuniziere hab ich diesen Effekt nicht.

 

Die Frage ist also: Was macht die WIFI Extension, das dazu führt, dass das PC Betriebssystem mehrer Nachrichten in ein Paket zusammen schnürt?

screenshot.thumb.jpg.a55743e3ab23eac98451a0fb54bea7c7.jpg

Link to comment
Share on other sites

Bei mir redet der PC ja nichtmal direkt mit dem Stack, sondern per GBit Netzkabel mit der FritBox und die sendet die Pakete weg. Nur das Tablet kann direkt mit dem Stack kommunizieren. Umso komischer ist es, wenn das Betriebssystem hier was sammelt.

 

Ich werde mal einen tcpdump versuchen, den Stack auch als AP einrichten und damit testen, ob das einen Unterschied macht.

Link to comment
Share on other sites

Der tcpdump der ersten Packages beim Aufbau des Sockets Tablet -> PC (ohne Ruckler) sieht so aus

21:23:08.345168 IP Nexus.47643 > mypc.4223: Flags [s], seq 4037415093, win 14600, options [mss 1460,sackOK,TS val 11923547 ecr 0,nop,wscale 6], length 0
21:23:08.345249 IP mypc.4223 > Nexus.47643: Flags [s.], seq 3885023147, ack 4037415094, win 14480, options [mss 1460,sackOK,TS val 54800367 ecr 11923547,nop,wscale 7], length 0
21:23:08.347537 IP Nexus.47643 > mypc.4223: Flags [.], ack 1, win 229, options [nop,nop,TS val 11923548 ecr 54800367], length 0
21:23:08.349080 IP Nexus.47643 > mypc.4223: Flags [P.], seq 1:9, ack 1, win 229, options [nop,nop,TS val 11923548 ecr 54800367], length 8

 

Und beim Aufbau des WLAN

21:03:55.527714 IP mypc.51853 > tinkertest.4223: Flags [s], seq 1809126939, win 14600, options [mss 1460,sackOK,TS val 53647549 ecr 0,nop,wscale 7], length 0
21:03:55.532842 IP tinkertest.4223 > mypc.51853: Flags [s.], seq 1301543003, ack 1809126940, win 2896, options [mss 1460,nop,wscale 0,nop,nop,TS val 676614046 ecr 53647549], length 0
21:03:55.532956 IP mypc.51853 > tinkertest.4223: Flags [.], ack 1, win 115, options [nop,nop,TS val 53647555 ecr 676614046], length 0
21:03:55.537074 IP mypc.51853 > tinkertest.4223: Flags [P.], seq 1:9, ack 1, win 115, options [nop,nop,TS val 53647559 ecr 676614046], length 8

 

Was auffällt ist, dass "SackOK" fehlt.

SackOK gehört bei dieser Art Verbindung eigentlich mit zum Handshake - oder?

Link to comment
Share on other sites

Bei mir redet der PC ja nichtmal direkt mit dem Stack, sondern per GBit Netzkabel mit der FritBox und die sendet die Pakete weg.

Den Aufbau hab ich hier quasi auch: PC -> Gigabit Cisco Switch -> FritzBox -> Stack. Ich denke der Switch und der Router sind für die Probleme hier nicht relevant.

 

So wie ich das sehe passiert folgendes: Das WIFI Modul auf der WIFI Extension arbeitet mit delayed ACKs (http://en.wikipedia.org/wiki/TCP_delayed_acknowledgment). Ist in dem Screenshot auch zu sehen, dort gibt es ganz viele Nachrichten vom PC (77 Byte) und dann werden die alle mit einem ACK beantwortet. Nun scheint es aber so zu sein, dass der PC nach einer Zeit aufhört zu senden wenn er kein ACK bekommen hat. Das WIFI Modul sendet aber erst das delayed ACK wenn der Buffer voll ist (1500 Byte). Da gibt es ein Timeout von 200ms (d.h. wenn der Buffer nach 200ms nicht voll ist, sendet das WIFI Modul trotzdem das delayed ACK).

 

Da lagst du mit deinem "5hz ruckeln" schon sehr gut :).

 

Interessant ist jetzt: Wenn der Stack Nachrichten zum zurücksenden hat (damals die Reached Nachrichten vom Servo), dann wird das ACK auch schon frühzeitig zusammen mit diesen Nachrichten rausgeschickt. Daher gab es das 5hz ruckeln dort nicht.

 

Ich denke damit ist die Problematik ziemlich gut verstanden, es ist eine Mischung aus dem 200ms Timeout und der Anzahl der Nachrichten die das Betriebssystem schickt bevor es erstmal aufgibt wenn kein ACK kommt. Das Verhalten wird hier vermutlich von OS zu OS unterschiedlich sein.

 

Falls hier jemand weiß wie man sowas für gewöhnlich löst oder umgeht: Immer raus damit ;). Ich bin mir nicht sicher ob wir die 200ms Timeout  auf dem WIFI Modul verringern können. Dokumentiert ist da nichts, werde aber am Montag den Hersteller fragen.

 

 

Link to comment
Share on other sites

Das erklärt auch, warum es Ruckler in Kombination mit dem Quad-Relais gibt: wenn die Servo-Response aktiv ist, aber beim Relais nicht, führt der Monoflop-Impuls ohne Response zu einem 200ms Delay in der Netzwerkkommunikation.

 

Wenn ich für alle Befehle eine Response aktiviere, läuft es relativ flüssig :).

 

Falls sich am Netzwerkverhalten nichts mehr ändern lässt, wäre ein 3. Zustand beim Handling von 'responseExpected' denkbar (eher kleine Optimierung):

  • Nicht nur responseExpected true/false, sondern auch eine Art 'emptyResponse'
  • Bei 'emptyResponse' kehrt Device.sendRequest zurück, ohne auf die Response zu warten.
  • Der ReceiveThread wirft Responses dieser Art direkt weg

Link to comment
Share on other sites

Wow... interessant das zu lesen :D

 

Zum delayed ACK habe ich erstmal nur das einschlägige RFC (1122) bemüht:

A TCP SHOULD implement a delayed ACK, but an ACK should not

be excessively delayed; in particular, the delay MUST be

less than 0.5 seconds, and in a stream of full-sized

segments there SHOULD be an ACK for at least every second

segment.

 

Möglicherweise könnt ihr bei eurem Chip ja nicht nur am Timeout sondern auch am Zähler stellen? Also sowas wie "ACK auf jedes 3. Packet"?

Link to comment
Share on other sites

Die Ethernet Extension wird absolut stabil sein. Dort wird es keinerlei Verbindungsprobleme geben, versprochen :). Wir testen da jetzt schon seit Monaten dran rum um das sicherzustellen.

 

Das hier angesprochene delayed ACK "Problem" gibt es bei der Ethernet Extension auch nicht, dort kann man delayed ACKs nämlich ausstellen ;).

Link to comment
Share on other sites

Noch eine Frage:

kann ich dem Kommentar jetzt entnehmen, dass die Anfrage beim Hersteller ergeben hat, dass sich der delayed ACK nicht abstellen lässt?

 

Dann muss ich mir nämlich noch was überlegen, um den Durchsatz noch etwas zu erhöhen/optimieren. Aktuell liege ich bei ca. 80 Requests Sekunde (eben mit Response). Was nicht mehr viel ist, verglichen mit 1ms über USB.

 

... und eine Anregung:

wäre ein "ErrorCallback" oder Ähnliches in der API für Euch nicht hilfreich? Ich habe im WLAN Code so ein paar TODO gesehen für Fehlerbehandlung, wo sich auch die Frage stellt: was ist überhaupt eine sinnvolle Fehlerbehandlung. Wenn der Client wenigstens einen Callback mit einem Fehlercode bekäme, würde das oft helfen, Probleme zu analysieren. Bei der LAN Extension ist der Durchsatz potentiel viel höher. Da könnten Puffer noch schneller voll sein.

Link to comment
Share on other sites

Noch eine Frage:

kann ich dem Kommentar jetzt entnehmen, dass die Anfrage beim Hersteller ergeben hat, dass sich der delayed ACK nicht abstellen lässt?

Wir haben noch keine Antwort, die Mühlen mahlen da bei sowas leider langsam :(.

 

Dann muss ich mir nämlich noch was überlegen, um den Durchsatz noch etwas zu erhöhen/optimieren. Aktuell liege ich bei ca. 80 Requests Sekunde (eben mit Response). Was nicht mehr viel ist, verglichen mit 1ms über USB.

Wir sind noch dran, es gibt zumindest die Möglichkeit das wir händisch eine leere Nachricht rausschicken, wenn nach kurzer Zeit einer Anfrage keine Antwort rausgeht.

 

Also immer wenn eine Nachricht reinkommt wird ein 10ms Timer gestartet. Wenn eine Nachricht rausgeht wird dieser Timer gestoppt (mit der rausgehenden Nachricht wird ja auch ein ACK geschickt). Falls der Timer bei 0 ankommt schicken wir eine Dummy-Nachricht raus, um ein das ACK zu erzwingen. Damit wären dann in deinem Fall die 200ms Wartezeit auf 10ms verringert worden, dafür werden aber "unnötige" Daten geschickt (aber halt auch nur wenn sowieso keine Daten rausgehen).

 

Bei der LAN Extension ist der Durchsatz potentiel viel höher. Da könnten Puffer noch schneller voll sein.

Das IC was wir für die Ethernet Extension verwenden ist sehr low-level verglichen mit dem WIFI Modul. Dadurch gibt es diese Probleme gar nicht (wir haben das sozusagen selbst in der Hand). Da können keine Buffer voll laufen, da dem PC die Größe des Buffers mit der TCP window size mitgeteilt wird, wie es gedacht ist. Das hat natürlich auch nachteile, ich musste z.B. für die Ethernet Extension selbst einen DHCP Client implementieren, das war ganz schön aufwendig.

 

Bei dem WIFI Modul ist die API einfach beschissen. Es ist so, dass mit jedem Byte was wir rausschicken wir auch gleichzeitig eins empfangen. Da kann man nichts gegen machen. Wenn jetzt viele Nachrichten intern generiert werden (z.B. die Reached Callbacks vom Servo) und wir so viele Daten von extern bekommen, das in jeder ms neue Daten zum auslesen da sind, dann brauchen wir die Buffer.

 

In dem Fall ist es nämlich so, das wir z.B. 20 ausgehende Bytes generieren, die eingehenden Paket haben aber nur die Größe 10. Nun können wir aber nur ein Paket gleichzeitig behandeln, d.h. wir müssen 10 Byte Buffern damit wir das 20 Byte Paket überhaupt rausschicken können. Wenn der Buffer voll läuft müssen wir anfangen die ausgehenden Pakete wegzuwerfen. Total bekloppt :o.

 

Aber das hat nichts mit dem delayed ACK zu tun, wodurch du im Moment diese 5hz siehst.

Link to comment
Share on other sites

Was ein Krampf ;D.

 

Also GainSpan konnte uns da nicht wirklich weiterhelfen. Es gibt undokumentierte Möglichkeiten an den Timeouts rumzustellen, allerdings wurde dadurch die Firmware instabil. Wir hatten ständig disassociation Events.

 

Ich habe jetzt einen 10ms Timer eingebaut der bei eingehenden Nachrichten (neu-)gestartet wird. Eine ausgehende Nachricht stoppt den Timer. Wenn der Timer bei 0 ankommt, wird eine Dummy Nachricht rausgeschickt die das Zurücksenden eines ACKs erzwingt. Dadurch ist aus deinem 5Hz Ruckeln jetzt ein "100Hz Ruckeln" geworden. Rein akustisch klingt ein Servo mit deinem Programm jetzt genauso wie wenn es über USB betrieben wird.

 

Wenn es zwischendurch Ruckler gibt kommen die durch TCP/IP retransmits. Das kannst du sehr schön in Wireshark sehen, immer wenn es ruckelt laufen in Wireshark rote spalten (retransmit oder duplizierte Nachricht) durch. Dagegen können wir natürlich nichts machen, die Daten gehen nunmal über die Luftschnittstelle. Da geht schonmal was verloren und muss neu geschickt werden ;).

 

Im Anhang ist eine beta der neuen Master Firmware.

firmware_master_brick_2.0.6-beta1.bin

Link to comment
Share on other sites

Sieht sehr gut aus, so flüssig wie noch nie  :) ...

 

Es läuft auch merklich flüssiger als mit der Alternative über setResponseExpected(BrickServo.FUNCTION_SET_POSITION, true).

 

Ich hatte bei der Verwendung der Java-Bindings 2.0.5 nach einer Weile 1x komische "Verwirrungen" in der Kommunikation mit Timeouts. Nach Update dieser auf 2.0.6 läuft bis jetzt alles stabil!

Link to comment
Share on other sites

Hat mit diesem Thread zu tun: http://www.tinkerunity.org/forum/index.php/topic,1526.msg10100.html#msg10100

 

Der Watchdog startet den Brick neu wenn 16 Sekunden lang die "tick task" nicht mehr ausgeführt wurde (läuft normalerweise 1x pro ms). Das sollte auch noch funktionieren wenn es einen Hard Fault o.ä. gab.

 

Das einzige Problem ist das man Bugs die nur alle paar Wochen auftreten dann evtl. gar nicht mehr mitbekommt, zumindest wenn das Steuerprogramm robust geschrieben ist. Aber ein sinnvolles Feature ist es auf alle Fälle.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...