1. Uso Básico

Un componente de espacio de usuario comienza creando sus pines y parámetros. Luego entra en un bucle que manejara periódicamente todas las salidas segun las entradas. El siguiente componente copia el valor visto en su pin de entrada (passthrough.in) a su pin de salida (passthrough.out) aproximadamente una vez por segundo.

#!/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

Copie el listado anterior en un archivo llamado "passthrough", hágalo ejecutable (chmod +x), y colóquelo en su $PATH. Luego, pruébelo:

Halrun

halcmd: loadusr passthrough

halcmd: show pin

    Component Pins:
    Owner Type  Dir     Value  Name
     03   float IN          0  passthrough.in
     03   float OUT         0  passthrough.out

halcmd: setp passthrough.in 3.14

halcmd: show pin

    Component Pins:
    Owner Type  Dir     Value  Name
     03   float IN       3.14  passthrough.in
     03   float OUT      3.14  passthrough.out

2. Componentes de espacio de usuario y retrasos

Si escribió el segundo "show pin" rápidamente, puede ver que passthrough.out todavía tenía su valor anterior de 0. Esto se debe a la llamada a time.sleep(1), que hace que la asignación al pin de salida ocurra al menos una vez por segundo. Como este es un componente de espacio de usuario, la demora real entre asignaciones puede ser mucho más larga si la memoria utilizada por el componente passthrough se intercambia en el disco; la asignación se puede retrasar hasta que la memoria se intercambie nuevamente.

Por lo tanto, los componentes del espacio de usuario son adecuados para elementos interactivos con el usuario como los paneles de control (los retrasos en el rango de milisegundos no seran notados, y son aceptables demoras más largas), pero no para enviar pulsos de paso a una placa de control paso a paso (los retrasos siempre deben estar en el rango de microsegundos).

3. Crear pines y parámetros

h = hal.component("passthrough")

El componente en sí es creado por una llamada al constructor hal.component. Los argumentos son el nombre del componente HAL y (opcionalmente) el prefijo utilizado para los nombres de los pines y los parámetros. Si el prefijo no se especifica, se usa el nombre del componente.

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

Los pines se crean mediante llamadas a métodos en el objeto componente. Los argumentos son: sufijo del nombre del pin, tipo de pin y dirección del pin. Para parámetros, los argumentos son: sufijo del nombre del parámetro, tipo de parámetro, y dirección del parámetro.

Tabla 1. Nombres de la opción .HAL

Tipos Pines y Parametros:

HAL_BIT

HAL_FLOAT

HAL_S32

HAL_U32

Direcciones de Pin:

HAL_IN

HAL_OUT

HAL_IO

Direcciones de Parametros:

HAL_RO

HAL_RW

El nombre completo del pin o parámetro se forma uniendo el prefijo y el sufijo con un ".", por lo que en el ejemplo, el pin creado se llama passthrough.in.

h.ready()

Una vez que se hayan creado todos los pines y parámetros, llame al método .ready().

3.1. Cambiar el Prefijo

El prefijo se puede cambiar llamando al método .setprefix(). Los prefijo actuales se puede recuperar llamando al método .getprefix().

4. Lectura y Escritura de Pines y Parámetros

Para los pines y parámetros que también sean identificadores adecuados de Python, el valor puede ser accedido o establecido usando la sintaxis de atributo:

h.out = h.in

Para todos los pines, sean o no identificadores adecuados de Python, el valor puede ser accedido o establecido usando la sintaxis de subíndice:

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

4.1. Manejo de Pines de Salida (HAL_OUT)

Periódicamente, generalmente en respuesta a un temporizador, todos los pines HAL_OUT deben ser "manejados" al asignarles un nuevo valor. Esto debe hacerse, sea o no el valor diferente al último asignado. Cuando un pin es conectado a una señal, su valor de salida anterior no se copia en la señal, por lo que el valor correcto solo aparecerá en la señal una vez que el componente asigna un nuevo valor.

4.2. Manejo de pines bidireccionales (HAL_IO)

La regla anterior no se aplica a los pines bidireccionales. En cambio, un pin bidireccional solo debe ser manejado por el componente cuando el componente desea cambiar el valor. Por ejemplo, en el interfaz canónico de encoder, el componente solo establece el pin index-enable a FALSE (cuando se produce un pulso de índice y el valor anterior es TRUE), pero nunca, por si mismo, lo establece en TRUE. Llevando repetidamente el pin a FALSE puede hacer que el otro componente conectado actúe como si hubiese sido visto otro impulso de índice.

5. Salida

Una solicitud halcmd unload para el componente se entrega como una excepción KeyboardInterrupt. Cuando llega una solicitud de descarga, el proceso debe o bien salir en poco tiempo o llamar al método .exit() en el componente, si un trabajo sustancial (como lectura o escritura de archivos) debe hacerse para completar el proceso de apagado.

6. Funciones útiles

6.1. component_exists

