Raspberry mit HC-SR04 (Ultraschall)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
braspi
Beiträge: 57
Registriert: So 20. Mär 2016, 16:39

Raspberry mit HC-SR04 (Ultraschall)

Beitrag von braspi »

Hallo, ich will Wege messen. Ich bekomme die Umsetzung nach Pascal leider nicht hin. Weiß wer Rat ?

Code: Alles auswählen

 
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Buttons,
  StdCtrls, Time,
  Unix, BaseUnix,
  Process
  ;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Memo: TMemo;
    Process: TProcess;
    sbBeenden: TSpeedButton;
    sbPascal: TSpeedButton;
    sbLeeren: TSpeedButton;
    sbPython: TSpeedButton;
    procedure OnCreate(Sender: TObject);
    procedure OnShow(Sender: TObject);
    procedure sbBeendenClick(Sender: TObject);
    procedure sbPascalClick(Sender: TObject);
    procedure sbLeerenClick(Sender: TObject);
    procedure sbPythonClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    sPath : string;
 
    TRIG    : integer;
    ECHO    : integer;
    PULSE   : real;
    BURST   : integer;
    SPEED_2 : integer;
 
    procedure Init_ultra(Pin_T : integer; Pin_E : integer);
    function Pin_Get(Pin_E : integer):integer;
  end;
  const
  PIN_ON        : PChar = '1';
  PIN_OFF       : PChar = '0';
  OUT_DIRECTION : PChar = 'out';
  IN_DIRECTION  : PChar = 'in';
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Init_ultra(Pin_T : integer; Pin_E : integer);
var
   fileDesc    : integer;
   gReturnCode : integer;
   cPIN        : PChar;
begin
     // Trigger als Ausgang
      cPIN := PChar(IntToStr(Pin_T));
 
     try
        fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
        gReturnCode := fpwrite(fileDesc, cPin[0], 2);
     finally
        gReturnCode := fpclose(fileDesc);
     end;
 
     try
        fileDesc := fpopen('/sys/class/gpio/gpio' + IntToStr(Pin_T) + '/direction' , O_WrOnly);
        gReturnCode := fpwrite(fileDesc, OUT_DIRECTION[0], 3);
     finally
         gReturnCode := fpclose(fileDesc);
     end;
 
     // Echo als Eingang
     cPIN := PChar(IntToStr(Pin_E));
 
     try
        fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
        gReturnCode := fpwrite(fileDesc, cPin[0], 2);
     finally
        gReturnCode := fpclose(fileDesc);
     end;
 
     try
        fileDesc := fpopen('/sys/class/gpio/gpio' + IntToStr(Pin_E) + '/direction' , O_WrOnly);
        gReturnCode := fpwrite(fileDesc, IN_DIRECTION[0], 2);
     finally
         gReturnCode := fpclose(fileDesc);
     end;
 
end;
 
function TForm1.Pin_Get(Pin_E : integer):integer;
var
   cPin        : PChar;
   fileDesc    : integer;
   gReturnCode : integer;
   pinStatus   : string[1] = '1';
   iStatus     : integer;
begin
     cPin := PChar(IntToStr(Pin_E));
 
     try
        fileDesc    := fpopen('/sys/class/gpio/gpio' + cPin + '/value' , O_RdOnly);
        gReturnCode := fpread(fileDesc, pinStatus[1], 1);
     finally
         gReturnCode := fpclose(fileDesc);
     end ;
 
     result:= StrToInt(pinStatus);
end;
 
procedure TForm1.sbLeerenClick(Sender: TObject);
begin
  Memo.Clear;
end;
 
procedure TForm1.sbPythonClick(Sender: TObject);
var
   AProcess    : TProcess;
   AStringList : TStringList;
begin
   AProcess    := TProcess.Create(nil);
   AStringList := TStringList.Create;
 
   try
      AProcess.CommandLine:='sudo ' + sPath + 'ultrasonic.py';
      AProcess.Options:= AProcess.Options + [poWaitOnExit, poUsePipes];
      AProcess.Execute;
      AStringList.LoadFromStream(AProcess.Output);
      Memo.Lines.Add(AStringList.Strings[0]);
   finally
           AProcess.Free;
           AStringList.Free;
   end;
