/ docs / src / hal / halmodule.txt
halmodule.txt
  1  [[cha:halmodule]]
  2  
  3  = Creating Userspace Python Components
  4  
  5  == Basic usage
  6  
  7  A userspace component begins by creating its pins and parameters, then
  8  enters a loop which will periodically drive all the outputs from the
  9  inputs. The following component copies the value seen on its input pin
 10  ('passthrough.in') to its output pin ('passthrough.out') approximately
 11  once per second.
 12  
 13  [source,c]
 14  ----
 15  #!/usr/bin/env python
 16  import hal, time
 17  h = hal.component("passthrough")
 18  h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)
 19  h.newpin("out", hal.HAL_FLOAT, hal.HAL_OUT)
 20  h.ready()
 21  try:
 22      while 1:
 23          time.sleep(1)
 24          h['out'] = h['in']
 25  except KeyboardInterrupt:
 26      raise SystemExit
 27  ----
 28  
 29  Copy the above listing into a file named "passthrough", make it
 30  executable ('chmod +x'), and place it on your '$PATH'. Then try it out:
 31  
 32  ----
 33  halrun
 34  
 35  halcmd: loadusr passthrough
 36  
 37  halcmd: show pin
 38  
 39      Component Pins: 
 40      Owner Type  Dir     Value  Name 
 41       03   float IN          0  passthrough.in 
 42       03   float OUT         0  passthrough.out 
 43  
 44  halcmd: setp passthrough.in 3.14 
 45  
 46  halcmd: show pin
 47  
 48      Component Pins: 
 49      Owner Type  Dir     Value  Name 
 50       03   float IN       3.14  passthrough.in 
 51       03   float OUT      3.14  passthrough.out 
 52  ----
 53  
 54  == Userspace components and delays
 55  
 56  If you typed “show pin” quickly, you may see that 'passthrough.out' 
 57  still had its old value of 0. This is because of the call to
 58  'time.sleep(1)', which makes the assignment to the output pin occur at
 59  most once per second. Because this is a userspace component, the actual
 60  delay between assignments can be much longer if the
 61  memory used by the passthrough component is swapped to disk, the
 62  assignment could be delayed until that memory is swapped back in.
 63  
 64  Thus, userspace components are suitable for user-interactive elements
 65  such as control panels (delays in the range of milliseconds are not
 66  noticed, and longer delays are acceptable), but not for sending step
 67  pulses to a stepper driver board (delays must always be in the range of
 68  microseconds, no matter what).
 69  
 70  == Create pins and parameters
 71  
 72  ----
 73  h = hal.component("passthrough")
 74  ----
 75  
 76  The component itself is created by a call to the constructor
 77  'hal.component'. The arguments are the HAL component name and
 78  (optionally) the
 79  prefix used for pin and parameter names. If the prefix is not
 80  specified, the component name is used.
 81  
 82  ----
 83  h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)
 84  ----
 85  
 86  Then pins are created by calls to methods on the component object. The
 87  arguments are: pin name suffix, pin type, and pin direction. For
 88  parameters, the arguments are: parameter name suffix, parameter type,
 89  and parameter direction.
 90  
 91  .HAL Option Names
 92  [width="100%",cols="<3s,4*<"]
 93  |===========================================================
 94  |Pin and Parameter Types: |HAL_BIT |HAL_FLOAT |HAL_S32 |HAL_U32
 95  |Pin Directions:          |HAL_IN  |HAL_OUT   |HAL_IO  |
 96  |Parameter Directions:    |HAL_RO  |HAL_RW    |        |
 97  |===========================================================
 98  
 99  The full pin or parameter name is formed by joining the prefix and the
