Autor Beitrag
Finn
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 17.02.05 16:51 
Hallo Delphi-Freunde,

ich plane zwei Schrittmotoren (für einen Satellitenrotor) mit Delphi über eine Steuerungsplatine (RN Mottor ST von robotikhardware.de) anzusteuern. Die Platine soll die Befele über RS 232 (COM1) bekommen. In der Doku der Platine ist eine Übersicht über die RS 232 Befehle die z.B. so aussehen:

print "#rmi" & chr(0) & chr(200) // Damit wird der Motorstrom eingestellt

Aber wie kann ich sowas mit Delphi machen, denn Delphi ist die einzige Sprache mit der ich mich ein kleines bisschen auskenne.

Wäre euch für jede Hilfe dankbar

MfG
Finn
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 16:56 
Kannst es ja mal über den Devicenamen "com1" probieren. Datei öffnen und Befehl reinschreiben.

Edit: :welcome:


Zuletzt bearbeitet von delfiphan am Do 17.02.05 17:07, insgesamt 1-mal bearbeitet
Finn Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 17.02.05 17:06 
Hi Delphiphan,

kannst du mir sagen wie das so ungefähr als Quelltext aussehen würde?

MfG
Finn
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 17:28 
Das Device öffnest du mit
CreateFile('COM1', GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

Du musst aber zuerst sicherstellen, dass die Einstellungen stimmen, also dass beispielsweise die richtige Baudrate (Übertragungsrate) eingestellt ist; was für eine Parität benutzt wird. Sonst wird die Kommunikation wohl nicht klappen. Um das Gerät richtig einzustellen musst du die Befehle SetCommState u.a. benützen. Ich verweise auf msdn:
msdn.microsoft.com/l...tions.asp?frame=true

Wenn dir das zu kompliziert ist, hol dir eine Komponente.
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Do 17.02.05 17:37 
Aaah, schönes Thema...

Na ja, die Informationen die Dir bis jetzt gegeben wurden sind ein bisschen dürftig.

Schau mal hier nach:

Serielle Schnittstelle ansprechen und pollen

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 17:58 
Genau, hol dir ne Komponente oder lass dich vom Experten SchelmVomElm beraten ;)
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Do 17.02.05 18:15 
Haha... :?

Beratung macht 1000,- € die Stunde :twisted:

Was wollt ihr immer mit den Komponenten. Die Serielle lässt sich doch so leicht über die API ansprechen. Er will ja auch nur senden.

CreateFile
SetCommState
WriteFile
CloseHandle

... Fertig!

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 18:27 
Finn hat folgendes geschrieben:
denn Delphi ist die einzige Sprache mit der ich mich ein kleines bisschen auskenne.

SchelmVomElm hat folgendes geschrieben:
Die Serielle lässt sich doch so leicht über die API ansprechen.

Nun, wenn man nicht weiss was überhaupt API ist, wird's schwer. Ne Komponente zu installieren ist einfach!
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Do 17.02.05 18:36 
Seit wann ist die API 'ne Programmiersprache?

Ob er KompoXY.SendString aufruft oder WriteFile...
Im überigen sind die Funktionen ja üppig beschrieben - nicht nur hier.
UND im Gegensatz zu den Komponenten unterliegen sie keinerlei Lizenzbedingungen.

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 18:48 
Zitat:
Seit wann ist die API 'ne Programmiersprache?

:?: (Hat das jemand behauptet?)

Und ich möchte hier jetzt keine Diskussion starten wieso man Komponenten schreibt. Ich habe es bloss vorgeschlagen.

Grüsse
Finn Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 17.02.05 19:34 
Titel: Hilfe !!
Hallo Leute,

vielen Dank für eure vielen Antworten. Ich habe allerdings große Schwierigkeiten mich in die Sache einzuarbeiten, denn das ist mein erstes Projekt, dass in diese Richtung geht.
Ich gehe an meiner Schule in eine Satelliten AG und plane mit einem selbstgebauten und selbstansteuerbaren Porabolschüsselrotor Bilder von Wettersatelliten zu empfangen.

So wie ich das verstanden hab geht das mit dem Ansteurn ungefähr so:

Ich klicke auf einen Button und das Programm schickt eien Befehl an Windows API (Was ist das?) der auf die an dem COM angeschlossene Platine eine Anweisung schreibt, die von der Platine ausgelesen wird und den Motor ensprechend steuert.

