This section explains principles behind the implementation of HAL components with the Python programming language.
1. Basic usage example
A non-realtime component begins by creating its pins and parameters, then enters a loop which will periodically drive all the outputs from the inputs. The following component copies the value seen on its input pin (passthrough.in) to its output pin (passthrough.out) approximately once per second.
#!/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
Copy the above listing into a file named "passthrough", make it executable (chmod +x), and place it on your $PATH. Then try it out:
$ 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. Non-realtime components and delays
If you typed "show pin" quickly, you may see that passthrough.out still had its old value of 0. This is because of the call to time.sleep(1), which makes the assignment to the output pin occur at most once per second. Because this is a non-realtime component, the actual delay between assignments can be much longer if the memory used by the passthrough component is swapped to disk, as the assignment could be delayed until that memory is swapped back in.
Thus, non-realtime components are suitable for user-interactive elements such as control panels (delays in the range of milliseconds are not noticed, and longer delays are acceptable), but not for sending step pulses to a stepper driver board (delays must always be in the range of microseconds, no matter what).
3. Pins und Parameter erstellen
h = hal.component("passthrough")
The component itself is created by a call to the constructor hal.component. The arguments are the HAL component name and (optionally) the prefix used for pin and parameter names. If the prefix is not specified, the component name is used.
h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)
Then pins are created by calls to methods on the component object. The arguments are: pin name suffix, pin type, and pin direction. For parameters, the arguments are: parameter name suffix, parameter type, and parameter direction.
Pin- und Parametertypen: |
HAL_BIT |
HAL_FLOAT |
HAL_S32 |
HAL_U32 |
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
See Python HAL Interface for an overview of available functions.
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_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