Autor Beitrag
mr_r0ssi
Hält's aus hier
Beiträge: 10

Win 98, Win 2000
D6 Prof
BeitragVerfasst: Mo 13.06.05 13:56 
Hallo,

folgendes Problem: Ich moechte von einer Messstelle daten einlesen nach folgenden Protokoll:
- Sende Konfig fuer MessSensor
- Warte auf OK
- Sende ENQ fuer Messdatenanforederung
- Warte auf Messdaten mit Sendebestaetigung
- Sende Konfig fuer naechsten MessSensor ..

Ich anwende die Comport Komponente von Async. Wenn ich die einzelen Schritte manuell ueber mehrere Buttons ausfuehre, bekomme ich die richtigen Eingaben von Triggeravail Event. Wenn ich aber die Protokollschritte ueber eine Schleife nacheinander ausfuehre, wird der Com Port nur sehr unregelmaessig eingelesen bzw. mir ist es nicht moeglich anhand der eingelesenen Daten ein Bearbeitungschema zu programmieren, weil die Daten sich von Mal zu Mal unterscheiden.
Ich habe keine grosse Erfahrung warum das TriggerAvail Ereignis richtig funktioniert, wenn ich manuell die Kommunikation steure, aber nicht wenn ich es automatisiert ueber eine Programmschleife laufen lasse.
Ein Sleep zw. den einzelenen Sendeaufrufen hat nicht wirklich geholfen. Ich waere ueber ein paar Tips wirklich dankbar.

Gruss
Stephan
Holgerwa
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 325

WIN XP Pro, Vista Business
Delphi 7 Pro, BDS 2006 Pro
BeitragVerfasst: Mo 13.06.05 14:05 
Hallo,

wie wartest Du denn nach dem Senden eines Kommandos auf die Antwort? Es sollte ja eine Art Handshake entstehen, in dem Du jeweils etwas sendest, und auf die Bestätigung (oder Daten) wartest.
Poste doch mal diesen Teil Deines Source-Codes.

Holger
mr_r0ssi Threadstarter
Hält's aus hier
Beiträge: 10

Win 98, Win 2000
D6 Prof
BeitragVerfasst: Mo 13.06.05 16:20 
Vielen Dank fuer das Interesse. Der Code fuer TriggerAvail, das immer ausgeloest wird falls Daten am Comport anliegen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
  I : Word;
  C : Char;
  S : String;
begin
  for I := 1 to Count do begin
    C := ApdComPort1.GetChar;
    case C of
      #0..#31 :S := S + IntToStr(ord(C));
      else  S := S + C;
    end;
  end;
  memo1.text := memo1.text + S + #13#10;
end;


Ein typ. Code in einem Button sieht so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
ApdComPort1.OutPut := 'PA1'#13#10; //Konfiguriere Messstelle
if ApdComPort1.WaitForString(#6#13#10,90,true,true) then //Warte auf OK
   ApdComPort1.OutPut := #5#13#10; //Schicke ENQ fuer Messdaten


Im Memo Fenster wird mir auch der Messwert + #13#10 ausgegeben wenn ich auf den Button klicke. Falls ich aber in einer anderen procedure die Buttonklicks nacheinander aufrúfe,
erhalte ich diffuse Ausgaben in Memofeld:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
begin
        Button4Click(Sender);
        Sleep(100);
        Button2Click(Sender);
        Sleep(100)
        Button5Click(Sender);
end;


Ich hoffe, dass der Code ausreicht, um mein Problem zu analysieren.
/Stephan

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.
Holgerwa
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 325

WIN XP Pro, Vista Business
Delphi 7 Pro, BDS 2006 Pro
BeitragVerfasst: Di 14.06.05 06:16 
Hallo,

Du wartest mit Deiner Anwendung nach dem Senden des ersten Strings, bis die Rückmeldung empfangen wurde. Während dieser Zeit steht die Anwendung, und reagiert auf nichts.
Da es sich um eine asynchrone Datenübertragung handelt, ist es besser, das ganze über Events zu steuern, also unabhängig vom Programmverlauf:
1) Button -> Sende ersten String
2) Event wird ausgelöst, wenn Rückmeldung empfangen wurde
3) Im Event wird der nächste String gesendet

Es gibt bei den AsyncPro Komponenten ein ApdDataPacket, welches nichts anderes tut, als auf den Empfang einer vorzugebenden Zeichenfolge zu warten, und dann einen Event auszulösen.

Versuch es mal so:
1) Senden des ersten Strings
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.Button1Click(Sender: TObject);
begin
  ApdComPort1.OutPut := 'PA1'#13#10; // Konfiguriere Messstelle
end;

2) Setz ein ApdDataPacket auf die Form, setze ComPort auf ApdComPort1, dann Rechts-Klick auf ApdDataPacket und "Edit Properties". In "Packet start condition" aktivierst Du "When String is received", und kopierst die Rückmeldung #6#13#10 in das Editfeld dahinter.
3) In den Event OnStringPacket kommt das:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.ApdDataPacket1StringPacket(Sender: TObject; Data: String);
begin
  ApdComPort1.OutPut := #5#13#10; //Schicke ENQ fuer Messdaten
end;

Es wird also durch den Buttonklick nur der erste String gesendet. Danach läuft das Programm normal weiter. Das hat u.A. den Vorteil, daß Du auch mehrere ComPorts bedienen kannst, wenn Du gleichzeitig mehrere Geräte auswerten mußt. Wenn die Rückmeldung empfangen wird, wird automatisch der zweite String gesendet. Ich habe das schon mehrfach zur Steuerung von externen Geräten verwendet, es funktioniert sehr zuverlässig.

Holger
mr_r0ssi Threadstarter
Hält's aus hier
Beiträge: 10

Win 98, Win 2000
D6 Prof
BeitragVerfasst: Di 14.06.05 11:05 
Vielen Dank Holger, es sieht schon etwas besser aus, aber folgendes Problem bleibt noch:
Wenn ich die 3 Buttons nacheinander im Program betätige, erhalte ich den Ausdruck, den ich auch erwarte:

Zitat:
61310 //Bestaetigung der Messstellenkonfig
0,6.1E+2 //Status, Messwert
1310 //Bestaetigung fuer Messwertuebermittlung
61310
4,9.9E+3
1310
61310
4,9.9E-3
1310


Wenn ich aber die Buttons mit

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
Button4Click(Sender);
Sleep(100);
Button2Click(Sender);
Sleep(100);
Button5Click(Sender);


ansteuere, erhalte ich soetwas wie
Zitat:

61310
61310
6134,9.9E
-31310


Ich weiss nicht wie ich meinem Programm beibringen kann, dass dergleiche Ausdruck im Memo bei beiden Vorgehensweisen erscheint. Gibt es eine entsprechende Konfig-moeglichkeit ueber die angesprochene Async Komponente?

Herzlichst
Stephan

Moderiert von user profile iconraziel: Delphi- und Quote-Tags hinzugefügt.
Holgerwa
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 325

WIN XP Pro, Vista Business
Delphi 7 Pro, BDS 2006 Pro
BeitragVerfasst: Di 14.06.05 11:23 
Hallo,

Du hattest oben nur den OnClick eines Buttons gepostet. Was machen denn die anderen Buttons?
Poste mal alle drei OnClicks.

Holger
mr_r0ssi Threadstarter
Hält's aus hier
Beiträge: 10

Win 98, Win 2000
D6 Prof
BeitragVerfasst: Di 14.06.05 11:53 
Ok, ich habe das ApdDataPacket in meine Appl. eingebaut und so konfiguriert wie vorgeschlagen. Der Buttoncode dannach sieht so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button2Click(Sender: TObject);
begin
        ApdComPort1.OutPut := 'PA2'#13#10;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
        ApdComPort1.OutPut := 'PA1'#13#10;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
        ApdComPort1.OutPut := 'PB1'#13#10;
end;


PA2, PA1 und PB1 sind die auszulesenden Messstellen.
Wenn der String gesendet wird, antwortet die Messstelle mit #6#13#10 danach schickt Stringpacket #5#13#10

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.ApdDataPacket1StringPacket(Sender: TObject; Data: String);
begin
        ApdComPort1.OutPut := #5#13#10;
end;


Es wird der Messwert uebertragen und danach die Bestaetigung mit #13#10

/S
Holgerwa
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 325

WIN XP Pro, Vista Business
Delphi 7 Pro, BDS 2006 Pro
BeitragVerfasst: Di 14.06.05 12:33 
Hallo,

ich denke das Problem sind die Sleep()s, die den Programmablauf komplett anhalten.
Während er Sleept, werden auch Deine TriggerAvail-Events nicht aufgerufen, und die empfangenen Daten nicht verarbeitet.
Du müßtest also dafür sorgen, daß er beim Warten weiterläuft, z.B. mit einem Timer, dessen Intervall Du dann auf die 100ms setzt und den Du zuerst Enabled:=false setzt, damit er nicht von selbst losläuft.
Vielleicht so (ungetestet):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var MStelle: byte; // Nummer der Meßstelle, global

procedure TForm1.Button1Click(Sender: TObject);
begin
  MStelle := 1;
  Timer1.Enabled := true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  case MStelle of
    1: ApdComPort1.OutPut := 'PA2'#13#10; // MStelle 1
    2: ApdComPort1.OutPut := 'PA1'#13#10; // MStelle 2
    3: ApdComPort1.OutPut := 'PB1'#13#10; // MStelle 3
  end;
  inc (MStelle);
  if MStelle > 3 then
    Timer1.Enabled := false;
end;

Dann sollte noch sichergestellt sein, daß die Meßstellen auch wirklich innerhalb der 100ms komplett mit Meßwert geantwortet haben, sodaß sich die Übertragungen nicht überschneiden, aber das hast Du sicher schon geklärt.

Holger
mr_r0ssi Threadstarter
Hält's aus hier
Beiträge: 10

Win 98, Win 2000
D6 Prof
BeitragVerfasst: Di 14.06.05 13:09 
Vielen Dank fuer die Hilfe. Jetzt funktioniert alles so wie ich es mir vorstelle.
Stephan