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