Jump to content

Recommended Posts

Ich habe leider schon wieder ein Problem :(:

 

Testaufbau:

  • Master mit Step-Down unten + WIFI Extension oben
  • DC-Brick ganz oben
  • Current/Voltage Bricklet hängt im Eingangsstrom des Stack und misst quasi den Stack; es sendet max. alle 0,5 Sekunden per Callback aktualsierte Werte für Strom,Spannung+Leistung (3 Callbacks)
     
  • Rotary Poti hängt am Master und sendet per Callback Wertänderungen max alle 0,2 Sekunden (also max 5x Sekunde)

Soweit klappt alles:

wenn ich am Poti drehe werden die Werte auf der Console ausgegeben und dazu erscheinen ab und zu geänderte Werte für den Energieverbrauch.

 

Wenn ich nun im Callback des Rotari Poti die Velocity des DC Bricks steuere, um damit die Motorgeschwindigkeit zu regeln, dann kommt es ab und zu vor, dass die IPConnection "hängt" und keine Callbacks mehr liefert. Strom am DC-Brick auslesen liefert dann immer rc=-1, Befehle zum DC Brick gesendet bleibt ohne Effekt. Manchmal fängt sich das wieder, manchmal aber auch nicht oder Mischformen: die Poticallbacks kommen an, die Änderungen in der Velocity haben aber keinen Effekt: Motor läuft unverändert weiter, dc_set_velocity liefert aber E_OK.

 

Beende ich das Programm hart und starte es neu, dann reagiert der Stack meist normal, ich kann den Motor wieder steuern (kein Stack-Reset). Ich muss den Stack vereinzelt aber auch resetten. CPU-Last auf PC ist quasi 0. Ich habe keine Response-Expected flags gesetzt (alles Default).

 

Aktuell sieht es danach aus, dass der Effekt verstärkt dann auftritt, wenn ich die Velocity auf Maximum gesetzt habe (Poti -150 -> Velocity -32767, Poti 150 -> Velocity 32767). Der Accellaration-Wert ist auf 32767 gesetzt, was den Motor binnen 1 Sekunde auf max beschleunigen kann.

 

Die Menge an WIFI Paketen pro Sekunde dürfte 20 nicht übersteigen (max. 6 vom Voltage/Current, 5 vom Poti + 5 zum DC Brick - anders als damals beim Servo-Brick, wo es sehr viele Pakete waren. Dennoch hängt die Verbindung ab und zu.

 

Firmware ist aktuell, Umgebung ist Intel Linux auf PC mit g++ 4.6.2 und C Bindings 2.0.8. Der Stack wird mit ca. 12V LiPo Akku versorgt, der Motor zieht ca. 150mA; Stack gesamt ca 250mA, die Spannung sackt auch nicht ab.

Stacktraces zwischendurch sind nicht so richtig ergebnisreich, da das Programm ja mit gdb gestoppt wird, sieht z. B. so aus:

 

Thread 5 (Thread 0x7fc599577700 (LWP 4028)):
#0  0x00007fc59a49a2bc in send () from /lib64/libpthread.so.0
#1  0x000000000041e020 in socket_send (length=<optimized out>, buffer=0x7fc599576d60, socket=<optimized out>) at ip_connection.c:274
#2  ipcon_send_request (ipcon=0x7fff69a71df8, request=0x7fc599576d60) at ip_connection.c:1532
#3  0x000000000041ec46 in device_send_request (device=0x7fc588009f10, request=0x7fc599576d60, response=0x0) at ip_connection.c:924
#4  0x0000000000411a02 in dc_set_velocity (dc=0x7fc588009f10, velocity=-13106) at brick_dc.c:362
#5  0x000000000040db71 in brickapi::MotorBrick::accelerateTo (this=0x7fc588009ec0, speed=-13106) at Brick.cpp:152
#6  0x00000000004037fe in PotiEvent::valueChanged (this=0x7fff69a73050, item=0x7fc588008090, newValue=-60) at bricktests.cpp:89
#7  0x000000000040f796 in brickapi::SensorItem::valueChanged (this=0x7fc588008090, _value=-60) at SensorItem.cpp:249
#8  0x000000000040a26a in brickapi::Potentiometer::callback (value=-60, user_data=0x7fc588008090) at Potentiometer.cpp:82
#9  0x000000000041e1f8 in ipcon_dispatch_packet (packet=0x7fc590000b40, ipcon=<optimized out>) at ip_connection.c:1115
#10 ipcon_callback_loop (opaque=0x630140) at ip_connection.c:1144
#11 0x000000000041d74e in thread_wrapper (opaque=<optimized out>) at ip_connection.c:534
#12 0x00007fc59a492f05 in start_thread () from /lib64/libpthread.so.0
#13 0x00007fc599a5f10d in clone () from /lib64/libc.so.6

Thread 4 (Thread 0x7fc598d76700 (LWP 4030)):
#0  0x00007fc59a4971eb in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x000000000041d8e6 in event_wait (event=0x7fff69a72f00, timeout=<optimized out>) at ip_connection.c:399
#2  0x000000000041f355 in ipcon_disconnect_probe_loop (opaque=0x7fff69a71df8) at ip_connection.c:1197
#3  0x000000000041d74e in thread_wrapper (opaque=<optimized out>) at ip_connection.c:534
#4  0x00007fc59a492f05 in start_thread () from /lib64/libpthread.so.0
#5  0x00007fc599a5f10d in clone () from /lib64/libc.so.6

Thread 3 (Thread 0x7fc598575700 (LWP 4032)):
#0  0x00007fc59a49a12c in recv () from /lib64/libpthread.so.0
#1  0x000000000041e481 in socket_receive (length=800, buffer=0x7fc598574b50, socket=<optimized out>) at ip_connection.c:270
#2  ipcon_receive_loop (opaque=0x7fff69a71df8) at ip_connection.c:1275
#3  0x000000000041d74e in thread_wrapper (opaque=<optimized out>) at ip_connection.c:534
#4  0x00007fc59a492f05 in start_thread () from /lib64/libpthread.so.0
#5  0x00007fc599a5f10d in clone () from /lib64/libc.so.6

Thread 2 (Thread 0x7fc597d74700 (LWP 4033)):
#0  0x00007fc59a4971eb in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x0000000000407c92 in __gthread_cond_timedwait (__cond=0x7fff69a72fe8, __mutex=0x7fff69a73018, __abs_timeout=0x7fc597d73c50)
    at /usr/include/c++/4.6/x86_64-suse-linux/bits/gthr-default.h:853
#2  0x0000000000408d49 in std::condition_variable::__wait_until_impl<std::chrono::system_clock, std::chrono::duration<long, std::ratio<1l, 1000000l> > > (this=0x7fff69a72fe8, __lock=..., __atime=...) at /usr/include/c++/4.6/condition_variable:158
#3  0x0000000000408a3b in std::condition_variable::wait_until<std::chrono::duration<long, std::ratio<1l, 1000000l> > > (
    this=0x7fff69a72fe8, __lock=..., __atime=...) at /usr/include/c++/4.6/condition_variable:95
#4  0x0000000000408703 in std::condition_variable::wait_for<long, std::ratio<1l, 1000l> > (this=0x7fff69a72fe8, __lock=..., __rtime=...)
    at /usr/include/c++/4.6/condition_variable:127
#5  0x0000000000407f07 in brickapi::AsyncTask::shouldFinish (this=0x7fff69a72fd0, waitMs=1000) at AsyncTask.cpp:76
#6  0x00000000004031e7 in PowerLog::run (this=0x7fff69a72fd0) at bricktests.cpp:69
#7  0x0000000000407e1a in brickapi::AsyncTask::callRunMethod (this=0x7fff69a72fd0) at AsyncTask.cpp:48
#8  0x0000000000409f00 in std::_Mem_fn<void (brickapi::AsyncTask::*)()>::operator() (this=0x630b08, __object=0x7fff69a72fd0)
    at /usr/include/c++/4.6/functional:551
#9  0x0000000000409e69 in std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)>::__call<void, , 0>(std::tuple<>&&, std::_Index_tuple<0>, std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)>::__enable_if_void<void>::type) (this=0x630b08, __args=...) at /usr/include/c++/4.6/functional:1287
#10 0x0000000000409e03 in std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)>::operator()<>() (
    this=0x630b08) at /usr/include/c++/4.6/functional:1378
