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.
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.)