Fehler im Programm
-
Hallo, ich habe wieder mal ein größeres Problem (so ne art Windows-Syndrom).
ich habe ein Program geschrieben, welches Messdaten von Serieller Schnittstelle in eine DB Schreibt (4 untersch. Sensoren). Zudem wird der Letzte Zeitwert in der DB ermittelt und zu jedem Datensatz mit +32s dazugeschrieben.
Das ganze passiert Blockweise(128B also 32Datensätze a 4B). Das ganze wird solange wiederholt bis ein Stopp-Signal kommt(1Byte=0xff).
So weit funktioniert die Sache eigentlich auch, aber manchmal wird die Zeit nicht korrekt dazuaddiert, d.h. manchmal zählt er 20,30,40 mal hoch und trägt dann plötzlich wieder einen alten wert ein, oder aber mehrere stunden vorraus.
Außerdem erscheint in einem der Felder(nicht immer dasselbe)manchmal ein unmöglicher wert(0,255,...).
Ich komme einfach nicht mehr weiter, ich habe schon allerhand ausprobiert,erfolglo und habe keine Idee woran es liegen könnte,weil manchmal tut es ja auch!
hier die Schleife:rec_buf_c[0] = 0x00; abbrechen = false; while(rec_buf_c[0] != 0xff) //Datensatz Downloaden und Speichern { Application->ProcessMessages(); //Ermöglicht Ausführen von anderen Prozessen if (abbrechen == true) //Bricht die Schleife ab, wenn { //abbrechen mit Button Verb. Trennen break; //auf true gesetzt wird } //Signal für Datenauslesen senden send_buf_c[0] = 0x20; //Daten Senden: Write_Comport(com_status_h, 2, &send_buf_c); //Daten Empfangen: // Wird bei mir direkt nach Write_Comport ausgeführt succes = Read_Comport (com_status_h, // Fest - True falls Port geöffnet &rec_bytes_dw, // Fest - Anzahl der Empfangenen Bytes 128, // Variabel - Empfange maximal 128 Bytes (für char) &rec_buf_c, // Variabel - Empfangspuffer (min. 19 Bytes groß) 3000); // Variabel - Timeout nach 3 sec. if(succes == true) { succes = false; if (rec_buf_c[0]== 0xff) { break; } else { //Aktivieren des Letzten Datensatzes Main->ADOQuery1->Close(); Main->ADOQuery1->SQL->Clear(); Main->ADOQuery1->SQL->Add("SELECT Zeitwert FROM Tabelle1 WHERE AnlagenNr =" + tmp); Main->ADOQuery1->Open(); Main->ADOQuery1->Last(); //Herauslesen des letzten Zeitwerts let_z = Main->ADOQuery1->FieldByName("Zeitwert")->AsDateTime; if(let_z == (EncodeTime(0, 0, 0, 0))) //Vieleicht ist hier was falsch? { let_z = dt-EncodeTime(0, 17,32, 0); } //Schreiben der Empfangenen Daten in die DB Main->ADOQuery1->Close(); Main->ADOQuery1->SQL->Clear(); Main->ADOQuery1->SQL->Add("SELECT * FROM Tabelle1"); Main->ADOQuery1->Open(); for(int z=0;z<32;z++) //für jeden Datensatz ein Durchlauf { //Main->ADOQuery1->Insert(); Main->ADOQuery1->Append(); Main->ADOQuery1->FieldByName("AnlagenNr")->AsString = tmp; if (rec_buf_c[ind] ==NULL) { Main->ADOQuery1->FieldByName("Windgeschwindigkeit")->AsInteger = 0; ind++; } else { gewandelte_mc_werte[ind] = rec_buf_c[ind]; Main->ADOQuery1->FieldByName("Windgeschwindigkeit")->AsInteger = gewandelte_mc_werte[ind]; ind++; } if (rec_buf_c[ind] ==NULL) { Main->ADOQuery1->FieldByName("Windrichtung")->AsInteger = 0; ind++; } else { gewandelte_mc_werte[ind] = rec_buf_c[ind]; Main->ADOQuery1->FieldByName("Windrichtung")->AsInteger = gewandelte_mc_werte[ind]; ind++; } if (rec_buf_c[ind] ==NULL) { Main->ADOQuery1->FieldByName("Strom")->AsInteger = 0; ind++; } else { gewandelte_mc_werte[ind] = rec_buf_c[ind]; Main->ADOQuery1->FieldByName("Strom")->AsInteger = gewandelte_mc_werte[ind]; ind++; } if (rec_buf_c[ind] ==NULL) { Main->ADOQuery1->FieldByName("Spannung")->AsInteger = 0; ind++; } else { gewandelte_mc_werte[ind] = rec_buf_c[ind]; Main->ADOQuery1->FieldByName("Spannung")->AsInteger = gewandelte_mc_werte[ind]; ind++; } Main->ADOQuery1->FieldByName("Leistung")->AsInteger = (Main->ADOQuery1->FieldByName("Strom")->AsInteger) * (Main->ADOQuery1->FieldByName("Spannung")->AsInteger);//StrToInt fällt weg let_z = let_z + EncodeTime(0, 0, 32, 0); Main->ADOQuery1->FieldByName("Zeitwert")->AsDateTime = let_z; //Hier wird Zeit eingetragen Main->ADOQuery1->Post(); //delay(10); } } }Ich weiß es ist etwas unübersichtlich, aber bitte helft mir! Ich muß dieses Problem dringend lösen!
-
OK, das mit der Zeit habe ich jetzt scheints hinbekommen.
Es war anscheinend ein Timing problem. Ich habe jetzt delay erst mal auf 60ms hochgesetzt und jetzt scheint es zu funktionieren.Aber das mit den Werten, das manchmal 0 auftaucht ist mir immer noch unerklärlich, mein Microcontroller sendet auf jeden fall immer eine 1 (Probrweise).
-
ist sicherlich fraglich, ob die db in der lage ist die daten innerhalb von 32ms zu schreiben. besser wäre das sicherlich ein temporäre puffer der die daten zwischenspeichert oder ein separater thread der das speichern übernimmt.
was liefert den Read_Comport nach dem timeout oder tritt der gar nicht erst auf?
wieso fragst du die pufferwerte mit NULL ab?
-
Ja das abfragen auf 0 ist eigentlich unnötig, ich hatte nur vorher eine etwas andere Variante, das ich die Pufferwerte als String und nicht als Int in die DB geschrieben habe. Da habe ich das gebraucht.
Was den Timeout betrifft: In dieser Funktion taucht er nicht auf,aber die Funktion Read_Comport hat eine untermethode (Read_File)die diese Zeit benötigt(wenn über Timeout Zeit keine Daten kommen wird abgebrochen).
Was die Zeit betrifft die DB zum Schreiben braucht: mit relativ wenig Daten langen mir im delay 31ms(deleay wird nicht mit sleep,sondern über timer gebastelt)->vieleicht Zufall?
, ich weiß aber nicht ob es mit zunehmender Datenmenge länger dauert.Was mich aber am meisten wundert, warum Taucht periodisch nach 32Sätzen im Feld Strom eine 0 und nach 33Sätzen in Windrichtung eine 0 auf? So was ist theoretisch mti dem Code nicht möglich!?