#11 0x0000000000409d42 in std::thread::_Impl<std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)> >::_M_run() (this=0x630af0) at /usr/include/c++/4.6/thread:117
#12 0x00007fc59a1f6058 in ?? () from /usr/lib64/libstdc++.so.6
#13 0x00007fc59a492f05 in start_thread () from /lib64/libpthread.so.0
#14 0x00007fc599a5f10d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7fc59ab7a720 (LWP 4024)):
#0  0x00007fc599a5118d in read () from /lib64/libc.so.6
#1  0x00007fc5999f6d18 in _IO_new_file_underflow () from /lib64/libc.so.6
#2  0x00007fc5999f7d8e in _IO_default_uflow_internal () from /lib64/libc.so.6
#3  0x00007fc5999f3108 in getchar () from /lib64/libc.so.6
#4  0x00000000004033e6 in runTests (host=0x7fff69a74110 "tinkertest") at bricktests.cpp:132
#5  0x00000000004035c5 in main (argc=3, argv=0x7fff69a731e8) at bricktests.cpp:163



======================= 2. Stacktrace ===============================
---------------------------------------------------------------------

Thread 5 (Thread 0x7f2b16106700 (LWP 4364)):
#0  0x00007f2b17028010 in sem_wait () from /lib64/libpthread.so.0
#1  0x000000000041e175 in semaphore_acquire (semaphore=<optimized out>) at ip_connection.c:479
#2  queue_get (length=<synthetic pointer>, data=<synthetic pointer>, kind=<synthetic pointer>, queue=0x630148) at ip_connection.c:731
#3  ipcon_callback_loop (opaque=0x630140) at ip_connection.c:1126
#4  0x000000000041d74e in thread_wrapper (opaque=<optimized out>) at ip_connection.c:534
#5  0x00007f2b17021f05 in start_thread () from /lib64/libpthread.so.0
#6  0x00007f2b165ee10d in clone () from /lib64/libc.so.6

