Forum: Mikrocontroller und Digitale Elektronik Serielle Verbindung bricht ab


von Paul (Gast)


Lesenswert?

Hallo,

mein Arduino empfängt alle 500ms ein Datenpaket mit einer Zahl darin, 
dieses wird in ein char Array gespeichert und zu einem MD5 hash gehasht. 
Danach wird an den Hash noch 456 (ID) dran gehängt.
Funktioniert alles problemlos, jedenfalls 1-2 Minuten. Danach stoppt die 
Serielle Kommunikation des Arduinos einfach. Die LED-leuchtet nicht 
mehr, durch die Arduino IDE kommt nichts mehr an und auch nicht in 
Putty.  Komisch ist wenn ich das serielle Fenster in der Arduino IDE 
beende und danach wieder öffne klappt die Ausgabe wieder für 1-2 
Minuten. Bin echt ratlos..

Baudrate wurde mit 9600 und 115200 versucht.



1
#include <MD5.h>
2
#include <SPI.h>
3
#include <Ethernet.h>
4
#include <EthernetUdp.h>
5
6
7
8
9
int udppacket=0;
10
int arraygroesse= 0;
11
int clientarraygroesse=0;
12
byte sendestatus=0;
13
byte hashzaehler = 0;
14
unsigned long clientzeit=0;
15
16
17
18
char recieveddata[100];
19
char hasharray[100]; //Ein MD5 Hash hat 32 Zeichen, hier von 0-31, die Zeichen 32-34 dient zur Zuordnung des Hashes, die restlichen fuer die Clientzeit
20
char clientzeitbuffer[100];
21
22
23
//Lokale Adresse:
24
25
byte clientmac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEB };
26
IPAddress clientip(192, 168, 3, 2);
27
IPAddress clientsubnet(255, 255, 255, 0);
28
IPAddress gateway(192, 168, 3, 1);
29
int clientport = 8002; //Lokaler Port
30
31
//Serveradresse:
32
33
IPAddress serverip(192, 168, 3, 1); //Address to send UDP packe to
34
IPAddress servergateway(292, 168, 3, 1);
35
int serverport = 8001;
36
37
38
char packetbuffer[UDP_TX_PACKET_MAX_SIZE]; //Bufferspeicher um Empfangene Pakete bis zur Bearbeitung zu speichern.
39
EthernetUDP Udp; //Beginnt eine UDP-Instanz
40
41
42
//########################################################################################################################################################################
43
44
45
void setup() {
46
47
  Ethernet.begin(clientmac, clientip, clientsubnet, gateway);
48
  Udp.begin(clientport);
49
  Serial.begin(115200);
50
51
}
52
53
//########################################################################################################################################################################
54
55
56
57
void loop() {
58
59
60
  char udppacket = Udp.parsePacket();
61
  if (udppacket) {
62
    Serial.println(udppacket);
63
64
65
    Udp.read(packetbuffer, udppacket);
66
    Serial.println(packetbuffer);
67
68
69
    //Speichert die Empfangenen Daten in ein char Array
70
    for (int i = 0; i < udppacket; i++) {
71
      recieveddata[i] = packetbuffer[i];
72
      Serial.print("Empfangene Zeit:");
73
      Serial.println(recieveddata[i]);
74
75
    }
76
77
    //Ermittelt die tatsächliche größe des Arrays
78
    arraygroesse = (unsigned)strlen(recieveddata);
79
    Serial.print("Arraygroesse ");
80
    Serial.print(arraygroesse);
81
    Serial.print("\n");
82
83
  }
84
85
86
   //########################################################################################################################################################################
87
88
89
  //if (arraygroesse!=0 && arraygroesse<31 && sendestatus==0) { //Die erste Zeit wird empfangen und gehasht.
90
if(arraygroesse >0){
91
92
    
93
    Serial.println("Der Mikrocontroller ist am HASH-Erstellen");
94
    unsigned char* hash = MD5::make_hash(recieveddata);
95
    char *md5str = MD5::make_digest(hash, 16);
96
    free(hash);
97
    //Serial.println(md5str);
98
99
100
    //Gibt den Hash in der seriellen Konsole & speichert ihn in ein neues Array.
101
    //Serial.println (hasharray[32]);
102
    for (int i = 0; i < 32; i++) {
103
      hasharray[i] = md5str[i];
104
     // Serial.print(hasharray[i]);
105
    }
106
107
    //Hängt an den Hash eine ID-an um dem Server Polls von Befehlen zu unterscheiden.
108
    hasharray[32] = '4';
109
    hasharray[33] = '5';
110
    hasharray[34] = '6';
111
112
113
114
    Serial.println("Hash mit 1"); //Ausgabe des Arrays in die Serielle Konsole
115
    for (int i = 0; i < 35; i++) {
116
      Serial.print(hasharray[i]);
117
    }
118
}
119
 
120
  udppacket=0;
121
  arraygroesse=0;
122
  }