Wäre euch super dankbar wenn ihr mir kurz erklären könntet wie das vom Ablauf vom Buttonklick in eienem Delphi-Programm bis zur Motorsteuerung funktioniert (Was macht mein Computer?).

Grüße
Finn
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 20:29 
Hallo Finn

Okay, kopier dir alle Funktionen und Variablendeklarationen von SchelmVomElm (von seinem Post) und kopierst dir die ins Programm rein. Und zwar nach dem implementation (und nach dem uses).

Danach platzierst du einen Knopf auf das Form und doppelklickst drauf. Delphi generiert dir dann automatisch eine Prozedur, die aufgerufen wird, wenn jemand auf den Knopf drückt. Das sollte klar sein.
In dieser Prozedur nun schreibst du
OpenCOM(1);
Damit "öffnest" du quasi die Leitung. Setze dann die Baudrate mit der Funktion SetBaudRate. Wie hoch die sein muss, müsste irgendwo in der Anleitung der Platine dokumentiert sein.
Um nun Befehle zu versenden benützst du den Befehl
SendString(PChar('Ich bin ein Befehl'));
Am Ende der Prozedur solltest du dann
CloseCOM;
ausführen, um die Leitung wieder zu "schliessen".

Was macht der Computer? In deinem Computer ist ein Chip drin, welcher es dir erlaubt Daten seriell (seriell heisst, es wird ein Bit nach dem anderen hintereinander über die Leitung übertragen) zu schicken. Im minimalen Fall reichen somit 2 Drähte aus, um Daten per COM Schnittstelle zu schicken. Da die Daten aber asynchron gesendet werden, muss man sich zuerst auf eine Datenrate einigen! Je nach Qualität der Verbindung wählt man dann eine hohe oder eher tiefe Datenrate.

Das Senden der Daten übernimmt eigentlich die Hardware. Die Hardware kann man aber in einer geschützten Umgebung wie Windows nicht direkt ansteuern, sondern man muss über das Betriebsystem gehen. Windows stellt bestimmte Befehle zur Verfügung, die man aufrufen kann, um indirekt die Hardware anzusteuern. Somit ist die Ansteuerung von verschiedenster Hardware mit den gleichen einfachen Befehlen möglich und man benötigt keinerlei Hardwarekenntnisse. Ein anderer Vorteil dieser indirekten Steuerung ist, dass man so auch Geräte emulieren kann.

API heisst so viel wie "Application Programming Interface". Es ist eine Ansammlung verschiedenster Funktionen die es dir erlauben, eben z.B. des COM1 anzusteuern. Die meisten Funktionen wie Datei öffnen, schliessen, etc. sind API-Calls oder Enden schlussendlich in einem API-Call. Sogar das Zeichnen der Buchstaben eines TLabels - das wird alles per API-Calls erledigt.

Gruss,
Simon
Finn Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43



BeitragVerfasst: Do 17.02.05 21:55 
Titel: DANKE
Hi Simon,

vielen Dank für deine ausfühliche Antwort. Jetzt bin ich schon wieder ein bisschen schlauer.
Ich hab die Variablen und einige Funktionen eingefügt allerdings blicke ich nicht ganz durch was die Funktionen bewirken und wo ich sie einsetzen muss.

Die Übertragung erfolgt mit 9600 Baud. (Die Baudrate ist doch die Anzahl der "Elementarinformationen" pro Sekunde, oder?)

So, das hab ich das jetzt in Delphi eingefügt:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

  // Benutzte GlobaleVariablen
  PortTimeout : _COMMTIMEOUTS;
  PortHandle : Integer;
  PortDCB : TDCB;
  PortNr  : Integer;
  PortState : Cardinal;
  WriteOverlapped,ReadOverlapped,StatusOs: TOverlapped;

implementation

// Testen ob Schnittstelle verfügbar ist
function ComAvailable(ComNr: byte): boolean; stdcall;
var
  TestHandle : integer;