100  suffix with a ".", so in the example the pin created is called
101  'passthrough.in'.
102  
103  ----
104  h.ready()
105  ----
106  
107  Once all the pins and parameters have been created, call the
108  '.ready()' method.
109  
110  === Changing the prefix
111  
112  The prefix can be changed by calling the '.setprefix()' method. The
113  current prefix can be retrieved by calling the '.getprefix()' method.
114  
115  == Reading and writing pins and parameters
116  
117  For pins and parameters which are also proper Python identifiers, the
118  value may be accessed or set using the attribute syntax:
119  
120  ----
121  h.out = h.in
122  ----
123  
124  For all pins, whether or not they are also proper Python identifiers,
125  the value may be accessed or set using the subscript syntax:
126  
127  ----
128  h['out'] = h['in']
129  ----
130  
131  === Driving output (HAL_OUT) pins
132  
133  Periodically, usually in response to a timer, all HAL_OUT pins should
134  be "driven" by assigning them a new value. This should be done whether
135  or not the value is different than the last one assigned. When a pin is
136  connected to a signal, its old output value is not copied into the
137  signal, so the proper value will only appear on the signal once the
138  component assigns a new value.
139  
140  === Driving bidirectional (HAL_IO) pins
141  
142  The above rule does not apply to bidirectional pins. Instead, a
143  bidirectional pin should only be driven by the component when the
144  component wishes to change the value. For instance, in the canonical
145  encoder interface, the encoder component only sets the 'index-enable'
146  pin to *FALSE* (when an index pulse is seen and the old value is
147  *TRUE*), but never sets it to *TRUE*. Repeatedly driving the pin
148  *FALSE*  might cause the other connected component to act as though
149  another index pulse had been seen. 
150  
151  == Exiting
152  
153  A 'halcmd unload' request for the component is delivered as a 
154  'KeyboardInterrupt' exception. When an unload request arrives, the 
155  process should either 
156  exit in a short time, or call the '.exit()' method on the component 
157  if substantial work (such as reading or 
158  writing files) must be done to complete the shutdown process.
159  
160  == Helpful Functions
161  
162  === component_exists
163  
164  Does the specified component exist at this time. +
165  Example: +
166  hal.component_exists("testpanel") +
167  
168  === component_is_ready
169  Is the specified component ready at this time. +
170  Example: +
171  hal.component_is_ready("testpanel") +
172  
173  === get_msg_level
174  
175  Get the current Realtime msg level. +
176  
177  === set_msg_level
178  
179  set the current Realtime msg level. +
180  used for debugging information. +
181  
182  === connect
183  
184  Connect a pin to a signal. +
185  example: +
186  hal.connect("pinname","signal_name")
187  
188  === get_value
189  
190  read a pin, param or signal directly. +
191  example: +
192  value = hal.get_value("iocontrol.0.emc-enable-in") +
193  
194  === new_signal
195  Create a New signal of the type specified. +
196  example" +
197  hal.new_sig("signalname",hal.HAL_BIT)
198  
199  === pin_has_writer
200  
201  Does the specified pin have a driving pin connected. +
202  Returns True or False. +
203  
204  === sampler_base
205  
206  TODO +
207  
208  === stream_base
209  
210  TODO +
211  
212  === stream
213  
214  TODO +
215  
216  === set_p
217  
218  Set a pin value. +
219  example: +
220  hal.set_p("pinname","10") +
221  
222  == Constants
223  
224  Use These To specify details rather then the value they hold.
225  
226  * HAL_BIT
227  
228  * HAL_FLOAT
229  
230  * HAL_S32
231  
232  * HAL_U32
233  
234  * HAL_IN
235  
236  * HAL_OUT
237  
238  * HAL_RO
239  
240  * HAL_RW
241  
242  * MSG_NONE
243  
244  * MSG_ALL
245  
246  * MSG_DBG
247  
248  * MSG_ERR
249  
250  * MSG_INFO
251  
252  * MSG_WARN
253  
254  == System Information
255  
256  Read these to aquire information about the realtime system.
257  
258  * is_kernelspace
259  
260  * is_rt
261  
262  * is_sim
263  
264  * is_userspace
265  
266  == Project ideas
267  
268  * Create an external control panel with buttons, switches, and
269     indicators. Connect everything to a microcontroller, and connect the
270     microcontroller to the PC using a serial interface. Python has a very
271     capable serial interface module called
272     http://pyserial.sourceforge.net/[pyserial] 
273     (Ubuntu package name “python-serial”, in the universe repository)
274  * Attach a http://lcdproc.omnipotent.net/[LCDProc]-compatible LCD module
275     and use it to display a digital readout with information of your choice
276     (Ubuntu package name “lcdproc”, in the universe repository)
277  * Create a virtual control panel using any GUI library supported by
278     Python (gtk, qt, wxwindows, etc)
279  
280