Thread 4 (Thread 0x7f2b15905700 (LWP 4366)):
#0  0x00007f2b170261eb in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x000000000041d8e6 in event_wait (event=0x7fff32d5c8f0, timeout=<optimized out>) at ip_connection.c:399
#2  0x000000000041f355 in ipcon_disconnect_probe_loop (opaque=0x7fff32d5b7e8) at ip_connection.c:1197
#3  0x000000000041d74e in thread_wrapper (opaque=<optimized out>) at ip_connection.c:534
#4  0x00007f2b17021f05 in start_thread () from /lib64/libpthread.so.0
#5  0x00007f2b165ee10d in clone () from /lib64/libc.so.6

Thread 3 (Thread 0x7f2b15104700 (LWP 4367)):
#0  0x00007f2b1702912c in recv () from /lib64/libpthread.so.0
#1  0x000000000041e481 in socket_receive (length=800, buffer=0x7f2b15103b50, socket=<optimized out>) at ip_connection.c:270
#2  ipcon_receive_loop (opaque=0x7fff32d5b7e8) at ip_connection.c:1275
#3  0x000000000041d74e in thread_wrapper (opaque=<optimized out>) at ip_connection.c:534
#4  0x00007f2b17021f05 in start_thread () from /lib64/libpthread.so.0
#5  0x00007f2b165ee10d in clone () from /lib64/libc.so.6

Thread 2 (Thread 0x7f2b14903700 (LWP 4368)):
#0  0x00007f2b170261eb in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x0000000000407c92 in __gthread_cond_timedwait (__cond=0x7fff32d5c9d8, __mutex=0x7fff32d5ca08, __abs_timeout=0x7f2b14902c50)
    at /usr/include/c++/4.6/x86_64-suse-linux/bits/gthr-default.h:853
