[gelöst] Consolenanwendung in Gui wandeln

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
NoCee
Beiträge: 167
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

[gelöst] Consolenanwendung in Gui wandeln

Beitrag von NoCee »

Guten Abend zusammen,
ich versuche gerade verzweifelt eine Konsolenanwendung
in ein Gui Programm umzubauen.
Die Hardware ist von Tinkerforge und dafür gibt's
Bindings für Delphi/Lazarus und Beispiele.
Problem, die Beispiele sind alle nur für Konsolenanwendungen.
Ich krieg das nicht in eine primitive Guianwendung gepackt.
hier das Beispiel: https://www.tinkerforge.com/de/doc/Soft ... elphi.html
Die Hardware besteht u.a. aus 4 digitalen Eingänge.
Man kann laut Beispiel hier einen Callback registrieren und da hörts leider auf.
Kann mir jemand zeigen wie das zu händeln ist?
Im unteren Beispiel vom Link "Interrupt" ist das für Apptype Console beschrieben und funktioniert auch.
Aber wie registriere ich einen Interrupt Callback in einer Guianwendung?
Der soll aufgerufen werden wenn sich einer der 4 Eingänge ändert.
Versuchshalber hab ich nur einen Button auf dem Formular gelegt, der Off bzw. On anzeigen soll.
Je nach Logiklevel vom digitalen Eingang.

Für Hilfe wäre ich dankbar

Grüße und Danke im Vorraus
NoCee
Zuletzt geändert von NoCee am Fr 15. Jun 2018, 21:25, insgesamt 2-mal geändert.

Mathias
Beiträge: 6143
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Consolenanwendung in Gui wandeln

Beitrag von Mathias »