Jemand eine Idee?

von g457 (Gast)


Lesenswert?

> char *md5str = [..]

leakt Speicher

von Paul (Gast)


Lesenswert?

Danke für diese Antwort aber damit kann ich eigentlich gar nichts 
anfangen..könntest du das genauer erklären?

von думлихер троль (Gast)


Lesenswert?

Ich hab das Gefuehl, die serielle Schnittstelle ist blockierend. Dann 
wird sie mit viel zuviel Zeug zugemuellt.

Zu Beginn wuerd ich nur das UDP Packet byte fuer byte auf die Serielle 
kopieren, ohne zusaetzliches Zeug.

von g457 (Gast)


Lesenswert?

> könntest du das genauer erklären?

Der Funktionsaufruf in besagter Zeile allokiert Ressourcen (hier: 
Speicher), die Du nie wieder freigibst (hier: das zugehörige 
free(md5str) fehlt) -> nach ein paar Runden ist die Ressource 
aufgebraucht (hier: kein freier Speicher mehr verfügbar) und es 
passieren lustige Sachen.

von Tom (Gast)


Lesenswert?

Paul schrieb:
> Danke für diese Antwort aber damit kann ich eigentlich gar nichts
> anfangen.

Zu jedem malloc gehört ein passendes free (siehe Grundlagen dynamischer 
Speicherverwaltung im Buch Deiner Wahl). Also in den Quelltext von 
MD5::make_hash und MD5::make_digest sehen, ob dort ein malloc passiert.

Der Autor der MD5-Lib hätte auch die C++-Möglichkeiten nutzen können 
(RAII), statt eine Klasse als überflüssigen Behälter für simple C-artige 
Funktionen zu verwenden.

von Paul (Gast)


Lesenswert?

Ah, vielen Dank!
Habe es nun geändert.
1
   Serial.println("Der Mikrocontroller ist am HASH-Erstellen");
2
    unsigned char* hash = MD5::make_hash(recieveddata);
3
    char *md5str = MD5::make_digest(hash, 16);
4
    free(md5str);

Jedoch besteht das selbe Problem weiterhin.
Weitere Ideen?

von Paul (Gast)


Lesenswert?

Ah, natürlich gehört

1
free(hash);

auch noch ergänzt :)
Jetzt klappt es..ich danke dir/euch ;)

von Stefan F. (Gast)


Lesenswert?

Serielle Schnittstellen können physikalisch nicht blockieren. Und 
Verbindungsabbrüche hat amn nur, wenn man das Kabel unterbricht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefan Us schrieb:
> Serielle Schnittstellen können physikalisch nicht blockieren.

Wenn sie Hardwarehandshake machen, schon.

von Paul (Gast)


Lesenswert?

Hallo,

nun habe ich ein weiteres Problem, der Hash wird erstellt jedoch stimmt 
dieser nur teilweise überein.. wäre toll wenn mir wieder jemand einen 
Tipp geben könnte. Das Array welches an die Hashfunktion gegeben wird 
enthält den  richtigen Inhalt, auch der generierte Hash stimmt, jedoch 
fehlen unterscheiden sich die Hashes:

z.B.

Klartext: 7377913

Arduino-Hash

1a6363927d7bfc6ff1cbd7048760d57378914

Normal generierter Hash

691a6363927d7bfc6ff1cbd7048760d5