#2  0x0000000000408d49 in std::condition_variable::__wait_until_impl<std::chrono::system_clock, std::chrono::duration<long, std::ratio<1l, 1000000l> > > (this=0x7fff32d5c9d8, __lock=..., __atime=...) at /usr/include/c++/4.6/condition_variable:158
#3  0x0000000000408a3b in std::condition_variable::wait_until<std::chrono::duration<long, std::ratio<1l, 1000000l> > > (
    this=0x7fff32d5c9d8, __lock=..., __atime=...) at /usr/include/c++/4.6/condition_variable:95
#4  0x0000000000408703 in std::condition_variable::wait_for<long, std::ratio<1l, 1000l> > (this=0x7fff32d5c9d8, __lock=..., __rtime=...)
    at /usr/include/c++/4.6/condition_variable:127
#5  0x0000000000407f07 in brickapi::AsyncTask::shouldFinish (this=0x7fff32d5c9c0, waitMs=1000) at AsyncTask.cpp:76
#6  0x00000000004031e7 in PowerLog::run (this=0x7fff32d5c9c0) at bricktests.cpp:69
#7  0x0000000000407e1a in brickapi::AsyncTask::callRunMethod (this=0x7fff32d5c9c0) at AsyncTask.cpp:48
#8  0x0000000000409f00 in std::_Mem_fn<void (brickapi::AsyncTask::*)()>::operator() (this=0x630b08, __object=0x7fff32d5c9c0)
    at /usr/include/c++/4.6/functional:551
#9  0x0000000000409e69 in std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)>::__call<void, , 0>(std::tuple<>&&, std::_Index_tuple<0>, std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)>::__enable_if_void<void>::type) (this=0x630b08, __args=...) at /usr/include/c++/4.6/functional:1287
#10 0x0000000000409e03 in std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)>::operator()<>() (
    this=0x630b08) at /usr/include/c++/4.6/functional:1378
#11 0x0000000000409d42 in std::thread::_Impl<std::_Bind_result<void, std::_Mem_fn<void (brickapi::AsyncTask::*)()> (brickapi::AsyncTask*)> >::_M_run() (this=0x630af0) at /usr/include/c++/4.6/thread:117
#12 0x00007f2b16d85058 in ?? () from /usr/lib64/libstdc++.so.6
#13 0x00007f2b17021f05 in start_thread () from /lib64/libpthread.so.0
#14 0x00007f2b165ee10d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f2b17709720 (LWP 4363)):
#0  0x00007f2b165e018d in read () from /lib64/libc.so.6
#1  0x00007f2b16585d18 in _IO_new_file_underflow () from /lib64/libc.so.6
#2  0x00007f2b16586d8e in _IO_default_uflow_internal () from /lib64/libc.so.6
#3  0x00007f2b16582108 in getchar () from /lib64/libc.so.6
#4  0x00000000004033e6 in runTests (host=0x7fff32d5d110 "tinkertest") at bricktests.cpp:132
#5  0x00000000004035c5 in main (argc=3, argv=0x7fff32d5cbd8) at bricktests.cpp:163

Link to post
Share on other sites

Anbei ein Testprogramm mit dem ich das Verhalten reproduzieren kann, wenn ich das Poti hin und her drehe. Manchmal fängt sich der Stack, wenn ich das Programm mit kill -9 beende und neu starte. Vereinzelt hängt sich aber der ganze Stack auf und der Motor läuft einfach weiter ...

 

Nach <ENTER> auf der Console müsste sich das Programm eigentlich beenden, es verharrt aber hier:

#0  0x00007f5c279ce8d4 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007f5c279ca1c5 in _L_lock_883 () from /lib64/libpthread.so.0
#2  0x00007f5c279ca01a in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x000000000040448d in ipcon_send_request (ipcon=0x7fffa1d9e5d0, request=0x7fffa1d9e5b0) at ip_connection.c:1525
#4  0x00000000004050d6 in device_send_request (device=0x608160, request=0x7fffa1d9e5b0, response=0x0) at ip_connection.c:924
#5  0x0000000000401c42 in dc_disable (dc=0x608160) at brick_dc.c:617
#6  0x0000000000401212 in main (argc=<optimized out>, argv=<optimized out>) at dc_test.cpp:116

 

