Forum: Mikrocontroller und Digitale Elektronik Arduino bleibt nach einer gewissen Zeit einfach hängen


von Jonathan K. (burgerohnealles)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hab grad ein Programm für meinen Arduino geschrieben, dass das 
Netzwerk nach Geräten abscannt und in einer Datei auf der MicroSD-Karte 
das ganze speichert. Das funktioniert auch, aber der Arduino bleibt 
immer nach einer gewissen Zeit (bis jetzt nach max. 5 min) hängen und 
gibt ab da in der Konsole entweder gar nichts mehr, ein paar komische 
Zeichen und dann gar nichts mehr oder nur noch unendlich viele komische 
Zeichen aus. Das Programm bleibt da einfach hängen. Woran kann das 
liegen?

Danke im Vorraus
burgerohnealles

von g457 (Gast)


Lesenswert?

> uint8_t devices[8];
                  ^
[..]
> for (uint8_t i=1; i<=254; i++) { // 1 // 255
                    ^^^^^^
[..]
>     devices[i/8] |= 1<<(i%8);
              ^^^
HTH

von Jonathan K. (burgerohnealles)


Lesenswert?

Ups. Logisch, dass es irgendwann hängen bleibt. Aber kann mir jemand 
erklären, was genau im ATmega328P vorgeht, dass es dann gar nichts mehr 
oder nur Quatsch macht?

von Jonathan K. (burgerohnealles)


Lesenswert?

Arrghh. Bleibt wieder hängen :( Ich habe
1
uint8_t devices[8];
 zu
1
uint8_t devices[32];
 und
1
f.write(devices, 8);
 zu
1
f.write(devices, 32);
 geändert. Aber wie gesagt, es bleibt wieder hängen. Was ist da noch 
falsch, bzw. wie gehe ich bei so einem Fall richtig vor, um das Problem 
zu lösen?

Hier nich die letzten Zeilen, die bei mir am Läppi ankamen:
1
74: load data ... ok ... connect data ... ok ... send data ... ok ... free memory ... ok ... wait for reply ... timeout, no reply
2
75: load data ... ok ... connect data ... ok ... send data ... ok ... free memory ... ok ... wait for reply ... timeout, no reply
3
76: load data ... ok ... connect data ... ok ... send data ... ok ... free memory ... ok ... wait for reply ... free memo

von Gusti (Gast)


Lesenswert?

Lies mal in einem Tutorial wie man ein Array verwendet. Das 1. Element 
im Array wird mit 0 angesprochen. Du initialisierts i mit 1. Wie soll 
dann bitte das 1. Element einen Wert bekommen.
Aber das wird nicht das Problem sein.

>was genau im ATmega328P vorgeht, dass es dann gar nichts mehr
>oder nur Quatsch macht?

Wenn dein Array auf 8 ist dann greifst du auf Specher zu, der nicht zum 
Array gehört, sondern zu irgendetwas anderem. Somit versaust dir deine 
anderen Variablen. Wenn du glück hast, dann ist dort nichts abgelegt. 
Dann merkst du nichts. Beim Computer würde das Betriebsystem dies 
verhindern und dein Programm würde mit einer Fehlermeldung stehen 
bleiben. Bei Windows würde dann kommen Program xyz funktioniert nicht 
mehr....
Beim uc fehlt diesr Schutz und dann macht es halt irgendetwas.

Ich vermute mal, dass du das meiste zusammenkopiert hast und jetzt 
versuchst es abzuändern, ohne wircklich zu verstehen was da passiert und 
wie man arrays verwendet. Ich würde dir ein C Tutorial empfehlen, da dir 
Grundkentnisse zu Arrays fehlen.

von µC_Starter (Gast)


Lesenswert?

Hallo,

das was Gusti empfohlen hat stimmt leider :-(

Hab das selbst erfahren - da hat mann praktische erfahrung von mehr als 
15 Jahren mit der Elektronik - sowohl Analog als auch Digital kennt die 
kleinen Gemeinheiten und (scheinbaren) selbstverständlichkeiten und 
möchte dann endlich in die µC Nutzung einsteigen- Aufbau, elektrische 
Ansteuerung, nutzung von Transistoren und MOSFET usw. - halt die ganze 
Hardware kein Problem.
Andererseits nie interesse an der Programmierung eines Computers gehabt 
- es gibt ja alles fertig ;-) und somit kaum Erfahrung mit 
Programmiersprachen.
Da sollte es doch möglich sein das Programmieren speziell für den µC 
(hier AVR und Sprache C) lernen zu können...
Und festgestellt => es geht nicht - die Tipps welche immer wieder 
gegeben werden (und die mir auch zuerst nicht gefallen haben) erstmal 
die Grundlagen am Computer zu erlernen sind (leider) richtig.
Ja da fängt mann mit der "Hallo world" Textausgabe auf den Monitor an, 
schafft ja nach Zeit und Lust dann nach einigen Wochen bis Monaten eine 
einfache Datenbank zu programmieren (welche aber Lichtjahre von 
Anwendungen wie Open Office entfernt ist) und fragt sich warum das Ganze 
?- Ich will doch nur einen µC Programmieren können um meine 
....steuerung endlich realisieren zu können.
Wenn es dann aber doch endlich mit den µC losgeht und mann sich die 
Beispiele, Datenblätter und Tutorials entschaut und aufeinmal versteht 
was gemeint ist, die Gedankengänge nochvollziehen kann dann wird einen 
auf einmal klar wieso der scheinbare Umweg nötig war.

Gerade Arduino verleitet erstmal dazu sich das Programm (Sketch) 
zusammen zu kopieren - das kann sogar funktionieren  allerdings lehrnt 
mann dabei sehr wenig und mann wird niemals selbst etwas anpassen oder 
entwickeln können und wird auch immer auf teuere fertige Hardware 
(shields) angewiesen bleiben
Den seltenen Sensor, der preiswerte Restposten, das neuste Display usw. 
auch mit ausfühlichen Datenblatt wird mann so nicht selbstständig zu 
laufen bringen und mann muss immer warten bis das ein anderer das 
gemacht hat (was eventeull nie passieren wird).

Aber auch mit Arduino kann mann auf sehr hohen Niveau arbeiten dafür 
sind aber die tiefergehenden Kenntnisse leider notwendig.

mfg

  µC_Starter

von Gusti (Gast)


Lesenswert?

Genau

Wobei Datenbankenprgrammieren und Objektorientierte Programmierung musst 
du nicht lernen für den uc, sofern du nur bei C bleibst.
Ich habe eine abgeschlossene Lehre als Elektroniker. Im 1. Jahr hatten 
wir in der Schule 4 Lektionen pro Woche uc programmieren. Im 1. Halbjahr 
haben wir nur auf der Konsole am Computer programmiert. So lernst du am 
einfachsten die Grundlagen. Wie z.B. wie verwende ich ein Array oder ein 
Switch case, und, oder, xor operationen etc.
Wann verwende ich ein for, while oder do while schleife.
Ausserdem haben wir so auch gelernt, wie man x for schleifen ineinander 
verschachtelt. Mit Übungen wie einen Tannenbaum an den Konsole ausgeben. 
Dies funktioniert recht einfach mit verschachtelten for Schleifen. Die 
Struktur der Verschachtelung ist sehr komplex und solche Übungen, auch 
wenn sie mühsam sind helfen sehr beim Verständnis. Was dir dann später 
auf dem uc zu gute kommt.
Vorallem auch wenn du 2 oder 3D Arrays verwendest.

von Jonathan K. (burgerohnealles)


Lesenswert?

Gusti schrieb:
> Ich vermute mal, dass du das meiste zusammenkopiert hast

Das stimmt nicht. Ich hab alles selbst geschrieben (bis auf den Teil, wo 
die Zeit ausgelesen wird)!

Gusti schrieb:
> Lies mal in einem Tutorial wie man ein Array verwendet. Das 1. Element
> im Array wird mit 0 angesprochen. Du initialisierts i mit 1. Wie soll
> dann bitte das 1. Element einen Wert bekommen.
> Aber das wird nicht das Problem sein.

Dirket nach dem Array steht die funktion
1
memset(devices, 0x00, 32)
. Dadurch werden doch alle Werte auf 0 gesetzt. Oder verstehe ich das 
falsch? Und dass ich bei 1 anfange hat auch einen Grunde, denn es gibt 
nun mal in einem Netzwerk keinen Rechner mit der IP-Adresse 
192.168.178.0 !

µC_Starter schrieb:
> Gerade Arduino verleitet erstmal dazu sich das Programm (Sketch)
> zusammen zu kopieren - das kann sogar funktionieren  allerdings lehrnt
> mann dabei sehr wenig und mann wird niemals selbst etwas anpassen oder
> entwickeln können und wird auch immer auf teuere fertige Hardware
> (shields) angewiesen bleiben

Das masg auch sein, aber wie gesagt, ich habe alles (bis auf den Teil, 
wo die Zeit ausgelesen wird) selbst geschrieben.


Nur jetzt verstehe ich immer noch nicht, warum das Programm hängen 
bleibt? Ich hab ja die Größe des Array auf 32 erweitert!? Und was ich 
oben vergessen hab dazuzuschreiben, logischer Weise auch die Funktion 
memset. Das hab auch den dritten Paramter von 8 auf 32 geändert! Aber 
warum funktioniert es immer noch nicht!?

von Uwe (Gast)


Lesenswert?

Weil nen Array was 32 groß ist nur von 0 bis 31 geht und nicht von 1 bis 
32.

von Jonathan K. (burgerohnealles)


Lesenswert?

Uwe schrieb:
> Weil nen Array was 32 groß ist nur von 0 bis 31 geht und nicht von 1 bis
> 32.

Ja das ist mir auch klar, aber wo greif ich z.B. auf das 32. Element zu?


Hab aber noch was gelesen (http://stackoverflow.com/a/7202857), und zwar 
man soll ein Array nicht mit memset() initialisieren, sonder mit einer 
Schleife die Werte einzeln setzt, aber warum?

von Markus (Gast)


Lesenswert?

1
while (millis() < t) {
2
...
3
uint8_t *rbuf = (uint8_t*) malloc(rbuf_size);
4
...
5
if (rbuf_size < (2 + SIZE_ETHERNET + SIZE_ARP)) { // min length for arp packet
6
  ...
7
  free(rbuf);
8
}
9
..
10
memcpy(&ethernet, rbuf+2, SIZE_ETHERNET);
11
..
12
free(rbuf);

Zweimal denselben Speicher freigeben (rbuf, einmal bedingt im if{} und 
einmal zwangsweise danach) und auch noch den evtl. schon freigegeben 
Speicher verwenden ist nicht schön.

von Jonathan K. (burgerohnealles)


Lesenswert?

Ja, wenn du genau in den Code guckt, steht da
1
if (rbuf_size < (2 + SIZE_ETHERNET + SIZE_ARP)) { // min length for arp packet
2
  ...
3
  free(rbuf);
4
  continue;
5
}
, was heißt, dass dann die Schleife hier abgebrochen wird und wieder von 
vorne weiter läuft. Oder steh ich grad aufm Schlauch und verstehe das 
ganz falsch !?

von Markus (Gast)


Lesenswert?

hast recht, habs übersehen.

von Jonathan K. (burgerohnealles)


Lesenswert?

Ja trotzdem danke, bin froh über jeden Tipp, der mein Problem lösen 
könnte. Ich versuchs mal, wie schon oben gesagt, das Array mit einer 
Schleife, anstatt mit memset() zu initialisieren, aber was ist daran 
falsch, es mit memset() zu machen?

von amateur (Gast)


Lesenswert?

Lokale Variable werden fast immer auf dem Stack abgelegt.
Die Rücksprungadressen von Unterfunktionen ebenfalls.

Wenn jetzt eine Variable "Amok" läuft, ist es nur eine Frage der Zeit, 
wenn diese eine Rücksprungadresse überschreibt.

von Jonathan K. (burgerohnealles)


Lesenswert?

amateur schrieb:
> Lokale Variable werden fast immer auf dem Stack abgelegt.
> Die Rücksprungadressen von Unterfunktionen ebenfalls.
>
> Wenn jetzt eine Variable "Amok" läuft, ist es nur eine Frage der Zeit,
> wenn diese eine Rücksprungadresse überschreibt.

Ok, dann weiß ich ja jetzt, warum diese komischen Ausgaben kommen, aber 
was meinst du mit "wenn eine Variable 'Amok' läuft"? Meinst du damit 
z.B. das:
1
uint8_t arr[8];
2
arr[10] = 26;
? Oder was ? Und wann passiert das in meinem Code? Nach den 
Verbesserungen, müsste es ja eigtl funktionieren. Ich habe auch noch
1
memset(devices, 0x00, 32);
 durch
1
  for(uint8_t i=0; i<32; i++)
2
    devices[i] = 0x00;
 ersetzt. Das
1
memset arbeitet auf Bytes. Da ein "int" aber i.d.R. aus ein paar Bytes besteht, werden alle Bytes des 'int's auf den Wert (hier 1) gesetzt. 
2
 Die binärdarstellung der 1 in einem 4-bytigen int wäre aber 0x00000001 und nicht 0x01010101.
 würde erklären, warum man memset nicht benutzen sollte, aber in meinem 
Fall geht das, weil ich ja alle Werte auf 0x00 setzen möchte. Was ist 
dann an dem Code noch falsch?

von Jonathan K. (burgerohnealles)


Lesenswert?

Fehler gefunden ^^ des war ein ziemlich mieser Fehler. Mir ist 
aufgefallen, dass es immer in dem Bereich bei " ok ... send data ... ok 
." zu Fehlern kommt. Also hab ich mal diesen Teil wegkommentiert. Also
1
uint8_t *buf = (uint8_t*) malloc(SIZE_ETHERNET + SIZE_ARP);
 und alles, wo auf buf zugegriffen wird. Dann kam beim Kompilieren ein 
Fehler. Und zwar hier:
1
      uint16_t rbuf_size = W5100.getRXReceivedSize(s);
2
      if (rbuf_size <= 0) continue;
3
      uint8_t *rbuf = (uint8_t*) malloc(rbuf_size);
4
      if (rbuf == NULL) {
5
        debug_print(F("error allocating memory\n"));
6
        return;
7
      }
! Da stand nämlich vorher noch "... if (buf == NULL) ...". Wenn ich 
jetzt das ganz starte, kommt dieser Fehler "error allocating memory". Da 
wurde dann anscheinend, wenn rbuf NULL war, auf irgendwas zugeriffen, 
und es hat sich aufgehangen. Was so ein kleiner Buchstabe für Ärger 
machen kann .. Habt ihr Tipps, wie man solche Fehler schneller findet? 
Sichher hätte es auch was gebracht, nach jedem Aufruf von free() den 
Zeiger auf NULL zu setzen. Sonst danke für die Hilfe und wenn ihr Tipps 
habt, her damit ! :D

von avr (Gast)


Lesenswert?

Jonathan K. schrieb:
> Sonst danke für die Hilfe und wenn ihr Tipps
> habt, her damit ! :D

Keine dynamische Speicherverwaltung verwenden. Bringt nichts und macht 
es komplizierter und fehleranfälliger.

von Jonathan K. (burgerohnealles)


Lesenswert?

avr schrieb:
> Jonathan K. schrieb:
>> Sonst danke für die Hilfe und wenn ihr Tipps
>> habt, her damit ! :D
>
> Keine dynamische Speicherverwaltung verwenden. Bringt nichts und macht
> es komplizierter und fehleranfälliger.

(Y) Wer ich mir merken! Ansonsten, war das Problem, dann immer noch da. 
Also hab ich meine umständlichste Methode genommen, nämlich, mehr oder 
weniger alles wegkommentieren. Dann Schritt für Schritt wieder einen 
Teil dazumachen und gucken wann der Fehler kommt. Diesmal hat der Aufruf 
der Funktion [c]W5100.recv_data_processing()[c] probleme, gemacht. Wenn 
das mir jemand erklären kannt, bitte! Gelöst habe ich es, in dem ich mir 
zuerst das Datenblatt und alle Dateien aus dem Orderner 
Arduino/libraries/Ethernet/utilitys nochmal angeguckt habe. Dann war ich 
in der Lage, diese "Problemfunktion" rauszulassen und den Code dieser 
Funktion direkt in den Code aufgeteilt einzufügen, und es GEHT! :D Wenn 
jmd den Code haben möchte, kann er mich fragen.

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.