Jemand eine Ahnung?
1
#include <MD5.h>
2
#include <SPI.h>
3
#include <Ethernet.h>
4
#include <EthernetUdp.h>
5
6
7
int udppacket = 0;
8
int arraygroesse = 0;
9
int clientarraygroesse = 0;
10
byte sendestatus = 0;
11
byte hashzaehler = 0;
12
unsigned long clientzeit = 0;
13
14
15
16
char recieveddata[100];
17
char hasharray[100]; //Ein MD5 Hash hat 32 Zeichen, hier von 0-31, die Zeichen 32-34 dient zur Zuordnung des Hashes, die restlichen fuer die Clientzeit
18
char clientzeitbuffer[100];
19
20
21
//Lokale Adresse:
22
23
byte clientmac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEB };
24
IPAddress clientip(192, 168, 3, 2);
25
IPAddress clientsubnet(255, 255, 255, 0);
26
IPAddress gateway(192, 168, 3, 1);
27
int clientport = 8002; //Lokaler Port
28
29
//Serveradresse:
30
31
IPAddress serverip(192, 168, 3, 1); //Address to send UDP packe to
32
IPAddress servergateway(292, 168, 3, 1);
33
int serverport = 8001;
34
35
36
char packetbuffer[UDP_TX_PACKET_MAX_SIZE]; //Bufferspeicher um Empfangene Pakete bis zur Bearbeitung zu speichern.
37
EthernetUDP Udp; //Beginnt eine UDP-Instanz
38
39
40
//########################################################################################################################################################################
41
42
43
void setup() {
44
45
  Ethernet.begin(clientmac, clientip, clientsubnet, gateway);
46
  Udp.begin(clientport);
47
  Serial.begin(9600);
48
49
}
50
51
//########################################################################################################################################################################
52
53
54
55
void loop() {
56
57
58
  udppacket = Udp.parsePacket();
59
  if (udppacket) {
60
61
    Udp.read(packetbuffer, udppacket);
62
    Serial.println(packetbuffer);
63
64
65
    //Speichert die Empfangenen Daten in ein char Array
66
    for (int i = 0; i < udppacket; i++) {
67
      recieveddata[i] = packetbuffer[i];
68
      Serial.println("Empfangene Zeit:");
69
      Serial.println(recieveddata[i]);
70
      Serial.println(packetbuffer[i]);
71
72
73
    }
74
75
    //Ermittelt die tatsächliche größe des Arrays
76
    arraygroesse = (unsigned)strlen(recieveddata);
77
    Serial.print("Arraygroesse ");
78
    Serial.print(arraygroesse);
79
    Serial.print("\n");
80
81
  }
82
83
84
  //########################################################################################################################################################################
85
86
87
  //if (arraygroesse!=0 && arraygroesse<31 && sendestatus==0) { //Die erste Zeit wird empfangen und gehasht.
88
  if (arraygroesse > 0) {
89
90
91
    Serial.println("HASH-Erstellen");
92
    unsigned char* hash = MD5::make_hash(recieveddata);
93
    char *md5str = MD5::make_digest(hash, 16);
94
    free(hash);
95
    free(md5str);
96
97
98
99
    for (int i = 0; i < 32; i++) {
100
      Serial.print(md5str[i]);
101
    }
102
    arraygroesse = 0;    
103
    memset(recieveddata, 0, sizeof(recieveddata));
104
105
106
  }
107
}

von Peter II (Gast)


Lesenswert?

Paul schrieb:
> free(md5str);
>
>     for (int i = 0; i < 32; i++) {
>       Serial.print(md5str[i]);

du darfst nicht den Speicher freigeben und dann später wieder darauf 
zugreifen.

Ich würde das Programm so umschreiben, das man überhaupt keine 
dynamischen Speicher braucht, lege doch das hash objekt global an. Das 
kann auch mehrfacher verwendet werden.

Keine Ahnung wie Arduino reagiert, wenn kein Speicher mehr frei ist bzw. 
wenn er zu stark fragmentiert ist.

von Paul (Gast)


Lesenswert?

Vielen Dank, du hast mir sehr geholfen!


Ja ich habe jetzt md5str vor der Speicherfreigabe in ein neues char 
Array geschrieben und jetzt klappt es... :)

von Peter II (Gast)


Lesenswert?

Paul schrieb:
> Ja ich habe jetzt md5str vor der Speicherfreigabe in ein neues char
> Array geschrieben und jetzt klappt es... :)

und warum? hast du zu viel ram oder cpu zeit das du sinnlos zeug 
rumkopieren musst?

Kannst du es nicht gleich in eine Variabel schreiben lassen?

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.