Meist du so was ?
Beim Klicken auf den Button, wird eine Ausgabe auf das Label ausgegeben.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  valueMask: word;
begin
  { Create IP connection }
  ipcon := TIPConnection.Create;
 
  { Create device object }
  idi4 := TBrickletIndustrialDigitalIn4.Create(UID, ipcon);
 
  { Connect to brickd }
  ipcon.Connect(HOST, PORT);
  { Don't use device before ipcon is connected }
 
  { Get current value as bitmask }
  valueMask := idi4.GetValue;
 
  Label1.Caption := Format('Value Mask: %d', [valueMask]);
 
  //  WriteLn(Format('Value Mask: %d', [valueMask]));
 
  //  WriteLn('Press key to exit');
  //  ReadLn;
  ipcon.Destroy; { Calls ipcon.Disconnect internally }
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

NoCee
Beiträge: 167
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: Consolenanwendung in Gui wandeln

Beitrag von NoCee »

Ne,
die Abfrage soll ja automatisch laufen.
So wie du es geschrieben hast, wäre es vom Link das obere Beispiel.
Als Einzelabfrage.
Das müßte ich dann ständig pollen. Oder über einen Timer machen.
Das geht aber irgendwie mit Registrierung eines Callbacks.
Wenn sich einer der Eingänge ändert wird dieser ohne mein Zutun aufgerufen.
Den Button hab ich nur um darauf entweder Off oder On anzuzeigen.
Auf dem Formular wird der Button nicht betätigt (reine Anzeige).

Code: Alles auswählen

 
{ Callback procedure for interrupt callback }
procedure TExample.InterruptCB(sender: TBrickletIndustrialDigitalIn4;
                               const interruptMask: word; const valueMask: word);
begin
  WriteLn(Format('Interrupt Mask: %d', [interruptMask]));// hier will ich den Button ändern (off/on)
  WriteLn(Format('Value Mask: %d', [valueMask]));          // die 3 Zeilen zu ändern krieg ich hin
  WriteLn('');                                                                 
end;
 
 
//das gehört auch noch irgendwo hin
 { Register interrupt callback to procedure InterruptCB }
  idi4.OnInterrupt := {$ifdef FPC}@{$endif}InterruptCB;
 


So wie ich das verstanden habe, kann ich irgendwie der Firmware sagen
melde dich erst wenn du einen Wechsel der Zustände am Eingang erkennst.
Dann ruft es den Callback "InterruptCB" auf mit dem ich dann was anfangen kann.
Tinkerforge beschreibt das über den Callback zum machen als den besseren Weg.
Was ich noch nachvollziehen kann.
Aber die paar Zeilen in ein Gui zu bekommen halt nicht mehr.

Gruß
NoCee

Mathias
Beiträge: 6143
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Consolenanwendung in Gui wandeln

Beitrag von Mathias »

Auf diese Art sollte es gehen, habe den Code blind getippt.

Code: Alles auswählen

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    ipcon: TIPConnection;
    idi4: TBrickletIndustrialDigitalIn4;
    procedure InterruptCB(Sender: TBrickletIndustrialDigitalIn4; const interruptMask: word; const valueMask: word);
  public
  end;
 
... 
 
const
  HOST = 'localhost';
  PORT = 4223;
  UID = 'XYZ'; { Change XYZ to the UID of your Industrial Digital In 4 Bricklet }
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  { Create IP connection }
  ipcon := TIPConnection.Create;
 
  { Create device object }
  idi4 := TBrickletIndustrialDigitalIn4.Create(UID, ipcon);
 
  { Connect to brickd }
  ipcon.Connect(HOST, PORT);
  { Don't use device before ipcon is connected }
 
  { Register interrupt callback to procedure InterruptCB }
 
  idi4.OnInterrupt := @InterruptCB;
 
  { Enable interrupt on pin 0 }
  idi4.SetInterrupt(1 shl 0);
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  idi4.Free;
  ipcon.Free;
end;
 
procedure TForm1.InterruptCB(Sender: TBrickletIndustrialDigitalIn4;
  const interruptMask: word; const valueMask: word);
begin
  ShowMessage('Ausgelöst');
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

NoCee
Beiträge: 167
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: Consolenanwendung in Gui wandeln

Beitrag von NoCee »

Danke für die schnelle Antwort.
Das sieht optisch schon mal richtig gut aus.
So in der Art hab ich mir das vorgestellt, bin aber in der Ecke noch ziemlicher Laie
als das ich das selber so hinbekommen würde.
Bin gespannt obs auch tut. Zumindest hilfts mal ein ganzes Stück weiter.
Komm aber erst nächste Woche zum Testen.
Ich hab mir noch alle Beispiele für Delphi/Lazarus auf der Seite von Tinkerforge angeschaut.
Alle nur für Konsole. Zwar schön aufwändig gemacht, aber hilft mir halt nicht.
Aber jetzt könnte es ja endlich klappen.

Danke nochmals für die Hilfe
und ein schönes Wochenende
NoCee

Benutzeravatar
kupferstecher
Beiträge: 416
Registriert: Do 17. Nov 2016, 11:52

Re: Consolenanwendung in Gui wandeln

Beitrag von kupferstecher »

Wenn ich das richtig sehe, ist dir eigentlich nur unklar, wo die Initialisierungen hingehoeren, oder?
*Einmal - wie Mathias vorgeschlagen hat - in das OnCreate-Ereignis der Form. Die kannst du im Objektinspektor anlegen.
*Eine andere geeignete Stelle ist in der Programmdatei '.lpr', direkt vor Application.Run. Dort ruft man zweckmaessigerweise eine Funktion auf, in der man alle Initialisierungen buendelt.
*Dann gibt es noch die INITIALIZATION (und FINALIZATION) -Abschnitte in den Units. Das ist ein Sprachfeature und wird damit noch vor der Erzeugung der Form(s) aufgerufen. Ist dadurch fuer visuelle Komponenten aber ungeeignet (Owner und Parent koennen nicht gesetzt werden).

NoCee
Beiträge: 167
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: Consolenanwendung in Gui wandeln

Beitrag von NoCee »

Guten Abend zusammen,
ich hab das in der Art in mein Prog eingebaut und es funzt einwandfrei.
Nur hab ich jetzt ein Problem mit einem Timer.
Den hab ich auf mein Formular gepackt und entsprechend gestartet.
Aber da passiert nix.

Code: Alles auswählen

procedure TForm1.InterruptCB(Sender: TBrickletIndustrialDigitalIn4;  const interruptMask: word; const valueMask: word);
begin 
  ShowMessage('Ausgelöst');
  MyTimer.enabled:=true;
end;
 


Ich hab versuchsweise noch im MyTimer.OnStart und OnStop noch was reingeschrieben.
Diese Events kommen einwandfrei.
Aber die Sekunde läuft nicht ab, bzw OnTimer kommt nicht.
Was ich dann herrausgefunden habe ist das wenn ich mir eine Variable im InteruptCB auf true setze mit der ich
wo anders den Timer starte, zB hab ich einen Sekundentakt, wenn ich hier reinschreibe
if MyVariable=true then MyTimer.Enable:=true;
und meine Variable dann auf false setze, läuft der Timer ganz wie gewohnt.
Warum kommen OnStart und OnStop vom Timer aber der OnTimer nicht?
Wie krieg ich das richtig zum Laufen ohne den Umweg mit einer Variablen?

Vielen Dank schon mal im Vorraus
Gruß
NoCee

NoCee
Beiträge: 167
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: Consolenanwendung in Gui wandeln

Beitrag von NoCee »

Jou, nachdem mir keiner helfen will :)

Ich vermute daß das Problem an dem Callback im Zusammenhang mit einem TTimer liegt.
Beim Pupillen wundlesen hab ich gefunden daß ein TTimer nicht threadsave sei.
Da kam das Gefühl auf, daß der Callback nicht zum Mainthread gehört es also hier Probleme geben kann.
Da hab ich dann einen Versuch mit einem TFPTimer gestartet und siehe da, es funktioniert.
Es wäre schön, wenn mir das jetzt noch jemand schlüssig erklären könnte.
Wo ist der Unterschied zwischen TTimer und TFPTimer?

Ansonsten ist das Thema damit erledigt.

Gruß und schönes Wochenende
NoCee

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Consolenanwendung in Gui wandeln

Beitrag von Socke »

NoCee hat geschrieben:Wo ist der Unterschied zwischen TTimer und TFPTimer?


TTimer wird vom Widgetset bereitgestellt und ist daher wie alle Widgetset-Dinge nicht threadsafe. Alles was das Widgetset betrifft (=GUI) gehört immer in den Mainthread. TTimer wird also von extern im Mainthread benachrichtigt und bearbeitet.

TFPTimer ist hingegen unabhängig von einem Widgetset implementiert. Die Komponente stellt hier lediglich eine Schnittstelle zum eigentlichen Timer der Klasse TFPTimerDriver dar. Deine Anwendung kann hier für verschiedene Zwecke verschieden Timer-Driver nutzen; das Widgetset als Quelle zu nutzen wäre also auch möglich. Die Standardimplementierung TFPThreadedTimerDriver nutzt einen eigenen Thread pro Timer für das Timing (Warten zwischen den Intervallen). Die eigentliche Ausführung des Event-Codes wird dann aber per Synchronize() an den Mainthread übergeben. D.h. selbst wenn du den Timer aus einem Thread heraus startest, wird der Event-Code immer noch im Mainthread und nicht im Timer-startenden Thread ausgeführt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

NoCee
Beiträge: 167
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: [gelöst] Consolenanwendung in Gui wandeln

Beitrag von NoCee »

Vielen Dank für die Antwort.
Der Timer ist genau das was ich gerade brauche.

Nur noch aus Neugier:
Wenn ich jetzt in einer Gui Anwendung einen Timer innerhalb eines separaten Threads bräuchte,
wie könnte man das lösen?

Gruß
NoCee

Antworten