end;
 
procedure TForm1.sbBeendenClick(Sender: TObject);
begin
     Close();
end;
 
procedure TForm1.OnShow(Sender: TObject);
begin
     TRIG    := 18;
     ECHO    := 17;
     PULSE   := 0.00001;
     BURST   := 25;
     SPEED_2 := 17015;   // Schallgeschwindigkeit/2
 
     Init_ultra(TRIG, ECHO);
end;
 
procedure TForm1.OnCreate(Sender: TObject);
begin
     GetDir(0,sPath);
     if (Length(sPath)>3 ) then sPath := sPath + '/';
end;
 
procedure TForm1.sbPascalClick(Sender: TObject);
var
   cPin        : PChar;
   fileDesc    : integer;
   gReturnCode : integer;
   distance : real;
   delta    : real;
   starttime : TTime;
   start, stopp : TTime;
begin
     //GPIO.output(TRIG, True)       # Trigger-Impuls
     cPin := PChar(IntToStr(18));
     try
        fileDesc    := fpopen('/sys/class/gpio/gpio' + cPin + '/value' , O_WrOnly);
        gReturnCode := fpwrite(fileDesc, PIN_ON[0], 1);
     finally
         gReturnCode := fpclose(fileDesc);
     end ;
 
  //sleep(PULSE);
     try
        fileDesc := fpopen('/sys/class/gpio/gpio' + cPin + '/value' , O_WrOnly);
        gReturnCode := fpwrite(fileDesc, PIN_OFF[0], 1);
     finally
         gReturnCode := fpclose(fileDesc);
     end ;
 
  sleep(1);
  starttime := Time.CurrentSec100OfDay();       // Zeit initialisieren
  stopp     := starttime;
  start     := starttime;
 
  // (Busy) Warten auf steigende Flanke, max. 2 Sekunden
  while ((Pin_Get(17) = 0) and (start < (starttime + 2))) do
    start := Time.CurrentSec100OfDay();        // Startzeit
 
 
  // (Busy) Warten auf fallende Flanke, max. 2 Sekunden
 
  while ( (Pin_Get(17) = 1) and (stopp < (starttime + 2))) do
    stopp := Time.CurrentSec100OfDay();        // Endezeit
 
  delta    := stopp - start;         // Zeitdifferenz und Entfernung berechnen
  distance := delta * SPEED_2;
  Memo.Lines.Add(FloatToStr(distance));
end;
 
end.
 


hier der python ultrasonic.py

Code: Alles auswählen

 
#!/usr/bin/python
 
import RPi.GPIO as GPIO
import time
import datetime
 
# GPIOs fuer den US-Sensor
TRIG = 18
ECHO = 17
 
# Dauer Trigger-Impuls
PULSE = 0.00001
 
# Anzahl Messwerte fuer Mittelwertbildung
BURST = 25
 
# Schallgeschwindigkeit/2
SPEED_2 = 17015 
 
# BCM GPIO-Referenen verwenden (anstelle der Pin-Nummern)
# und GPIO-Eingang definieren
GPIO.setmode(GPIO.BCM)
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
GPIO.output(TRIG, False)
time.sleep(1)                   # Setup-Zeit fuer Sensor
 
def measure():                  # Messung ausfuehren
  GPIO.output(TRIG, True)       # Trigger-Impuls
  time.sleep(PULSE)
  GPIO.output(TRIG, False)
  starttime = time.time()       # Zeit initialisieren
  stopp = starttime
  start = starttime
  # (Busy) Warten auf steigende Flanke, max. 2 Sekunden
  while  GPIO.input(ECHO) == 0 and start < starttime + 2:
    start = time.time()         # Startzeit
  # (Busy) Warten auf fallende Flanke, max. 2 Sekunden
  while  GPIO.input(ECHO) == 1 and stopp < starttime + 2:
    stopp = time.time()         # Endezeit
  delta = stopp - start         # Zeitdifferenz und Entfernung berechnen
  distance = delta * SPEED_2
  return distance
 
