RPi - Bessere Möglichkeit zur Abfrage vieler GPIO's?

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Osmodia
Beiträge: 6
Registriert: Sa 20. Dez 2014, 21:29

RPi - Bessere Möglichkeit zur Abfrage vieler GPIO's?

Beitrag von Osmodia »

Hi,
ich programmiere mit Lazarus auf einem Raspberry Pi samt Pascal IO. Genauer gesagt, schreibe ich ein kleines Kontrollprogramm, womit ich die Zustände einiger GPIO Pins auslese und das Programm darauf halt reagiert.
Insgesamt habe ich 6 Reed Kontakte und einen PIR Sensor als Inputs an den GPIO Pins, und einen Kontakt für ein Relais als Output.
Über 2 ToggleBox' en kann ich die Alarmanlage Ein und Ausschalten bzw. Scharf / Unscharf stellen.

Bild

Falls einer der Kontakte geöffnet wird, und die Alarmanlage aus ist, wird in eine Listbox die Uhrzeit und die Meldung eingetragen, welcher Kontakt geöffnet wurde.
Falls aber die Alarmanlage Scharf ist und ein Kontakt geöffnet wird, wird ebenfalls eine Meldung in die Listbox eingetragen und zusätzlich dazu das Relais geschaltet.

Soweit funktioniert das auch wie es soll. Die GPIO Pins werden korrekt ausgelesen und geschaltet und die Zuständer werden verarbeitet.
Standardmäßig wird die Alarmanlage beim Form.Create ausgeschaltet und die Box wird aktiviert.

Sobald man die ToggleBox zum Scharfstellen anklickt, und ein Kontakt geöffnet wird (egal welcher, ich habe alle getestet) schaltet das Relais.
Aber:
Wenn dann der Kontakt wieder geschlossen wird, und erneut geöffnet wird, oder ein anderer Kontakt geöffnet wird, schaltet der Pin nicht durch.
Erst wenn ich die Alarmanlage ausschalte und wieder einschalte funktioniert es wieder bis ein Kontakt geöffnet wird. Dann muss ich wieder Aus- und Einschalten.


Anbei Code Fragmente:

Code: Alles auswählen

 
[...]
  private 
  waschkeller_19: TGpioLinuxPin;
  hintereingang_21: TGpioLinuxPin;
[...]
var // Global
alarm_scharf: Boolean;
[...]
procedure TForm1.ToggleBox1Change(Sender: TObject);
begin
  if ToggleBox1.Checked = true then
   begin
   ToggleBox2.Checked := false;
   Panel1.Color:=clLime;
   Label14.Caption:='Alarmanlage ist [AN]!';
   alarm_scharf := true;
   ListBox1.Items.Add(timetostr(time) +' '+ datetostr(date) + '  -  ' + 'Alarmanlage ist [AN]');
   end;
end; 
 
procedure TForm1.ToggleBox2Change(Sender: TObject);
begin
  if ToggleBox2.Checked = true then
   begin
   ToggleBox1.Checked := false;
   Panel1.Color:=clRed;
   Label14.Caption:='Alarmanlage ist [AUS]!';
   alarm_scharf := false;
   ListBox1.Items.Add(timetostr(time) +' '+ datetostr(date) + '  -  ' + 'Alarmanlage ist [AUS]');
 end;
end;
 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
   Label1.Caption:=timetostr(time) +' '+ datetostr(date);
   ListBox1.Items.Add(timetostr(time) +' '+ datetostr(date) + '  -  ' + 'Programm gestartet!');
   ToggleBox2.Checked := true;
end;
 
 
procedure TForm1.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
 
begin
   waschkeller_19 := TGpioLinuxPin.Create(P35);
   hintereingang_21 := TGpioLinuxPin.Create(P40);
[...]
   waschkeller_19.Direction := gdIn;
   hintereingang_21.Direction := gdIn;
[...]
 
//Washkeller/////////////////////////////////////////////////////
  if waschkeller_19.value = false then
  begin
     Label8.Caption := ('[Offen]');
   end;
  if (waschkeller_19.value = false) and (alarm_scharf = true) then
  begin
     Label8.Caption := ('[Offen]');
     sirene_10.value := true;
     sleep(1000);
     sirene_10.value := false;
     sirene_10.Destroy;
     waschkeller_19.value := true;
     alarm_scharf := false;
    end;
if waschkeller_19.value = true then
   begin
     Label8.Caption := ('[Geschlossen]');
   end;
 
//Hintereingang///////////////////////////////////////////////////
 