Edit:

und noch was ist mir gerade in diesem Testprogramm aufgefallen: vereinzelt startet das Programm erst gar nicht, sondern läuft auf einen Segementation fault, weill der Hauptthread schneller ist, als die IP-Connection Threads. Soll bedeuten, wenn ich den sleep(1) hier ergänze:

 

    if (ipcon_connect(&ipcon, host, 4223) < 0) {
        printf("Could not connect to brickd at %s:4223", host);
        return 1;
    }

    sleep(1);
    rotary_poti_create(&potiDevice, uidPoti, &ipcon);

 

läuft alles OK, ist der weg, kracht's vereinzelt.

Der connect sollte intern wohl eine kleine Wartezeit einbauen, damit die Threads alle initialisiert sind (ist aber ein anderes / zusätzliches Thema).

dc_test.cpp

Link to post
Share on other sites

Der connect sollte intern wohl eine kleine Wartezeit einbauen

 

Besser blockieren bis alles fertig ist. Offenbar gibts da ja eine gewisse Portion Nebenläufigkeit die fertig sein muss damit weitere Aufrufe funktionieren.

Link to post
Share on other sites

Ist das denn wieder ein WLAN Problem? Also hast du die Probleme auch wenn du es direkt per USB anschließt? Ich teste deinen Beispielcode heute Abend, mal gucken ob ich das reproduzieren kann.

Link to post
Share on other sites

Generell gilt, dass du die Kommunikation aus dem Tritt bringen kannst, wenn z.B. in den Headern der Pakete falsche Daten stehen. Das Problem hatten wir ja schon :(

 

Das die IP Connection "hängt" und keine Callbacks mehr ausliefert, kann daran liegen, dass der Receive Thread nicht mehr richtig funktioniert und keine Callback-Pakete mehr empfängt; oder daran, dass du den Callback Thread in einer deiner Callback-Funktionen blockierst, das gibt dein Testprogramm allerdings nicht her.

 

Dass dc_set_velocity ohne Response-Expected E_OK sagt ist zu erwarten, da E_OK bei Settern ohne Response-Expected soviel heißt wie: ich bin die Anfrage über den Socket losgeworden, mehr nicht.

 

Die beiden Stacktraces im ersten Post sehen normal aus.

 

Dass das dc_disable() beidem Beenden allerdings im ipcon_send_request() ewig auf den socket_mutex wartet ist verdächtig. Wobei da Zeile 1525 nicht passt, es müsste 1523 sein, hast du da vielleicht lokale Änderungen in ip_connection.c, oder verwendest doch nicht die aktuelle Version? Interessant wäre hier ein voller Stacktrace aller Thread um zu sehen, wer da gerade auf dem socket_mutex sitzt.

 

Das du nach dem ipcon_connect() eine sleep(1) brauchst um einen Segfault zu vermeiden ist verdächtig. Eigentlich sollte ipcon_connect() nicht auf das Starten des Receive und des Callback Thread warten müssen. Diese sind nicht an der Initialisierung globaler Datenstrukturen beteiligt. Soll heißen, selbst wenn die beiden Thread nie starten solltest du im schlimmsten Fall einfach keine Antworten auf Getter und keine Callbacks bekommen, aber keinen Segfault.

 

Hast du dir male neben GDB Traces angesehen was Valgrind zu deinem Programm meint.

Link to post
Share on other sites

Ich habe in ip_connection.c zwei printf-Aufrufe eingebaut an Stellen, wo ein unbekanntes Paket kommt bzw. queue_get auf Fehler läuft - die werden aber nicht aufgerufen - darum 2 Zeilen mehr.

 

Per USB scheint es zu funktionieren, d. h. sieht eher nach einem WLAN Problem aus. Die Responses kommen vereinzelt auch stark verzögert wie damals beim Servobrick (erst X Sekunden nichts und dann viele Poti-Callbacks auf einmal, dann reagiert der DC-Brick meist aber auch nicht mehr).

 

Das mit dem segfault prüfe ich nochmal.

Link to post
Share on other sites

Das mit dem segfault bekomme ich nicht mehr reproduziert.

 

Vermutlich habe ich beim Extrahieren der Testsource aus der Komplettanwendung einen Fehler gemacht. Ich glaub am Anfang hatte ich in der Testsource eine Init-Sequenz der Art

...create
...register_callback
...create
...register_callback

Und dabei ist es möglich, dass direkt nach dem ersten register_callback dieser schon aufgerufen wird uns auf das unitialisierte zweite Device zugreift.

 

Die normale Anwendung initialisiert anders und dort ist das nie aufgetreten.

 

Die Probleme mit dem DC Brick bestehen noch, auch mit dem letzten Update der Power-Sensor Firmware.

Link to post
Share on other sites

Ich versuche mal den aktuellen Status zusammenzufassen und noch einige Fragen zu stellen:

 

 

1) Du rufst dc_set_velocity() im position Callback des Rotary Potis auf um mit dem Poti die Geschwindigkeit des Motors zu steuern. Wenn du am Poti drehst kommt es vor, dass die IP Connection "hängt" und keine Callbacks mehr ausliefert. Dazu zwei Fragen:

 

