/ docs / src / hal / tutorial.txt
tutorial.txt
   1  [[cha:hal-tutorial]]
   2  
   3  = HAL Tutorial
   4  
   5  == Introduction
   6  
   7  Configuration moves from theory to device -- HAL device that is. For
   8  those who have had just a bit of computer programming, this section is
   9  the 'Hello World' of the HAL. Halrun can be used to create a working
  10  system. It is a command line or text file tool for configuration and
  11  tuning. The following examples illustrate its setup and operation.
  12  
  13  === Notation
  14  
  15  Terminal commands are shown without the system prompt unless you are
  16  running 'HAL'. The terminal window is in 'Applications/Accessories'
  17  from the main Ubuntu menu bar.
  18  
  19  .Terminal Command Example
  20  ----
  21  me@computer:~linuxcnc$ halrun
  22  (will be shown like the following line)
  23  halrun
  24  
  25  (the halcmd: prompt will be shown when running HAL)
  26  halcmd: loadrt debounce
  27  halcmd: show pin
  28  ----
  29  
  30  === Tab-completion
  31  
  32  Your version of halcmd may include tab-completion. Instead of
  33  completing file names as a shell does, it completes commands with HAL
  34  identifiers. You will have to type enough letters for a unique match.
  35  Try pressing tab after starting a HAL command:
  36  
  37  .Tab Completion
  38  ----
  39  halcmd: loa<TAB>
  40  halcmd: load
  41  halcmd: loadrt
  42  halcmd: loadrt deb<TAB>
  43  halcmd: loadrt debounce
  44  ----
  45  
  46  === The RTAPI environment
  47  
  48  RTAPI stands for Real Time Application Programming Interface. Many HAL
  49  components work in realtime, and all HAL components store data in
  50  shared memory so realtime components can access it. Normal Linux does
  51  not support realtime programming or the type of shared memory that HAL
  52  needs. Fortunately there are realtime operating systems (RTOS's) that
  53  provide the necessary extensions to Linux. Unfortunately, each RTOS
  54  does things a little differently.
  55  
  56  To address these differences, the LinuxCNC team came up with RTAPI, which
  57  provides a consistent way for programs to talk to the RTOS. If you are
  58  a programmer who wants to work on the internals of LinuxCNC, you may want to
  59  study 'linuxcnc/src/rtapi/rtapi.h' to understand the API. But if you are a
  60  normal person all you need to 
  61  know about RTAPI is that it (and the RTOS) needs to be loaded into the
  62  memory of your computer before you do anything with HAL.
  63  
  64  == A Simple Example
  65  
  66  === Loading a component
  67  
  68  For this tutorial, we are going to assume that you have successfully
  69  installed the Live CD and, if using a RIP footnote:[Run In Place, when the
  70  source files have been downloaded to a user directory.], invoked the 
  71  'rip-environment' script to prepare your shell.
  72  In that case, all you need to do is
  73  load the required RTOS and RTAPI modules into memory. Just run the
  74  following command from a terminal window:
  75  
  76  // NOTE! add link to rip-environment explanation
  77  
  78  .Loading HAL
  79  ----
  80  cd linuxcnc
  81  halrun
  82  halcmd:
  83  ----
  84  
  85  With the realtime OS and RTAPI loaded, we can move into the first
  86  example. Notice that the prompt is now shown as 'halcmd:'.
  87  This is because subsequent commands will be interpreted as HAL commands,
  88  not shell commands.
  89  
  90  For the first example, we will use a HAL component called 'siggen',
  91  which is a simple signal generator. A complete description of the
  92  'siggen' component can be found in the <<sec:siggen,Siggen>> section of
  93  this Manual.
  94  It is a realtime component, implemented as a Linux kernel module. To
  95  load 'siggen' use the HAL command 'loadrt'.
  96  
  97  .Loading siggen
  98  ----
  99  halcmd: loadrt siggen
 100  ----
 101  
 102  === Examining the HAL
 103  
 104  Now that the module is loaded, it is time to introduce 'halcmd' , the
 105  command line tool used to configure the HAL. This tutorial will
 106  introduce some halcmd features, for a more complete description try
 107  'man halcmd', or see the reference in <<sec:hal-commands,Hal Commands>>
 108  section of this document. The first
 109  halcmd feature is the 'show' command. This command displays information
 110  about the current state of the HAL. To show all installed components:
 111  
 112  .Show Components
 113  ----
 114  halcmd: show comp
 115  
 116  Loaded HAL Components:  
 117  ID     Type  Name                                PID   State
 118      3  RT    siggen                                    ready
 119      2  User  halcmd2177                          2177  ready
 120  ----
 121  
 122  Since 'halcmd' itself is a HAL component, it will always show up in
 123  the list. The number after halcmd in the component list is the process ID.
 124  It is possible to run more than one copy of halcmd at the same time (in
 125  different windows for example), so the PID is added to the end of the
 126  name to make it unique. The list also shows the 'siggen' component
 127  that we installed in the previous step. The 'RT' under 'Type' indicates
 128  that 'siggen' is a realtime component. The 'User' under 'Type' indicates
 129  it is a user space component.
 130  
 131  Next, let's see what pins 'siggen' makes available:
 132  
 133  .Show Pins
 134  ----
 135  halcmd: show pin
 136  
 137  Component Pins: 
 138  Owner   Type   Dir        Value  Name 
 139       3  float  IN             1  siggen.0.amplitude
 140       3  bit    OUT        FALSE  siggen.0.clock
 141       3  float  OUT            0  siggen.0.cosine
 142       3  float  IN             1  siggen.0.frequency
 143       3  float  IN             0  siggen.0.offset
 144       3  float  OUT            0  siggen.0.sawtooth
 145       3  float  OUT            0  siggen.0.sine
 146       3  float  OUT            0  siggen.0.square
 147       3  float  OUT            0  siggen.0.triangle
 148  ----
 149  
 150  This command displays all of the pins in the current HAL. A complex system
 151  could have dozens or hundreds of pins. But right now there are only
 152  nine pins. Of these pins eight are floating point and one is bit (boolean).
 153  Six carry data out of the 'siggen' component and three are used to transfer
 154  settings into the component. Since we have not yet executed the code
 155  contained within the component, some the pins have a value of zero.
 156  
 157  The next step is to look at parameters:
 158  
 159  .Show Parameters
 160  ----
 161  halcmd: show param
 162  
 163  Parameters: 
 164  Owner   Type  Dir        Value   Name 
 165       3  s32   RO             0   siggen.0.update.time
 166       3  s32   RW             0   siggen.0.update.tmax
 167  ----
 168  
 169  The 'show param' command shows all the parameters in the HAL. Right now
 170  each parameter has the default value it was given when the component
 171  was loaded. Note the column labeled 'Dir'. The parameters labeled '-W'
 172  are writable ones that are never changed by the component itself,
 173  instead they are meant to be changed by the user to control the
 174   component. We will see how to do this later. Parameters labeled 'R-'
 175  are read only parameters. They can be changed only by the component.
 176   Finally, parameter labeled 'RW' are read-write parameters. That means
 177  that they are changed by the
 178   component, but can also be changed by the user. Note: the parameters
 179  'siggen.0.update.time' and 'siggen.0.update.tmax' are for debugging
 180  purposes, and won't be covered in this section.
 181  
 182  Most realtime components export one or more functions to actually run
 183  the realtime code they contain. Let's see what function(s) 'siggen'
 184  exported:
 185  
 186  .Show Functions
 187  ----
 188  halcmd: show funct
 189  
 190  Exported Functions:
 191  Owner   CodeAddr  Arg       FP   Users  Name 
 192   00003  f801b000  fae820b8  YES      0   siggen.0.update
 193  ----
 194  
 195  The siggen component exported a single function. It requires floating
 196  point. It is not currently linked to any threads, so 'users' is
 197  zero.
 198  
 199  === Making realtime code run
 200  
 201  To actually run the code contained in the function 'siggen.0.update',
 202  we need a realtime thread. The component called 'threads' that is used
 203  to create a new thread. Lets create a thread called 'test-thread' with
 204  a period of 1 ms (1,000 us or 1,000,000 ns):
 205  
 206  ----
 207  halcmd: loadrt threads name1=test-thread period1=1000000
 208  ----
 209  
 210  Let's see if that worked:
 211  
 212  .Show Threads
 213  ----
 214  halcmd: show thread
 215  
 216  Realtime Threads: 
 217       Period  FP     Name               (     Time, Max-Time )
 218       999855  YES           test-thread (        0,        0 )
 219  ----
 220  
 221  It did. The period is not exactly 1,000,000 ns because of hardware
 222  limitations, but we have a thread that runs at approximately the
 223  correct rate, and which can handle floating point functions. The next
 224  step is to connect the function to the thread:
 225  
 226  .Add Function
 227  ----
 228  halcmd: addf siggen.0.update test-thread
 229  ----
 230  
 231  Up till now, we've been using 'halcmd' only to look at the HAL.
 232  However, this time we used the 'addf' (add function) command to
 233  actually change something in the HAL. We
 234  told 'halcmd' to add the function 'siggen.0.update' to the thread
 235  'test-thread', and if we look at the thread list again, we see that it
 236  succeeded:
 237  
 238  ----
 239  halcmd: show thread
 240  
 241  Realtime Threads: 
 242       Period  FP     Name                (     Time, Max-Time )
 243       999855  YES          test-thread   (        0,        0 )
 244                    1 siggen.0.update
 245  ----
 246  
 247  There is one more step needed before the 'siggen' component starts
 248  generating signals. When the HAL is first started,
 249  the thread(s) are not actually running. This is to allow you to
 250  completely configure the system before the realtime code starts. Once
 251  you are happy with the configuration, you can start the realtime code
 252  like this:
 253  
 254  ----
 255  halcmd: start
 256  ----
 257  
 258  Now the signal generator is running. Let's look at its output pins:
 259  
 260  ----
 261  halcmd: show pin
 262  
 263  Component Pins:
 264  Owner   Type  Dir         Value  Name 
 265       3  float IN              1  siggen.0.amplitude
 266       3  bit   OUT         FALSE  siggen.0.clock
 267       3  float OUT    -0.1640929  siggen.0.cosine
 268       3  float IN              1  siggen.0.frequency
 269       3  float IN              0  siggen.0.offset
 270       3  float OUT    -0.4475303  siggen.0.sawtooth
 271       3  float OUT     0.9864449  siggen.0.sine
 272       3  float OUT            -1  siggen.0.square
 273       3  float OUT    -0.1049393  siggen.0.triangle
 274  ----
 275  
 276  And let's look again: 
 277  
 278  ----
 279  halcmd: show pin
 280  
 281  Component Pins:
 282  Owner   Type  Dir         Value  Name
 283       3  float IN              1  siggen.0.amplitude
 284       3  bit   OUT         FALSE  siggen.0.clock
 285       3  float OUT     0.0507619  siggen.0.cosine
 286       3  float IN              1  siggen.0.frequency
 287       3  float IN              0  siggen.0.offset
 288       3  float OUT     -0.516165  siggen.0.sawtooth
 289       3  float OUT     0.9987108  siggen.0.sine
 290       3  float OUT            -1  siggen.0.square
 291       3  float OUT    0.03232994  siggen.0.triangle
 292  ----
 293  
 294  We did two 'show pin' commands in quick succession, and you can see
 295  that the outputs are no longer zero.
 296  The sine, cosine, sawtooth, and triangle outputs are
 297  changing constantly. The square output is also working, however it
 298  simply switches from +1.0 to -1.0 every cycle.
 299  
 300  === Changing Parameters
 301  
 302  The real power of HAL is that you can change things. For example, we
 303  can use the 'setp' command to set the value of a parameter. Let's
 304  change the amplitude
 305  of the signal generator from 1.0 to 5.0:
 306  
 307  .Set Pin
 308  ----
 309  halcmd: setp siggen.0.amplitude 5
 310  ----
 311  
 312  .Check the parameters and pins again
 313  ----
 314  halcmd: show param
 315  
 316  Parameters: 
 317  Owner   Type  Dir         Value  Name
 318       3  s32   RO           1754  siggen.0.update.time
 319       3  s32   RW          16997  siggen.0.update.tmax
 320  
 321  halcmd: show pin
 322  
 323  Component Pins:
 324  Owner   Type  Dir         Value  Name
 325       3  float IN              5  siggen.0.amplitude
 326       3  bit   OUT         FALSE  siggen.0.clock
 327       3  float OUT     0.8515425  siggen.0.cosine
 328       3  float IN              1  siggen.0.frequency
 329       3  float IN              0  siggen.0.offset
 330       3  float OUT      2.772382  siggen.0.sawtooth
 331       3  float OUT     -4.926954  siggen.0.sine
 332       3  float OUT             5  siggen.0.square
 333       3  float OUT      0.544764  siggen.0.triangle
 334  ----
 335  
 336  Note that the value of parameter 'siggen.0.amplitude' has changed to
 337  5, and that the pins now have larger values.
 338  
 339  === Saving the HAL configuration
 340  
 341  Most of what we have done with 'halcmd' so far has simply been viewing
 342  things with the 'show' command. However two of the commands actually
 343  changed things. As we
 344  design more complex systems with HAL, we will use many commands to
 345  configure things just the way we want them. HAL has the memory of an
 346  elephant, and will retain that configuration until we shut it down. But
 347  what about next time? We don't want to manually enter a bunch of
 348  commands every time we want to use the system. We can save the
 349  configuration of the entire HAL with a single command:
 350  
 351  .Save
 352  ----
 353  halcmd: save
 354  # components 
 355  loadrt threads name1=test-thread period1=1000000 
 356  loadrt siggen 
 357  # pin aliases 
 358  # signals 
 359  # nets 
 360  # parameter values 
 361  setp siggen.0.update.tmax 14687 
 362  # realtime thread/function links 
 363  addf siggen.0.update test-thread 
 364  ----
 365  
 366  The output of the 'save' command is a sequence of HAL commands. If
 367  you start with an 'empty'
 368  HAL and run all these commands, you will get the configuration that
 369  existed when the 'save' command was issued. To save these commands
 370  for later use, we simply
 371  redirect the output to a file:
 372  
 373  .Save to a file
 374  ----
 375  halcmd: save all saved.hal
 376  ----
 377  
 378  === Exiting halrun
 379  
 380  When you're finished with your HAL session type 'exit' at the 'halcmd:'
 381  prompt. This will return you to the system prompt and close down the HAL
 382  session. Do not simply close the terminal window without shutting down
 383  the HAL session.
 384  
 385  .Exit HAL
 386  ----
 387  halcmd: exit
 388  ----
 389  
 390  === Restoring the HAL configuration
 391  
 392  To restore the HAL configuration stored in 'saved.hal', we need to
 393  execute all of those HAL commands. To do that, we use '-f <file name>'
 394  which reads commands from a file, and '-I' (upper case i) which shows
 395  the halcmd prompt after executing the commands:
 396  
 397  .Run a Saved File
 398  ----
 399  halrun -I -f saved.hal
 400  ----
 401  
 402  Notice that there is not a 'start' command in saved.hal. It's
 403  necessary to issue it again (or edit saved.hal to add it there).
 404  
 405  === Removing HAL from memory
 406  
 407  If an unexpected shut down of a HAL session occurs you might have to
 408  unload HAL before another session can begin. To do this type the
 409  following command in a terminal window.
 410  
 411  .Removing HAL
 412  ----
 413  halrun -U
 414  ----
 415  
 416  [[sec:tutorial-halmeter]](((Halmeter,Tutorial Halmeter)))
 417  
 418  == Halmeter
 419  
 420  You can build very complex HAL systems without ever using a graphical
 421  interface. However there is something satisfying about seeing the
 422  result of your work. The first and simplest GUI tool for the HAL is
 423  halmeter. It is a very simple program that is the HAL equivalent of the
 424  handy Fluke multimeter (or Simpson analog meter for the old timers).
 425  
 426  We will use the siggen component again to check out halmeter. If you
 427  just finished the previous example, then you can load siggen using the
 428  saved file. If not, we can load it just like we did before:
 429  
 430  ----
 431  halrun
 432  halcmd: loadrt siggen
 433  halcmd: loadrt threads name1=test-thread period1=1000000
 434  halcmd: addf siggen.0.update test-thread
 435  halcmd: start
 436  halcmd: setp siggen.0.amplitude 5
 437  ----
 438  
 439  At this point we have the siggen component loaded and running. It's
 440  time to start halmeter.
 441  
 442  .Starting Halmeter
 443  ----
 444  halcmd: loadusr halmeter
 445  ----
 446  
 447  The first window you will see is the 'Select Item to Probe' window.
 448  
 449  .Halmeter Select Window
 450  
 451  image::images/halmeter-select.png[align="center", alt="Halmeter Select Window"]
 452  
 453  This dialog has three tabs. The first tab displays all of the HAL pins
 454  in the system. The second one displays all the signals, and the third
 455  displays all the parameters. We would like to look at the pin
 456  'siggen.0.cosine' first, so click on it then click the 'Close' button.
 457  The probe
 458  selection dialog will close, and the meter looks something like the
 459  following figure.
 460  
 461  .Halmeter
 462  
 463  image::images/halmeter-1.png[align="center", alt="Halmeter"]
 464  
 465  To change what the meter displays press the 'Select' button which
 466  brings back the 'Select Item to Probe' window.
 467  
 468  You should see the value changing as siggen generates its cosine wave.
 469  Halmeter refreshes its display about 5 times per second.
 470  
 471  To shut down halmeter, just click the exit button.
 472  
 473  If you want to look at more than one pin, signal, or parameter at a
 474  time, you can just start more halmeters. The halmeter window was
 475  intentionally made very small so you could have a lot of them on the
 476  screen at once.
 477  
 478  == Stepgen Example(((stepgen)))
 479  
 480  Up till now we have only loaded one HAL component. But the whole idea
 481  behind the HAL is to allow you to load and connect a number of simple
 482  components to make up a complex system. The next example will use two
 483  components.
 484  
 485  Before we can begin building this new example, we want to start with a
 486  clean slate. If you just finished one of the previous examples, we need
 487  to remove the all components and reload the RTAPI and HAL libraries.
 488  
 489  ----
 490  halcmd: exit
 491  ----
 492  
 493  === Installing the components
 494  
 495  Now we are going to load the step pulse generator component. For a
 496  detailed description of this component refer to the stepgen section of the
 497  Integrator Manual. In this example we will use the 'velocity' control
 498  type of stepgen.  For now, we can skip the details, and just run the
 499  following commands.
 500  
 501  ----
 502  halrun 
 503  halcmd: loadrt stepgen step_type=0,0 ctrl_type=v,v
 504  halcmd: loadrt siggen
 505  halcmd: loadrt threads name1=fast fp1=0 period1=50000 name2=slow period2=1000000
 506  ----
 507  
 508  The first command loads two step generators, both configured to
 509  generate stepping type 0. The second command loads our old friend
 510  siggen, and the third one creates two threads, a fast one with a period
 511  of 50 microseconds and a slow one with a period of 1 millisecond. The fast
 512  thread doesn't support floating point functions.
 513  
 514  As before, we can use 'halcmd show' to take a look at the HAL. This
 515  time we have a lot more pins and parameters than before:
 516  
 517  ----
 518  halcmd: show pin
 519  
 520  Component Pins:
 521  Owner   Type  Dir         Value  Name
 522       4  float IN              1  siggen.0.amplitude
 523       4  bit   OUT         FALSE  siggen.0.clock
 524       4  float OUT             0  siggen.0.cosine
 525       4  float IN              1  siggen.0.frequency
 526       4  float IN              0  siggen.0.offset
 527       4  float OUT             0  siggen.0.sawtooth
 528       4  float OUT             0  siggen.0.sine
 529       4  float OUT             0  siggen.0.square
 530       4  float OUT             0  siggen.0.triangle
 531       3  s32   OUT             0  stepgen.0.counts
 532       3  bit   OUT         FALSE  stepgen.0.dir
 533       3  bit   IN          FALSE  stepgen.0.enable
 534       3  float OUT             0  stepgen.0.position-fb
 535       3  bit   OUT         FALSE  stepgen.0.step
 536       3  float IN              0  stepgen.0.velocity-cmd
 537       3  s32   OUT             0  stepgen.1.counts
 538       3  bit   OUT         FALSE  stepgen.1.dir
 539       3  bit   IN          FALSE  stepgen.1.enable
 540       3  float OUT             0  stepgen.1.position-fb
 541       3  bit   OUT         FALSE  stepgen.1.step
 542       3  float IN              0  stepgen.1.velocity-cmd
 543  
 544  halcmd: show param
 545  
 546  Parameters:
 547  Owner   Type  Dir         Value  Name
 548       4  s32   RO              0  siggen.0.update.time
 549       4  s32   RW              0  siggen.0.update.tmax
 550       3  u32   RW     0x00000001  stepgen.0.dirhold
 551       3  u32   RW     0x00000001  stepgen.0.dirsetup
 552       3  float RO              0  stepgen.0.frequency
 553       3  float RW              0  stepgen.0.maxaccel
 554       3  float RW              0  stepgen.0.maxvel
 555       3  float RW              1  stepgen.0.position-scale
 556       3  s32   RO              0  stepgen.0.rawcounts
 557       3  u32   RW     0x00000001  stepgen.0.steplen
 558       3  u32   RW     0x00000001  stepgen.0.stepspace
 559       3  u32   RW     0x00000001  stepgen.1.dirhold
 560       3  u32   RW     0x00000001  stepgen.1.dirsetup
 561       3  float RO              0  stepgen.1.frequency
 562       3  float RW              0  stepgen.1.maxaccel
 563       3  float RW              0  stepgen.1.maxvel
 564       3  float RW              1  stepgen.1.position-scale
 565       3  s32   RO              0  stepgen.1.rawcounts
 566       3  u32   RW     0x00000001  stepgen.1.steplen
 567       3  u32   RW     0x00000001  stepgen.1.stepspace
 568       3  s32   RO              0  stepgen.capture-position.time
 569       3  s32   RW              0  stepgen.capture-position.tmax
 570       3  s32   RO              0  stepgen.make-pulses.time
 571       3  s32   RW              0  stepgen.make-pulses.tmax
 572       3  s32   RO              0  stepgen.update-freq.time
 573       3  s32   RW              0  stepgen.update-freq.tmax
 574  ----
 575  
 576  === Connecting pins with signals
 577  
 578  What we have is two step pulse generators, and a signal generator. Now
 579  it is time to create some HAL signals to connect the two components. We
 580  are going to pretend that the two step pulse generators are driving the
 581  X and Y axis of a machine. We want to move the table in circles. To do
 582  this, we will send a cosine signal to the X axis, and a sine signal to
 583  the Y axis. The siggen module creates the sine and cosine, but we need
 584  'wires' to connect the modules together. In the HAL, 'wires' are called
 585  signals. We need to create two of them. We can call them anything we
 586  want, for this example they will be 'X-vel' and 'Y-vel'. The signal
 587  'X-vel' is intended to run from the cosine output of the signal
 588  generator to the velocity input of the first step pulse generator. 
 589  The first step is to connect the signal to the signal generator output. 
 590  To connect a signal to a pin we use the net command.
 591  
 592  .net command
 593  ----
 594  halcmd: net X-vel <= siggen.0.cosine
 595  ----
 596  
 597  To see the effect of the 'net' command, we show the signals again.
 598  
 599  ----
 600  halcmd: show sig
 601  
 602  Signals:
 603  Type          Value  Name     (linked to)
 604  float             0  X-vel <== siggen.0.cosine
 605  ----
 606  
 607  When a signal is connected to one or more pins, the show command lists
 608  the pins immediately following the signal name. The 'arrow' shows the
 609  direction of data flow - in this case, data flows from pin
 610  'siggen.0.cosine' to signal 'X-vel'. Now let's connect the 'X-vel' to
 611  the velocity input of a step pulse generator.
 612  
 613  ----
 614  halcmd: net X-vel => stepgen.0.velocity-cmd
 615  ----
 616  
 617  We can also connect up the Y axis signal 'Y-vel'. It is intended to
 618  run from the sine output of the signal generator
 619  to the input of the second step pulse generator. The following command
 620  accomplishes in one line what two 'net' commands accomplished for
 621  'X-vel'.
 622  
 623  ----
 624  halcmd: net Y-vel siggen.0.sine => stepgen.1.velocity-cmd
 625  ----
 626  
 627  Now let's take a final look at the signals and the pins connected to
 628  them.
 629  
 630  ----
 631  halcmd: show sig
 632  
 633  Signals:
 634  Type          Value  Name     (linked to)
 635  float             0  X-vel <== siggen.0.cosine
 636                             ==> stepgen.0.velocity-cmd
 637  float             0  Y-vel <== siggen.0.sine
 638                             ==> stepgen.1.velocity-cmd
 639  ----
 640  
 641  The 'show sig' command makes it clear exactly how data flows through
 642  the HAL. For example, the 'X-vel' signal comes from pin
 643  'siggen.0.cosine', and goes to pin 'stepgen.0.velocity-cmd'.
 644  
 645  === Setting up realtime execution - threads and functions
 646  
 647  Thinking about data flowing through 'wires' makes pins and signals
 648  fairly easy to understand. Threads and functions are a little more
 649  difficult. Functions contain the computer instructions that actually
 650  get things done. Thread are the method used to make those instructions
 651  run when they are needed. First let's look at the functions available
 652  to us.
 653  
 654  ----
 655  halcmd: show funct
 656  
 657  Exported Functions:
 658  Owner   CodeAddr  Arg       FP   Users  Name
 659   00004  f9992000  fc731278  YES      0   siggen.0.update
 660   00003  f998b20f  fc7310b8  YES      0   stepgen.capture-position
 661   00003  f998b000  fc7310b8  NO       0   stepgen.make-pulses
 662   00003  f998b307  fc7310b8  YES      0   stepgen.update-freq
 663  ----
 664  
 665  In general, you will have to refer to the documentation for each
 666  component to see what its functions do. In this case, the function
 667  'siggen.0.update' is used to update the outputs of the signal
 668  generator. Every time it is executed, it calculates the values of
 669  the sine, cosine, triangle, and square outputs. To make smooth
 670  signals, it needs to run at specific intervals.
 671  
 672  The other three functions are related to the step pulse generators.
 673  
 674  The first one, 'stepgen.capture_position', is used for position
 675  feedback. It captures the value of an internal
 676  counter that counts the step pulses as they are generated. Assuming no
 677  missed steps, this counter indicates the position of the motor.
 678  
 679  The main function for the step pulse generator is
 680  'stepgen.make_pulses'. Every time 'make_pulses' runs it decides if it
 681  is time to take a step, and if so sets the
 682  outputs accordingly. For smooth step pulses, it should run as
 683  frequently as possible. Because it needs to run so fast, 'make_pulses'
 684  is highly optimized and performs only a few calculations. Unlike the
 685  others, it does not need floating point math.
 686  
 687  The last function, 'stepgen.update-freq', is responsible for doing 
 688  scaling and some other calculations that need to be performed 
 689  only when the frequency command changes.
 690  
 691  What this means for our example is that we want to run
 692  'siggen.0.update' at a moderate rate to calculate the sine and cosine
 693  values. Immediately after we run 'siggen.0.update', we want to run
 694  'stepgen.update_freq' to load the new values into the step pulse
 695  generator. Finally we need
 696   to run 'stepgen.make_pulses' as fast as possible for smooth pulses.
 697  Because we don't use position
 698  feedback, we don't need to run 'stepgen.capture_position' at all.
 699  
 700  We run functions by adding them to threads. Each thread runs at a
 701  specific rate. Let's see what threads we have available.
 702  
 703  ----
 704  halcmd: show thread
 705  
 706  Realtime Threads:
 707       Period  FP     Name               (     Time, Max-Time )
 708       996980  YES                  slow (        0,        0 )
 709        49849  NO                   fast (        0,        0 )
 710  ----
 711  
 712  The two threads were created when we loaded 'threads'. The first one,
 713  'slow', runs every millisecond, and is capable of running floating
 714  point functions. We will use it for 'siggen.0.update' and
 715  'stepgen.update_freq'. The second thread is 'fast', which runs every
 716  50 microseconds, and does not support floating point.
 717  We will use it for 'stepgen.make_pulses'. To connect the
 718  functions to the proper thread, we use the 'addf' command.
 719  We specify the function first, followed by the thread.
 720  
 721  ----
 722  halcmd: addf siggen.0.update slow
 723  halcmd: addf stepgen.update-freq slow
 724  halcmd: addf stepgen.make-pulses fast
 725  ----
 726  
 727  After we give these commands, we can run the 'show thread' command
 728  again to see what happened.
 729  
 730  ----
 731  halcmd: show thread
 732  
 733  Realtime Threads:
 734       Period  FP     Name               (     Time, Max-Time )
 735       996980  YES                  slow (        0,        0 )
 736                    1 siggen.0.update
 737                    2 stepgen.update-freq
 738        49849  NO                   fast (        0,        0 )
 739                    1 stepgen.make-pulses
 740  ----
 741  
 742  Now each thread is followed by the names of the functions, in the
 743  order in which the functions will run.
 744  
 745  === Setting parameters
 746  
 747  We are almost ready to start our HAL system. However we still need to
 748  adjust a few parameters. By default, the siggen component generates
 749  signals that swing from +1 to -1. For our example that is fine, we want
 750  the table speed to vary from +1 to -1 inches per second. However the
 751  scaling of the step pulse generator isn't quite right. By default, it
 752  generates an output frequency of 1 step per second with an input of
 753  1.000. It is unlikely that one step per second will give us one inch
 754  per second of table movement. Let's assume instead that we have a 5
 755  turn per inch leadscrew, connected to a 200 step per rev stepper with
 756  10x microstepping. So it takes 2000 steps for one revolution of the
 757  screw, and 5 revolutions to travel one inch. that means the overall
 758  scaling is 10000 steps per inch. We need to multiply the velocity input
 759  to the step pulse generator by 10000 to get the proper output. That is
 760  exactly what the parameter 'stepgen.n.velocity-scale' is for. In this
 761  case, both the X and Y axis have the same scaling, so
 762  we set the scaling parameters for both to 10000.
 763  
 764  ----
 765  halcmd: setp stepgen.0.position-scale 10000
 766  halcmd: setp stepgen.1.position-scale 10000
 767  halcmd: setp stepgen.0.enable 1
 768  halcmd: setp stepgen.1.enable 1
 769  ----
 770  
 771  This velocity scaling means that when the pin 'stepgen.0.velocity-cmd'
 772  is 1.000, the step generator will generate 10000 pulses per second
 773  (10KHz). With the motor and leadscrew described above, that will result
 774  in the axis moving at exactly 1.000 inches per second. This illustrates
 775  a key HAL concept - things like scaling are done at the lowest possible
 776  level, in this case in the step pulse generator. The internal signal
 777  'X-vel' is the velocity of the table in inches per second, and other
 778  components such as 'siggen' don't know (or care) about the scaling at
 779  all. If we changed the leadscrew, or motor, we would change only the
 780  scaling parameter of the step pulse generator.
 781  
 782  === Run it!
 783  
 784  We now have everything configured and are ready to start it up. Just
 785  like in the first example, we use the 'start' command.
 786  
 787  ----
 788  halcmd: start
 789  ----
 790  
 791  Although nothing appears to happen, inside the computer the step pulse
 792  generator is cranking out step pulses, varying from 10KHz forward to
 793  10KHz reverse and back again every second. Later in this tutorial we'll
 794  see how to bring those internal signals out to run motors in the real
 795  world, but first we want to look at them and see what is happening.
 796  
 797  [[sec:tutorial-halscope]](((Tutorial Halscope)))
 798  
 799  == Halscope
 800  
 801  The previous example generates some very interesting signals. But much
 802  of what happens is far too fast to see with halmeter. To take a closer
 803  look at what is going on inside the HAL, we want an oscilloscope.
 804  Fortunately HAL has one, called halscope.
 805  
 806  Halscope has two parts - a realtime part that is loaded as a kernel
 807  module, and a user part that supplies the GUI and display. However, you
 808  don't need to worry about this, because the userspace portion will
 809  automatically request that the realtime part be loaded. Also notice
 810  the first time you run halscope in a directory it gives a benign
 811  message that the file 'autosave.halscope' could not be opened.
 812  
 813  .Starting Halscope
 814  ----
 815  halcmd: loadusr halscope
 816  halcmd: halscope: config file 'autosave.halscope' could not be opened
 817  ----
 818  
 819  The scope GUI window will open, immediately followed by a
 820  'Realtime function not linked' dialog that looks like the following
 821  figure.
 822  
 823  .Realtime function not linked dialog
 824  
 825  image::images/halscope-01.png[align="center", alt="Realtime function not linked dialog"]
 826  
 827  This dialog is where you set the sampling rate for the oscilloscope.
 828  For now we want to sample once per millisecond, so click on the 989 us
 829  thread 'slow' and leave the multiplier at 1. We will also leave the
 830  record length at 4000 samples, so that we can use up to four channels
 831  at one time. When you select a thread and then click 'OK', the dialog
 832  disappears, and the scope window looks something like the following
 833  figure.
 834  
 835  .Initial scope window
 836  
 837  image::images/halscope-02.png[align="center", alt="Initial scope window"]
 838  
 839  === Hooking up the scope probes
 840  
 841  At this point, Halscope is ready to use. We have already selected a
 842  sample rate and record length, so the next step is to decide what to
 843  look at. This is equivalent to hooking 'virtual scope probes' to the
 844  HAL. Halscope has 16 channels, but the number you can use at any one
 845  time depends on the record length - more channels means shorter
 846  records, since the memory available for the record is fixed at
 847  approximately 16,000 samples.
 848  
 849  The channel buttons run across the bottom of the halscope screen.
 850  Click button '1', and you will see the 'Select Channel Source' dialog
 851  as shown in the following figure. This dialog is very similar to the
 852  one used by Halmeter. We would like to look at the signals we defined
 853  earlier, so we click on the 'Signals' tab, and the dialog displays all
 854  of the signals in the HAL (only two for this example).
 855  
 856  .Select Channel Source
 857  
 858  image::images/halscope-03.png[align="center", alt="Select Channel Source"]
 859  
 860  To choose a signal, just click on it. In this case, we want channel 1
 861  to display the signal 'X-vel'. Click on the Signals tab then click on
 862  'X-vel' and the dialog closes and the channel is now selected.
 863  
 864  .Select Signal
 865  
 866  image::images/halscope-04.png[align="center", alt="Select Signal"]
 867  
 868  The channel 1 button is pressed in, and channel number 1 and the name
 869  'X-vel' appear below the row of buttons. That display always indicates
 870  the selected channel - you can have many channels on the screen, but
 871  the selected one is highlighted, and the various controls like vertical
 872  position and scale always work on the selected one.
 873  
 874  .Halscope
 875  
 876  image::images/halscope-05.png[align="center", alt="Halscope"]
 877  
 878  To add a signal to channel 2, click the '2' button. When the dialog
 879  pops up, click the 'Signals' tab, then click on 'Y-vel'. We also want
 880  to look at the square and triangle wave outputs. There are no signals
 881  connected to those pins, so we use the 'Pins' tab instead. For channel
 882  3, select 'siggen.0.triangle' and for channel 4, select
 883  'siggen.0.square'.
 884  
 885  === Capturing our first waveforms
 886  
 887  Now that we have several probes hooked to the HAL, it's time to
 888  capture some waveforms. To start the scope, click the 'Normal' button
 889  in the 'Run Mode' section of the screen (upper right). Since we have a
 890  4000 sample record length, and are acquiring 1000 samples per second,
 891  it will take halscope about 2 seconds to fill half of its buffer.
 892  During that time a progress bar just above the main screen will show
 893  the buffer filling. Once the buffer is half full, the scope waits for a
 894  trigger. Since we haven't configured one yet, it will wait forever. To
 895  manually trigger it, click the 'Force' button in the 'Trigger' section
 896  at the top right. You should see the remainder of the buffer fill, then
 897  the screen will display the captured waveforms. The result will look
 898  something like the following figure.
 899  
 900  .Captured Waveforms
 901  
 902  image::images/halscope-06.png[align="center", alt="Captured Waveforms"]
 903  
 904  The 'Selected Channel' box at the bottom tells you that the purple
 905  trace is the currently selected one, channel 4, which is displaying the
 906  value of the pin 'siggen.0.square'. Try clicking channel buttons 1
 907  through 3 to highlight the other three traces.
 908  
 909  === Vertical Adjustments
 910  
 911  The traces are rather hard to distinguish since all four are on top of
 912  each other. To fix this, we use the 'Vertical' controls in the box to
 913  the right of the screen. These controls act on the currently selected
 914  channel. When adjusting the gain, notice that it covers a huge range -
 915  unlike a real scope, this one can display signals ranging from very
 916  tiny (pico-units) to very large (Tera-units). The position control
 917  moves the displayed trace up and down over the height of the screen
 918  only. For larger adjustments the offset button should be used.
 919  
 920  .Vertical Adjustment
 921  
 922  image::images/halscope-07.png[align="center", alt="Vertical Adjustment"]
 923  
 924  === Triggering
 925  
 926  Using the 'Force' button is a rather unsatisfying way to trigger the
 927  scope. To set up real triggering, click on the 'Source' button at the
 928  bottom right. It will pop up the 'Trigger Source' dialog, which is
 929  simply a list of all the probes that are currently connected. Select a
 930  probe to use for triggering by clicking on it. For this example we will
 931  use channel 3, the triangle wave as shown in the following figure.
 932  
 933  .Trigger Source Dialog
 934  
 935  image::images/halscope-08.png[align="center", alt="Trigger Source Dialog"]
 936  
 937  After setting the trigger source, you can adjust the trigger level and
 938  trigger position using the sliders in the 'Trigger' box along the right
 939  edge. The level can be adjusted from the top to the bottom of the
 940  screen, and is displayed below the sliders. The position is the
 941  location of the trigger point within the overall record. With the
 942  slider all the way down, the trigger point is at the end of the record,
 943  and halscope displays what happened before the trigger point. When the
 944  slider is all the way up, the trigger point is at the beginning of the
 945  record, displaying what happened after it was triggered. The trigger
 946  point is visible as a vertical line in the progress box above the
 947  screen. The trigger polarity can be changed by clicking the button just
 948  below the trigger level display.
 949  
 950  Now that we have adjusted the vertical controls and triggering, the 
 951  scope display looks something like the following figure.
 952  
 953  .Waveforms with Triggering
 954  
 955  image::images/halscope-09.png[align="center", alt="Waveforms with Triggering"]
 956  
 957  === Horizontal Adjustments
 958  
 959  To look closely at part of a waveform, you can use the zoom slider at
 960  the top of the screen to expand the waveforms horizontally, and the
 961  position slider to determine which part of the zoomed waveform is
 962  visible. However, sometimes simply expanding the waveforms isn't enough
 963  and you need to increase the sampling rate. For example, we would like
 964  to look at the actual step pulses that are being generated in our
 965  example. Since the step pulses may be only 50 us long, sampling at 1KHz
 966  isn't fast enough. To change the sample rate, click on the button that
 967  displays the number of samples and sample rate to bring up the 'Select
 968  Sample Rate' dialog, figure . For this example, we will click on the
 969  50 us thread, 'fast', which gives us a sample rate of about 20KHz. Now
 970  instead of displaying about 4 seconds worth of data, one record is 4000
 971  samples at 20KHz, or about 0.20 seconds.
 972  
 973  .Sample Rate Dialog
 974  
 975  image::images/halscope-10.png[align="center", alt="Sample Rate Dialog"]
 976  
 977  === More Channels
 978  
 979  Now let's look at the step pulses. Halscope has 16 channels, but for
 980  this example we are using only 4 at a time. Before we select any more
 981  channels, we need to turn off a couple. Click on the channel 2 button,
 982  then click the 'Chan Off' button at the bottom of the 'Vertical' box.
 983  Then click on channel 3, turn if off, and do the same for channel 4.
 984  Even though the channels are turned off, they still remember what they
 985  are connected to, and in fact we will continue to use channel 3 as the
 986  trigger source. To add new channels, select channel 5, and choose pin
 987  'stepgen.0.dir', then channel 6, and select 'stepgen.0.step'. Then
 988  click run mode 'Normal' to start the scope, and adjust the horizontal
 989  zoom to 5 ms per division. You should see the step pulses slow down as
 990  the velocity command (channel 1) approaches zero, then the direction
 991  pin changes state and the step pulses speed up again. You might want to
 992  increase the gain on channel 1 to about 20 milli per division to better see
 993  the change in the velocity command. The result should look like  the
 994  following figure.
 995  
 996  .Step Pulses
 997  
 998  image::images/halscope-11.png[align="center", alt="Step Pulses"]
 999  
1000  === More samples
1001  
1002  If you want to record more samples at once, restart realtime and load
1003  halscope with a numeric argument which indicates the number of samples
1004  you want to capture.
1005  
1006  ----
1007  halcmd: loadusr halscope 80000
1008  ----
1009  
1010  If the 'scope_rt' component was not already loaded, halscope will
1011  load it and request 80000 total samples, so that when sampling 
1012  4 channels at a time there will be 20000 samples per channel. 
1013  (If 'scope_rt' was already loaded, the numeric argument to 
1014  halscope will have no effect).
1015