def measure_range():            # Bildet Mittelwert von BURST Messungen
  values = []
  sum = 0
  for i in range(0, BURST):
    values.append(measure())    # Messung starten
    sum = sum + values[i]       # Wert im Array speichern und aufsummieren   
    time.sleep(0.05)
  return sum/BURST;             # Mittelwert zurueckgeben
 
# do it
try: 
    Distance = measure_range()
    Distance = Distance*10
    print("%1.0f" % Distance)
    time.sleep(1)
 
# reset GPIO settings if user pressed Ctrl+C
except :
  print("Bye")
  GPIO.cleanup()
 
 

Der Python müsste auch überarbeitet werde. Habe aber keine Ahnung.
Grüße aus Berlin

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

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Mathias »

Zuerst mal eine Frage, kannst du mit deinem Funktionen die GPIOs ansprechen, zB. wen eine LED angeschlossen ist ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von m.fuchs »

Ich habe das auch mal zwischendurch probiert und meine damals festgestellt zu haben, dass GPIO über den virtuellen Filezugriff zu langsam für den Ultraschallsensor ist. Gibt es da nicht noch andere Möglichkeiten?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Mathias »

Gibt es da nicht noch andere Möglichkeiten?

Ich habe bis jetzt leider auch nichts gefunden.
Aber vielleicht hilft dir dies weiter: http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi, Ungefähr bis Mitte scrollen.

Was man sicher direkt ansprechen kann, ist der I²C-Bus, dies habe ich schon probiert.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von pluto »

Am besten geht sowas über ein Arduino der am PI angeschlossen wird. Die Erfahrung konnte ich einmal machen.
MFG
Michael Springwald

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

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Mathias »

pluto hat geschrieben:Am besten geht sowas über ein Arduino der am PI angeschlossen wird. Die Erfahrung konnte ich einmal machen.

Da kann ich dir zustimmen, was GPIO, anbelangt hat der Arduino die Nase sehr weit vorn.
Dies hat noch einen Vorteil, man kann auf dem PC entwickeln und testen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von pluto »

Vielleicht gibt es auch schnelle Analog IC für den PI, die über I²C oder SPI angeschlossen werden... Wäre aber auch wieder ein externes Bauteil.

Ich denke ein atTiny oder ein Arduino Nano wäre das einfachste.....
MFG
Michael Springwald

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

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Mathias »

Ich denke ein atTiny oder ein Arduino Nano wäre das einfachste.....

Den Nano kann man einfach mit dem USB verbinden und fertig.
ATtiny ist schon komplizierter, man kann ihn wohl mit 3,3V betreiben und mit I²C mit dem Raspi verbinden, aber dann geht auch der Vorteil flöten, das man das Raspi-Programm auf dem schnellen PC einwickeln kann, und der grösste Nachteil, ist das programmieren des ATtiny selbst.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

braspi
Beiträge: 57
Registriert: So 20. Mär 2016, 16:39

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von braspi »

Hallo, was für eine Resonanz !
- die GPIO lassen sich wunderbar schalten
- das Messen geht mit dem Raspi auch

In meinem Beispiel, das funktioniert, muss ich allerdings den Umweg mit dem beschriebem Py-Script machen (Process ...). Soweit alles Tutti. Ich wollte nur mal den Script in Pascal umsetzen.
Irgendwie nehme ich die falsche Startzeit oder weiß der Teufel was.
Der Ultraschallsensor sollte in einem Rohr meinen Wasserstand messen, aber ich befürchte, dass das nicht klappt. Na mal sehen.
Grüße

braspi
Beiträge: 57
Registriert: So 20. Mär 2016, 16:39

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von braspi »

Noch was ..
Raspi deshalb, weil nach Stromausfall schaltet das Betriebssystem wieder ein und verbindet sich automatisch in meinem Netz. Ich kann die Software wunderbar mit vnc warten. ich habe mir ein Raspberry Zero W gekauft und der ist jetzt 2 m unter der Erde verbaut und kann da eine Drainage steuern. Hin und wieder schalte ich meinen Router aus und ein, der Raspi springt immer wieder an.
Grüße ...
Zuletzt geändert von braspi am Do 3. Aug 2017, 15:16, insgesamt 1-mal geändert.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von pluto »