if hintereingang_21.value = false then
begin
   Label9.Caption := ('[Offen]');
 end;
if (hintereingang_21.value = false) and (alarm_scharf = true) then
begin
   Label9.Caption := ('[Offen]');
   sirene_10.value := true;
   sleep(1000);
   sirene_10.value := false;
   sirene_10.Destroy;
   hintereingang_21.value := true;
   alarm_scharf := false;
  end;
if hintereingang_21.value = true then
  begin
   Label9.Caption := ('[Geschlossen]');
end;   
 
// Die anderen Kontakte bestehen auch aus verschachtelten if then Bedingungen 
[...]                               
 
 
Kann man die ganzen if then Bedingungen ersetzen durch etwas kompakt und sinnvollerem?
Ich vermute irgend wo dort liegt der Hund begraben - entweder habe ich also irgendwo einen Denkfehler oder es ist einfach zu spät :roll:

Vielleicht kann mir ja jemand helfen :)

Socke
Lazarusforum e. V.
Beiträge: 3178
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: RPi - Bessere Möglichkeit zur Abfrage vieler GPIO's?

Beitrag von Socke »

Osmodia hat geschrieben:Kann man die ganzen if then Bedingungen ersetzen durch etwas kompakt und sinnvollerem?
Ich vermute irgend wo dort liegt der Hund begraben - entweder habe ich also irgendwo einen Denkfehler oder es ist einfach zu spät :roll:
Die einfachen Tipps:

Code: Alles auswählen

 if (waschkeller_19.value = false) and (alarm_scharf = true) then
// verkürzen zu
 if (not waschkeller_19.value) and alarm_scharf then
Vergleiche mit True und False ergeben keine neue Weisheit.

Sich wiederholende Dinge kann man in eigene Funktionen ausgliedern, wie z.B.

Code: Alles auswählen

     sirene_10.value := true;
     sleep(1000);
     sirene_10.value := false;
     sirene_10.Destroy;
Wobei die Sirene hoffentlich noch irgendwo erstellt wird.

Ansonsten musst du wohl die gesamte Programmstruktur ändern. Beispielsweise defnierst du dir einen Record/Objekt, in dem du den Zusammenhang zwischen Eingangssignal und Anzeige-Label speicherst. Zu Programmbeginn füllst du dann eine Liste mit diesen Zusammenhängen und suchst dann in der Liste nach dem passenden Zusammenhang-Record.

Code: Alles auswählen

type TMyRecord = record
  Input: TGPIOPin;
  AnzeigeLabel: TLabel;
end;
 
procedure TuWas(const therecord: TMyRecord);
begin
  if (not therecord.Input.Value) and alarm_scharf then
  begin
    therecord.AnzeigeLabel.Caption := 'Offen';
    SireneHeulen;
   // usw.
  end;
end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Osmodia
Beiträge: 6
Registriert: Sa 20. Dez 2014, 21:29

Re: RPi - Bessere Möglichkeit zur Abfrage vieler GPIO's?

Beitrag von Osmodia »

Danke für deine Tipps. Wenn ich das richtig verstehe mit dem Record, muss ich also jeden Pin als Wert in den Record eintragen?
Weil im Augenblick definiere ich alle Pins über die private Deklaration:

Code: Alles auswählen

 
private
waschkeller_19: TGpioLinuxPin;
hintereingang_21: TGpioLinuxPin; 
[...]
 
Das würde also entfallen, oder wie sehe ich das?

Code: Alles auswählen

type TMyRecord = record
  waschkeller_19: TGpioLinuxPin;
  hintereingang_21: TGpioLinuxPin;
{usw}
 [...]
  label_waschkeller: TLabel;
  label_hintereingang: TLabel;
 {usw}
[...]
end;
 
procedure TForm1.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
begin
  if (not TMyRecord.waschkeller.value) and (alarm_scharf) then
  begin
    TMyRecord.label_waschkeller.caption := 'Offen';
    Sirene_An;
  end;
 
  if not TMyRecord.waschkeller.value then
 begin
    TMyRecord.label_waschkeller.caption := 'Offen'  
 end
 
  if TMyRecord.waschkeller.value = true then
   begin
      TMyRecord.label_waschkeller.caption := 'Geschlossen';
 
begin
  if (not TMyRecord.hintereingang.value) and alarm_scharf then
  begin
    TMyRecord.label_hintereingang.caption := 'Offen';
    Sirene_An;
  end;
 
   // usw.
  end;
end;
Danke schon mal.

Antworten