Existencia del componente especificado en este momento
Ejemplo:
hal.component_exists("testpanel")

6.2. component_is_ready

Componente especificado listo en este momento
Ejemplo:
hal.component_is_ready("testpanel")

6.3. get_msg_level

Nivel msg de tiempo real actual.

6.4. set_msg_level

Establecer nivel msg de tiempo real.
usado para informacion de depuracion.

6.5. connect

Conecta un pin a una señal.
ejemplo:
hal.connect("pinname","signal_name")

6.6. get_value

leer pin, parametro o señal directamente.
ejemplo:
value = hal.get_value("iocontrol.0.emc-enable-in")

6.7. new_signal

Crea una nueva señal del tipo especificado.
ejemplo "+ hal.new_sig("nombre-de-la-señal",hal.HAL_BIT)

6.8. pin_has_writer

El pin especificado tiene un pin de manejo conectado
Devuelve verdadero o falso.
h.in.pin_has_writer()

6.9. get_name

Obtener nombre de objeto HAL
h.in.get_name()
devuelve una cadena

6.10. get_type

Obtener tipo de objeto HAL
h.in.get_type()
devuelve un entero

6.11. get_dir

Obtener tipo de direccion de objeto HAL
h.in.get_dir()
devuelve un entero

6.12. get

Obtener valor del objeto HAL
h.in.get()

6.13. set

Establecer valor del objeto HAL
h.out.set(10)

6.14. is_pin

el objeto es pin o parametro?
h.in.is_pin()
devuelve bool

6.15. sampler_base

TODO

6.16. stream_base

TODO

6.17. stream

TODO

6.18. set_p

Establecer un valor en cualquier pin HAL.
ejemplo:
hal.set_p("pinname","10")

7. Constantes

Úselas para especificar detalles con el valor que representan.

  • 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. Información del sistema

Leer estas variables para obtener información sobre el sistema en tiempo real.

  • is_kernelspace

  • is_rt

  • is_sim

  • is_userspace

9. Usar con hal_glib en el handler GladeVCP

GladeVCP usa la biblioteca hal_glib, que puede usarse para conectar una señal "observador" en un pin de entrada HAL.
Esta señal se puede usar para registrar una función a llamar cuando el pin HAL cambia de estado.

Uno debe importar el módulo y el módulo hal:

import hal_glib
import hal

Luego haga un pin y conecte una señal value-changed (el observador) a una llamada de función:

class HandlerClass:
    def __init__(self, halcomp,builder,useropts):
        self.example_trigger = hal_glib.GPin(halcomp.newpin('example-trigger', hal.HAL_BIT, hal.HAL_IN))
        self.example_trigger.connect('value-changed', self._on_example_trigger_change)

Y tener una función que se llamará:

    def _on_example_trigger_change(self,pin,userdata=None):
        print "pin value changed to:" % (pin.get())
        print "pin name= %s" % (pin.get_name())
        print "pin type= %d" % (pin.get_type())

        # esto se puede llamar fuera de la función
        self.example_trigger.get()

10. Usar con hal_glib en el handler QtVCP

QtVCP usa la biblioteca hal_glib, que puede usarse para conectar una señal "observador" en un pin de entrada HAL.
Esta señal se puede usar para registrar una función a llamar cuando el pin HAL cambia de estado.

Uno debe importar el módulo hal:

import hal

Luego haga un pin y conecte una señal value_changed (el observador) a una llamada de función:

    ########################
    # **** INICIALIZAR **** #
    ########################
    # widgets permite el acceso a widgets desde los archivos qtvcp
    # en este punto, los widgets y los pines hal no están instanciados
    def __init__(self, halcomp,widgets,paths):
        self.hal = halcomp
        self.testPin = self.hal.newpin('test-pin', hal.HAL_BIT, hal.HAL_IN)
        self.testPin.value_changed.connect(lambda s: self.setTestPin(s))

Y tener una función que se llamará.
Esto muestra formas de obtener el valor y la información del pin.

    #######################
    # funciones generales #
    #######################
    def setTestPin(self, data):
        print "Test pin value changed to:" % (data)
        print 'halpin object =', self.w.sender()
        print 'Halpin name: ',self.sender().text()
        print 'Halpin type: ',self.sender().get_type()

        # esto se puede llamar fuera de la función
        print self.testPin.get()

11. Ideas de proyectos

  • Crea un panel de control externo con botones, interruptores y indicadores. Conecte todo a un microcontrolador, y conecte el microcontrolador a la PC con una interfaz serie. Python tiene un muy eficaz módulo de interfaz serie llamado pyserial (Nombre del paquete de Ubuntu "python-serial", en el repositorio universo)

  • Adjunte un módulo LCD compatible con LCDProc- y úselo para mostrar una lectura digital con la información que elija (Nombre del paquete de Ubuntu "lcdproc", en el repositorio universo)

  • Crear un panel de control virtual utilizando cualquier biblioteca GUI compatible con Python (gtk, qt, wxwindows, etc.)