1a) Wie erkennst du das keine Callbacks mehr ausgeliefert werden? Du drehst am Poti, die Motorgeschwindigkeit bleibt aber unverändert? Und du siehst auch die Ausgabe vom printf im position Callback nicht?

 

1b) Tritt das nur auf wenn du am Poti drehst, oder passiert das auch wenn der Motor nur unverändert vor sich hin läuft?

 

 

2) Das Problem tritt häufiger auf wenn der Motor schneller dreht. Dazu auch eine Frage:

 

2a) Kann das ein EMV Problem sein und der Motor stört den Stack?

 

 

3) Was ist mit dem dc_disable() nach dem Enter-Drücken, hängt der immer noch?

 

 

4) Der Segfault in deinem Testprogramm war eine Problem mit der Initialisierung im Programm und kein Problem in den Bindings selbst.

Link to post
Share on other sites

Ja, über das Poti steuere ich testhalber die Geschwindigkeit des Motors.

Zu den Fragen:

 

1a) Ja: ich kann am Poti drehen und nichts passiert. Außerdem kommen normalweise immer wieder Änderungen per Callback vom Power-Sensor, da mit geänderter Drehzahl sich ja auch die Stromstärke ändert und der Akku immer ein paar Millivolt verliert. Es kommen normalerweise mindestens 2 Callbacks pro Sekunde (Ausgabe in Console). Diese Callbacks bleiben aus. Im guten Fall kommt nach X Sekunden (z. B. 15) ein ganzer Schwung an Messwerten und Poti-Werten und das System fängt sich wieder. Im Worst Case muss ich den Stack neu booten, da auch ein erneuter Connect sonst nicht mehr funktioniert.

 

1b) ich habe ihn noch nie länger laufen lassen, kann ich mal versuchen.

 

2a) der Motor ist recht klein und hat kleine Entsörtkondensatoren an den Anschlüssen und zum Gehäuse. Er liegt ca. 20cm vom Stack entfernt. Wie kann ich erkennen, ob der den Stack ggf. stört?

Es ist aber schon auffällig, dass gerade bei Aufdrehen auf max. Geschwindigkeit der "Hänger" eher auftritt.

 

3) ja: wenn sich der Stack nicht fängt zeigen ausgehende Befehle keine Reaktion mehr. Drücke ich zu einer Zeit ENTER, wo der Stack normal reagiert, dann stoppt der Motor wie gewollt.

 

4) korrekt, hat nichts mit den Bindings zu tun.

Link to post
Share on other sites

1a) Diese Burst-Verhalten hört sich ja schon nach WIFI Problem an. Hast du dir die WIFI Kommunikation mal in Wireshark angesehen, um zu sehen ob die per WIFI auch so eingehen und nicht irgendwie in den C Bindings verlangsamt wird, wobei ich gerade nicht wüsste wie das passieren sollte, aber wer weiss.

 

 