-
bist du sicher, dass du jeweils den richtigen index im array verwendest?
- wozu dient z?
- wo und wie wird ind initialisiert?
- wie gross ist der puffer rec_buf_c?
-
Das stimmt soweit schon, rec_buf_c ist 128Byte groß = daten vom MC
z ist eigentlich nur eine Zwischenvariable um bis auf 32 zu zählen. Sie wird sonst niergends verwendet.
ind initialisiere ich wenn ich den Button wo diese Schleife drin ist drücke mit 0.
Am ende der while Schleife wird ind ebenfalls wieder auf 0 gesetzt.
(Am Ende des geposteten Codes fehlt noch ein else,wenn übertragung Fehlschlägt und anschließend dann ind = 0)
-
der uebersichtlichkeit halber und einfach auch weil dein code ziemlich undurchsichtig ist, würde ich dir empfehlen diesen mal soweit um zu stellen, dass man besser sieht was passiert. hier mal ein vorschlag:
das ist nur der teil, der die daten in die db schreibt. ist wesentlich kompakter und macht genau das gleiche (naja, sollte zumindest ;))
// ... char v1, v2, v3, v4; // fuer jeden Datensatz ein Durchlauf for (int z = 0; z < 128; z += 4) { let_z = let_z + EncodeTime(0, 0, 32, 0); v1 = rec_buf_c[z]; v2 = rec_buf_c[z + 1]; v3 = rec_buf_c[z + 2]; v4 = rec_buf_c[z + 3]; // wozu diese werte merken? gewandelte_mc_werte[z] = v1; gewandelte_mc_werte[z + 1] = v2; gewandelte_mc_werte[z + 2] = v3; gewandelte_mc_werte[z + 3] = v4; Main->ADOQuery1->Append(); Main->ADOQuery1->FieldByName("AnlagenNr")->AsString = tmp; Main->ADOQuery1->FieldByName("Windgeschwindigkeit")->AsInteger = v1; Main->ADOQuery1->FieldByName("Windrichtung")->AsInteger = v2; Main->ADOQuery1->FieldByName("Strom")->AsInteger = v3; Main->ADOQuery1->FieldByName("Spannung")->AsInteger = v4; Main->ADOQuery1->FieldByName("Leistung")->AsInteger = v3 * v4; Main->ADOQuery1->FieldByName("Zeitwert")->AsDateTime = let_z; Main->ADOQuery1->Post(); } // ...
-
danke für deinen Code, er ist in der Tat etwas Kompakter und tut genauso!

allerdings schreibt er auch genauso eine 0 abwechselnd in die Felder.
Aber da dieser Code eigentlich so richtig ist(stimmt doch,oder?) könnte es ja evtl auch sein das es an meinem MC liegt.mfg