Rasperry Zero W

Sagt das doch gleich, dass du kein Standard PI 3 oder so meinst.

Aber ob der ein Schnellen Anlogen Eingang hat?

Wie schon gesagt, du kannst ein Arduino sehr leicht am PI direkt über USB oder über die Gripo Leiste anschließen.
Scheinbar kommst du ja noch irgendwie an den PI ran oder?
So dürfte das kein Problem sein.
MFG
Michael Springwald

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

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Mathias »

Aber ob der ein Schnellen Anlogen Eingang hat?

Der HC-SR04 braucht gar keinen Analog-Eingang. Da läuft alles digital.
Siehe Arduino sketch: http://www.instructables.com/id/Simple- ... 4-Example/
Einzig, was ein Problem sein könnte, der Sensor arbeitet mit 5V und der Raspi hat 3,3V.
Aber dies kann man auch umgehen: https://tutorials-raspberrypi.com/raspb ... r-hc-sr04/

Wen man auf dieser Seite http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi weiter liest, hat es fast zum Schluss eine Unit, welche sehr schnellen GPIO-Zugriffe hat.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

braspi
Beiträge: 57
Registriert: So 20. Mär 2016, 16:39

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von braspi »

Hallo, es funktioniert ja. Nur habe ich zu meinem Leidwesen gemerkt, dass die Streuung für mich zu groß ist. Ich kann damit nicht zielen. Eigentlich sollte ein Schwimmer(Tennisball) in einem Rohr abgefragt werden. Nur meine "Konstruktion" macht nicht das, was sie soll, hat jemand eine Lösung ?
- zwei Widerstände lösen das Spannungsproblem.
Der Link sieht gut aus. Hatte natürlich auch geguckt, aber "Wer bis zum Ende liest hat mehr vom Text".
Danke.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Warf »

Ultraschallsensor und raspberry pi wird nicht gut funktionieren denn der pi hat ein Betriebssystem.

Das erste Problem sind die kontextwechsel, der Aufruf von read und Write bedeutet ein Wechsel des Prozesses, da diese Funktionen Programme des Betriebssystems sind. Dein eigener Prozess wird unterbrochen, das Betriebssystem läd seinen read/write Prozess, und wenn die Ergebnisse vorliegen wird dein Prozess wieder geladen. Das dauert lange, und da du beim ultraschallsensor sehr genau Zeit messen musst, macht kannst du dir diese Unterbrechung nicht leisten. Aus der userspace ist der Zugriff auf die gpio pins nicht ohne den Umweg über das Betriebssystem möglich.

Das zweite Problem ist das multithreading, das Betriebssystem kann jederzeit deinen Prozess kurzzeitig suspenden um einen anderen Prozess laufen zu lassen. Das macht jede deterministische genaue Zeitmessung unmöglich.

Es gibt dafür allerdings auch Lösungen. Entweder verwendest du einen microcontroller wie einen arduino, der dann ohne Betriebssystem nur das messen übernimmt und dann die Daten an den pi sendet, oder du schreibst eine Kernel Anwendung für Linux (Treiber, halt etwas das auf Ring 0 läuft), indem du dann das scheduling kurz ausschaltest und vollzugriff auf die gpios hast (realisiert dann durch isr oder kthread).

Um ehrlich zu sein würde ich dir lieber den arduino empfehlen, denn Kernel Prozesse zu schreiben ist echt nicht so einfach.


PS: Ultraschall Messung in einem Rohr klappt eh nicht sonderlich gut, da Schall von engen Wänden reflektiert wird, und du damit verfälschte Ergebnisse bekommst. Verwende lieber einen nicht Sensor

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

Re: Raspberry mit HC-SR04 (Ultraschall)

Beitrag von Mathias »

@Warf

Da hast du natürlich recht, beim Raspi hat man die gleichen Problem wie beim PC, wen man etwas in Echtzeit machen will.
Unter DOS was das früher etwas anders, da konnte man "CLI" aufrufen, aber bei den heutigen OS geht dies nicht mehr.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten