In diesem Abschnitt werden die Grundsätze für die Implementierung von HAL-Komponenten mit der Programmiersprache Python erläutert.

1. Grundlegendes Anwendungsbeispiel

Eine Nicht-Echtzeit-Komponente beginnt mit der Erstellung ihrer Pins und Parameter und tritt dann in eine Schleife ein, die periodisch alle Ausgänge von den Eingängen steuert. Die folgende Komponente kopiert den Wert an ihrem Eingangspin (passthrough.in) etwa einmal pro Sekunde an ihren Ausgangspin (passthrough.out).

#!/usr/bin/env python3
import hal, time
h = hal.component("passthrough")
h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)
h.newpin("out", hal.HAL_FLOAT, hal.HAL_OUT)
h.ready()
try:
    while 1:
        time.sleep(1)
        h['out'] = h['in']
except KeyboardInterrupt:
    raise SystemExit

Kopieren Sie das obige Listing in eine Datei mit dem Namen "passthrough", machen Sie es ausführbar (chmod +x), und legen Sie es in Ihren $PATH. Dann probieren Sie es aus:

Bildschirmkopie mit Einzelheiten über die Ausführung des neu erstellten Passthrough-HAL-Moduls.
$ halrun

halcmd: loadusr passthrough

halcmd: show pin

    Komponenten-Pins:
    Owner Typ  Richtung     Wert  Name
     03   float IN          0  passthrough.in
     03   float OUT         0  passthrough.out

halcmd: setp passthrough.in 3.14

halcmd: show pin

    Komponenten-Pins:
    Owner Typ   Richtung Wert  Name
     03   float IN       3.14  passthrough.in
     03   float OUT      3.14  passthrough.out

2. Nicht-Echtzeit-Komponenten und Verzögerungen

Wenn Sie schnell "show pin" eintippen, sehen Sie vielleicht, dass "passthrough.out" immer noch den alten Wert von 0 hat. Das liegt an dem Aufruf von "time.sleep(1)", der dafür sorgt, dass die Zuweisung an den Ausgangspin höchstens einmal pro Sekunde erfolgt. Da es sich um eine Nicht-Echtzeit-Komponente handelt, kann die tatsächliche Verzögerung zwischen den Zuweisungen viel länger sein, wenn der von der Passthrough-Komponente verwendete Speicher auf die Festplatte ausgelagert wird, da die Zuweisung verzögert werden könnte, bis dieser Speicher wieder ausgelagert wird.

So eignen sich Nicht-Echtzeit-Komponenten für benutzerinteraktive Elemente wie Bedienfelder (Verzögerungen im Bereich von Millisekunden werden nicht bemerkt, und längere Verzögerungen sind akzeptabel), nicht aber für das Senden von Schrittimpulsen an eine Stepper-Treiberkarte (Verzögerungen müssen immer im Bereich von Mikrosekunden liegen, egal wie).

3. Pins und Parameter erstellen

h = hal.component("passthrough")

Die Komponente selbst wird durch einen Aufruf des Konstruktors hal.component erzeugt. Die Argumente sind der HAL-Komponentenname und (optional) das für Pin- und Parameternamen verwendete Präfix. Wird das Präfix nicht angegeben, wird der Komponentenname verwendet.

h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)

Dann werden Pins durch Aufrufe von Methoden auf dem Komponentenobjekt erstellt. Die Argumente sind: Suffix des Pin-Namens, Pin-Typ und Pin-Richtung. Bei Parametern lauten die Argumente: Parameternamenssuffix, Parametertyp und Parameterrichtung.

Tabelle 1. Namen der HAL-Optionen

Pin- und Parametertypen:

HAL_BIT

HAL_FLOAT

HAL_S32

HAL_U32

HAL_S64

HAL_U64

Pin-Richtungen:

HAL_IN

HAL_OUT

HAL_IO

Parameter-Richtungen:

HAL_RO

HAL_RW

Der vollständige Pin- oder Parametername wird durch Verbinden des Präfixes und des Suffixes mit einem "." gebildet. Im Beispiel heißt der erstellte Pin also passthrough.in.

h.ready()

Sobald alle Pins und Parameter erstellt wurden, rufen Sie die Methode .ready() auf.

3.1. Ändern des Präfixes

Das Präfix kann durch den Aufruf der Methode .setprefix() geändert werden. Das aktuelle Präfix kann durch den Aufruf der Methode .getprefix() abgefragt werden.

4. Lesen und Schreiben von Pins und Parametern

Bei Pins und Parametern, die auch echte Python-Bezeichner sind, kann der Wert unter Verwendung der Attributsyntax aufgerufen oder gesetzt werden:

h.out = h.in

Für alle Pins, unabhängig davon, ob sie auch echte Python-Bezeichner sind oder nicht, kann der Wert unter Verwendung der tiefgestellten Syntax aufgerufen oder gesetzt werden:

h['out'] = h['in']

Um alle Pins mit ihren Werten zu sehen, gibt getpins alle Werte in einem Wörterbuch dieser Komponente zurück.

h.getpins()
>>>{'in': 0.0, 'out': 0.0}

4.1. Ansteuerung der Ausgangsstifte (HAL_OUT)

In regelmäßigen Abständen, in der Regel als Reaktion auf einen Timer, sollten alle HAL_OUT-Pins "getrieben" werden, indem ihnen ein neuer Wert zugewiesen wird. Dies sollte unabhängig davon geschehen, ob sich der Wert von dem zuletzt zugewiesenen unterscheidet oder nicht. Beim Verbinden eines Pins mit einem Signal wird sein alter Ausgangswert nicht in das Signal kopiert, so dass der richtige Wert erst auf dem Signal erscheint, wenn die Komponente einen neuen Wert zuweist.

4.2. Ansteuerung von bidirektionalen (HAL_IO) Pins

Die obige Regel gilt nicht für bidirektionale Pins. Stattdessen sollte ein bidirektionaler Pin nur dann von der Komponente angesteuert werden, wenn die Komponente den Wert ändern möchte. In der kanonischen Encoder-Schnittstelle beispielsweise setzt die Encoder-Komponente den Pin index-enable nur auf FALSE (wenn ein Indeximpuls gesehen wird und der alte Wert TRUE ist), aber niemals auf TRUE. Das wiederholte Setzen des Pins auf FALSE könnte dazu führen, dass die andere angeschlossene Komponente sich so verhält, als ob ein weiterer Indeximpuls gesehen worden wäre.

5. Beenden

Eine halcmd unload Anforderung für die Komponente wird als KeyboardInterrupt Ausnahme geliefert. Wenn eine Entladeanforderung eintrifft, sollte der Prozess entweder in kurzer Zeit beendet werden oder die Methode .exit() für die Komponente aufrufen, wenn umfangreiche Arbeiten (wie das Lesen oder Schreiben von Dateien) durchgeführt werden müssen, um den Abschaltvorgang abzuschließen.

6. Hilfreiche Funktionen

Siehe Python HAL Interface für eine Übersicht der verfügbaren Funktionen.

7. Konstanten

Verwenden Sie diese, um Details zu spezifizieren, und nicht den Wert, den sie enthalten.

  • HAL_BIT

  • HAL_FLOAT

  • HAL_S32

  • HAL_U32

  • HAL_S64

  • HAL_U64

  • HAL_IN

  • HAL_OUT

  • HAL_RO

  • HAL_RW

  • MSG_NONE

  • MSG_ALL

  • MSG_DBG

  • MSG_ERR

  • MSG_INFO

  • MSG_WARN

8. System-Informationen

Lesen Sie diese, um Informationen über das Echtzeitsystem zu erhalten.

  • is_kernelspace

  • is_rt

  • is_sim

  • is_userspace