2a) Hast du mal ohne Motor dran getestet? Hast du mal eine andere Stromversorgung ausprobiert? Vielleicht packt dein Akku den Anfahrtsstrom des Motors nicht und die Spannung bricht dadurch so sehr ein, dass das den Stack beeinflusst.

 

 

3) Ich meinte, dass dein Steuerprogramm dauerhaft in dc_enable() hängt. Das sollte nicht passieren, falls dem so ist sieht das nach einem Bug aus. Selbst wenn der Stack nicht reagiert sollten Getter und Setter mit Response Expected nach 2,5sec (oder auf was du den Timeout gestellt hast) returnen. Setter ohne Response Expected sollte direkt returnen. Daher meine Frage nach einem Backtrace aller Threads in diesem Fall, da es in dem einen Backtrace zu dem Problem so aussieht als würde da jemand dauerhaft auf dem socket_mutex hocken, was nicht sein darf.

Link to post
Share on other sites

Die Netzkommunikation kann ich mir mal ansehen und auch mal ohne Motor testen.

 

Am Akku liegt es nicht: ich hatte erst einen 9,6V Akku 1,8Ah und dann auch noch einen 3-Zellen LiPo Akku (voll geladen 2,5Ah). Der Motor zieht nur 80-200mA und der Effekt tritt mit beiden Akkus auf.

 

Nochmal zu 3):

ja - wenn der Effekt auftritt hängt das Programm nach drücken von Enter im dc_disable() und lässt sich nur noch durch ein SIGKILL beenden. Ein response-expected ist nicht explizit gesetzt, alles ist quasi "Default", auch die Timeout-Werte.

 

Ich werde mal der Reihenfolge nach

- einen Stacktrace (Snapshot) liefern im Normalbetrieb

- einen Stacktrace liefern, wenn's klemmt

- ohne Motor testen

- die Netzkommunikation mitschneiden

Link to post
Share on other sites

Ich kann den Hänger recht schnell reproduzieren, wenn ich mit Acceleration 0 das Poti auf Maximum drehe und damit max Velocity am DC Brick setze. Danach läuft der Motor weiter und nimmt keine Commands mehr an. Meist muss ich den Stack dann resetten, nur ab und zu fängt sich das System.

 

Manchmal beendet sich das Programm nach ENTER drücken noch, der Motor läuft dann aber dennoch weiter! D. h. der dc_disable wird gesendet, aber ohne Wirkung. Bei einem Neustart der Anwendung hängt der Connect dann (Anwendung kann sich nicht mehr verbinden - hängt, hilft nur noch reset).

 

Komplett ohne Last konnte ich das nicht reproduzieren :(. Allerdings kommen dann von Haus aus nur max 5-6 Callback (5 vom Poti + evtl. 1 vom Power-Sensor). Nur mit Last erzeugt der Power-Sensor ja geänderte Werte.

 

Ich habe zwei gdb-Traces hier angehängt, sonst wäre der Post zu groß gewesen:

beim ersten läuft der Motor schon unkontrolliert und lässt sich nicht mehr steuern. ENTER wurde noch nicht gedrückt. Bei diesem Testfall hat sich das Programm nach ENTER noch normal beendet, aber den Motor lief dennoch weiter.

 

Der zweite hat einen Zustand, nach ENTER wo das Programm eigentlich schon enden will, aber in der Netzkommunikation zum Stack hängt.

 

Ich scheitere gerade an einer 12V Glühbirne die ich nicht habe, um eine andere Last-Art zu testen.

gdb_traces.txt

Link to post
Share on other sites

Der zweite GDB Trace zeigt ein Deadlock. Da war eine Race Condition zwischen der disconnect() Funktion und dem Disconnect Probe Thread die du da getroffen hast. In den angehängten C Bindings ist das Problem behoben und du solltest es mit diesen nicht mehr schaffen können, dass dein Programm beim Beenden hängt.

 

Da es ohne Motor zu funktionieren scheint, muss das Problem des hängenden Stacks ja mit dem Motor direkt oder indirekt zusammenhängen. Dazu fallen mit verschiedenen Dinge ein:

 

 

1) Es könnte wie gesagt mit der Stromversorgung zusammenhängen. Der Motor zieht beim Anfahren mit voller Beschleunigung viel mehr Strom also die 80-200mA die du angibst. Dadurch bricht die Versorgungsspannung ein und der Stack verträgt das nicht.

 

Hierzu könntest du testen den Stack und den Motor nicht aus der gleichen Quelle zu versorgen. Dann kann der Motor den Stack nicht mehr über die Stromversorgung beeinflussen.

 

Dabei dann das Voltage/Current an die Versorgung des Motors hängen, damit die Callbacks weiter kommen.

 

Ja, ich weiss ich beharre stark auf diesem Gedanken :)

 

Eine andere Art von Last (z.B. eine Lampe) ist potentiell auch ein guter Test.

 

 

2) Du sagst, dass Problem tritt häufiger wenn du die Beschleunigung auf Maximum stellst. Geht das Problem dann weg, wenn du die Beschleunigung deutlich unter Maximum stellst?

 

 

3) Du hast den Motor 20cm vom Stack entfernt liegen. Macht es einen Unterschied wenn du den Motor deutlich weiter weg (1-2m) legst?

tinkerforge_c_bindings_2_0_8_74953a5547502075cede11c872b82dad8d10639e.zip

Link to post
Share on other sites

Ich hab's mal andersrum gemacht: nicht 'nen stärkeren Akku, sondern einen Schwächeren genommen (weniger Spannung).

 

=> der Effekt tritt deutlich seltener auf bzw. wird extrem schwer zu reproduzieren. Das verstärkt den Verdacht, dass der Motor den Stack stört.

 

Wenn ich den Motor an einen Fahrtregler anschließe und per Servobrick steuere klappts (Motor ist in etwa in gleicher Entfernung).

 

Das würde bedeuten, dass über die Motor-Stromzufuhr Spannungsspitzen zurück auf den Stack übertragen werden, die diesen dann zum Absturz bringen.

 

Wie kann ich das verhindern?

Die Entstörkondensatoren scheinen nicht ausreichend zu sein.

Link to post
Share on other sites

In beiden Fällen über dieselbe Spannungsversorgung, wobei ich die Eingangsspannung immer an die Step-Down und auch an den Eingang des RC/Servo-Bricks lege, damit nicht zwingend alles über die internen Leitungen des Stacks geht. Das scheint aber keinen Effekt zu haben, da eine externe Spannung am DC/Servo-Brick wohl etwas höher sein muss als die Stack-Spannung damit das als solche erkannt wird - oder?

Link to post
Share on other sites
  • 2 weeks later...

Nach diversen Test bin ich jetzt der festen Überzeugung:

der Bürstenmotor bringt den Stack zum Absturz, wenn die Bürstenfunken zu stark werden. Das ganze überträgt sich über die Motoranschlüsse zurück zum DC Brick und stört dann alles.

 

Nehme ich ein schwächeres Akku (9,6 statt 12) ist alles OK.

Nehme ich einen Motor mit 16V Nennspannung und 12V Akku ist auch alles OK.

Der Abstand des Motors zum Brick spielt keine Rolle.

 

Die Frage ist nun:

kann ich den Stack noch durch irgendeine Schutzschaltung vor sowas schützen? Die Entstörkondensatoren allein reichen nicht aus. Habt Ihr eine Idee?

Link to post
Share on other sites

Die Entstörkondensatoren sind schon dran.

Die Schottky-Diode scheidet aus wegen der Polumkehr.

Bleibt noch der Einbau von Drosseln übrig.

 

Ein Fahrtregler zeigt sich völlig unbeeindruckt von dem Motor. Nur das DC Brick mag das nicht, d. h. ich brauche eine Entsörung, die speziell dieses Phänomen löst.

 

Was ich wohl mal versuchen werde:

2 Zener-Dioden (z.B. 16V) in Reihe aber gegenläufig zwischen die Pole. D. h. die Sperrspannung in Summe ist dann etwas höher als die Zenerspannung. Ob das schnell genug reagiert, um weniger Spannungsspitzen auf das DC Brick zu übertragen, ist die Frage.

 

Link to post
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...