begin
  TestHandle :=
  CreateFile(PChar('\\.\COM'+IntToStr(ComNr)),GENERIC_READ or GENERIC_WRITE,0,
             nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,LongInt(0));
  if (TestHandle <= 0then
    Result := false
  else
  begin
    Result := true;
    CloseHandle(TestHandle);
  end;
end;

// Die Schnittstelle öffnen / schließen / testen
function OpenCOM(Port: byte): boolean; stdcall;
begin
  PortHandle :=
  CreateFile(PChar('\\.\COM'+IntToStr(Port)),GENERIC_READ or GENERIC_WRITE,0,
             nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,LongInt(0));

  if PortNr > 0 then
  begin                                     
    Result := true;                         // Hier kommt die Fehlermeldung
    InitOverlapped(WriteOverlapped);        // Undeclared identifier:
    InitOverlapped(ReadOverlapped);         // 'Init Overlapped'
    InitOverlapped(StatusOs);
  end else Result := false;
end;

// Ini Funktion für die Overlapped Strukturen
procedure InitOverlapped(var Overlapped : TOverlapped);
begin
  Overlapped.Offset := 0;
  Overlapped.OffsetHigh := 0;
  Overlapped.Internal := 0;
  Overlapped.InternalHigh := 0;
  Overlapped.hEvent := CreateEvent(nil,True,False,'');
end;

// Die Schnittstelle konfigurieren
function SetBaudRate(baud: cardinal): boolean; stdcall;
begin
  GetCommState(PortHandle,PortDCB);
  PortDCB.BaudRate := baud;
  Result := SetCommState(PortHandle,PortDCB);
end;

function SendString(Str: PChar): boolean; stdcall;
var
  written  : cardinal;
  tmpStr : string;
  i: LongBool;
begin
  if (PortHandle <> 0then
  begin
    tmpStr := string(Str);
    Result := not WriteFile(PortHandle,tmpStr[1],Length(tmpStr),written,@WriteOverlapped);
  end;
end;

// Lesen und Schreiben
function ReadString(var Buf: PChar): Cardinal; stdcall;
var
  StrBuf: string;
  Error,BytesRead: DWORD;
  Status: TComStat;
  RdSuccess: boolean;
begin
  BytesRead := 0;
  if (PortHandle <> -1then
  begin
    ClearCommError(PortHandle,Error,@Status);
    case Error of
      CE_BREAK,CE_DNS,CE_FRAME,CE_IOE,CE_MODE,CE_OOP,CE_OVERRUN,CE_PTO,CE_RXOVER,
      CE_RXPARITY,CE_TXFULL:
      begin
        BytesRead := 0;
      end
    else
      begin
        SetLength(StrBuf,Status.cbInQue);
        RdSuccess := ReadFile(PortHandle,StrBuf[1],Status.cbInQue,BytesRead,@ReadOverlapped);
        if not RdSuccess then BytesRead := 0;
      end;
    end;
  end;
  if (BytesRead > 0then
  begin
    Result := BytesRead;
    try
      StrPCopy(Buf,StrBuf);
    except
      Result := 0;
    end;
  end else Result := 0;
end;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

begin
OpenCOM(1);
SetBaudRate(9600);
SendString(PChar('Ich bin ein Befehl'));
CloseCOM(1);                               // Hier kommt die Fehlermeldung
end;                                       // Undeclared identifier:
                                           // 'Close COM'
end.


(Ich hoff ,dass ich das nicht total doof angestellt hab :oops: )

Beim compilieren hat er zweimal gemeckert:
Undeclared identifier:'Init Overlapped'
Undeclared identifier:'Close COM'

Zitat:

Um nun Befehle zu versenden benützst du den Befehl
SendString(PChar('Ich bin ein Befehl'));


Wie muss ich mir die Befehle vorstellen?
In der Doku der Motorsteuerung ist eine Übersicht über RS 232 Befehle die z.B. so aussehen:

print "#rmi" & chr(0) & chr(200) // Damit wird der Motorstrom eingestellt

Kann ich mit sowas in Delphi etwas anstellen?

Gruß
Finn
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 17.02.05 22:24 
Hi Finn

Die Funktion "CloseCom" hast du vergessen aus dem Post zu kopieren.
Zudem musst du im Programm "CloseCom;" schreiben, statt "CloseCom(1);".

Und das "InitOverlapped" musst vor dem "OpenCOM" kommen (Reihenfolge der Funktionen vertauschen).

Die Funktion "ReadString" kannst du löschen, die brauchst du nicht (du musst ja nur senden).

Wie der Befehl genau aussehen muss, weiss ich leider auch nicht. Ich frage mich was "&" bedeutet? Ist das VB?
Probier mal SendString(PChar('#rmi'+chr(0)+chr(200)));

Gruss,
Simon