summaryrefslogtreecommitdiff
path: root/docs/src/hal/rtcomps_es.txt
blob: b911bf7827d9af9400c4779e84e08566c1cd747d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
= HAL Component Descriptions

[[cha:realtime-components]]
(((Realtime Components)))

////
ATTENTION TRANSLATORS before translating this document copy the base document
into this copy to get the latest version. Untranslated documents are not kept
up to date with the English documents. 

Do not translate anchors or links, translate only the text of a link after the
comma.
Anchor [[anchor-name]]
Link <<anchor-name,text after the comma can be translated>>

Make sure the documents build after translating.
////


[[sec:Stepgen]]
== Stepgen(((stepgen)))

This component provides software based generation of step pulses in
response to position or velocity commands. In position mode, it has a
built in pre-tuned position loop, so PID tuning is not required. In
velocity mode, it drives a motor at the commanded speed, while obeying
velocity and acceleration limits. It is a realtime component only, and
depending on CPU speed, etc, is capable of maximum step rates of 10kHz
to perhaps 50kHz. The following figure shows three block diagrams, each is a
single step pulse generator.
The first diagram is for step type '0', (step and direction). The second is
for step type '1' (up/down, or pseudo-PWM), and the third is for step types 2
through 14 (various stepping patterns). The first two diagrams show position
mode control, and the third one shows velocity mode. Control mode and
step type are set independently, and any combination can be selected.

.Step Pulse Generator Block Diagram position mode
(((Stepgen Block Diagram)))

image::images/stepgen-block-diag.png[align="center"]

.Installing

----
halcmd: loadrt stepgen step_type=<type-array> [ctrl_type=<ctrl_array>]
----

'<type-array>' is a series of comma separated decimal integers. Each
number causes a
single step pulse generator to be loaded, the value of the number
 determines the stepping type. '<ctrl_array>' is a comma separated
series of 'p' or 'v' characters, to specify position or velocity
mode. 'ctrl_type' is optional, if ommitted, all of the step generators
will be position
mode. 

For example:
----
halcmd: loadrt stepgen step_type=0,0,2 ctrl_type=p,p,v
----

will install three step generators. The first two use step type '0'
(step and direction) and run in position mode. The last one uses step
type '2' (quadrature) and runs in velocity mode. The default value for
'<config-array>' is '0,0,0' which will install three type '0'
(step/dir) generators. The maximum
number of step generators is 8 (as defined by MAX_CHAN in stepgen.c).
Each generator is independent, but all are updated by the same
 function(s) at the same time. In the following descriptions, '<chan>'
is the number of a specific generator. The first generator is number 0.
(((Stepgen Block Diagram)))
.Removing

----
halcmd: unloadrt stepgen
----

.Pins

Each step pulse generator will have only some of these pins, depending
on the step type and control type selected.

* '(float) stepgen.<chan>.position-cmd' - Desired motor position, in
   position units (position mode only).
* '(float) stepgen.<chan>.velocity-cmd' - Desired motor velocity, in
   position units per second (velocity mode only).
* '(s32) stepgen.<chan>.counts' - Feedback position in counts,
   updated by 'capture_position()'.
* '(float) stepgen.<chan>.position-fb' - Feedback position in
   position units, updated by 'capture_position()'.
* '(bit) stepgen.<chan>.enable' - Enables output steps - when false,
   no steps are generated.
* '(bit) stepgen.<chan>.step' - Step pulse output (step type 0 only).
* '(bit) stepgen.<chan>.dir' - Direction output (step type 0 only).
* '(bit) stepgen.<chan>.up' - UP pseudo-PWM output (step type 1 only).
* '(bit) stepgen.<chan>.down' - DOWN pseudo-PWM output (step type 1 only).
* '(bit) stepgen.<chan>.phase-A' - Phase A output (step types 2-14 only).
* '(bit) stepgen.<chan>.phase-B' - Phase B output (step types 2-14 only).
* '(bit) stepgen.<chan>.phase-C' - Phase C output (step types 3-14 only).
* '(bit) stepgen.<chan>.phase-D' - Phase D output (step types 5-14 only).
* '(bit) stepgen.<chan>.phase-E' - Phase E output (step types 11-14 only).

[[sub:stepgen-parameters]]
.Parameters

* '(float) stepgen.<chan>.position-scale' - Steps per position unit.
   This parameter is used for both output and feedback.
* '(float) stepgen.<chan>.maxvel' - Maximum velocity, in position
   units per second. If 0.0, has no effect.
* '(float) stepgen.<chan>.maxaccel' - Maximum accel/decel rate, in
   positions units per second squared.
   If 0.0, has no effect.
* '(float) stepgen.<chan>.frequency' - The current step rate, in
   steps per second.
* '(float) stepgen.<chan>.steplen' - Length of a step pulse (step
   type 0 and 1) or minimum time in a
   given state (step types 2-14), in nano-seconds.
* '(float) stepgen.<chan>.stepspace' - Minimum spacing between two
   step pulses (step types 0 and 1 only), in nano-seconds. Set to 0 to
   enable the stepgen 'doublefreq' function. To use 'doublefreq' the
   <<sub:parport-functions,parport reset function>> must be enabled.
* '(float) stepgen.<chan>.dirsetup' - Minimum time from a direction
   change to the beginning of the next
   step pulse (step type 0 only), in nanoseconds.
* '(float) stepgen.<chan>.dirhold' - Minmum time from the end of a
   step pulse to a direction change
   (step type 0 only), in nanoseconds.
* '(float) stepgen.<chan>.dirdelay' - Minmum time any step to a step
   in the opposite direction (step
   types 1-14 only), in nano-seconds.
* '(s32) stepgen.<chan>.rawcounts' - The raw feedback count, updated
   by 'make_pulses()'. 

In position mode, the values of maxvel and maxaccel are used by the
internal position loop to avoid generating step pulse trains that the
motor cannot follow. When set to values that are appropriate for the
motor, even a large instantaneous change in commanded position will
result in a smooth trapezoidal move to the new location. The algorithm
works by measuring both position error and velocity error, and
calculating an acceleration that attempts to reduce both to zero at the
same time. For more details, including the contents of the 'control
equation' box, consult the code.

In velocity mode, maxvel is a simple limit that is applied to the
commanded velocity, and maxaccel is used to ramp the actual frequency
if the commanded velocity changes abruptly. As in position mode, proper
values for these parameters ensure that the motor can follow the
generated pulse train.

[[sub:Stepgen-Step-Types]]
.Step Types

.Step Type 0
Step type 0 is the standard step and direction type. When configured for
step type 0, there are four extra parameters that determine the exact
timing of the step and direction signals. In the following figure 
the meaning of these parameters is shown. The
parameters are in nanoseconds, but will be rounded up to an integer
multiple of the thread period for the threaed that calls
'make_pulses()'. For example, if 'make_pulses()' is called every 16 us,
and steplen is 20000, then the step pulses will
be 2 x 16 = 32 us long. The default value for all four of the parameters
is 1ns, but the automatic rounding takes effect the first time the code
 runs. Since one step requires 'steplen' ns high and 'stepspace' ns
low, the maximum frequency is 1,000,000,000 divided by
'(steplen+stepspace)'. If 'maxfreq' is set higher than that limit, it
will be lowered automatically. If
maxfreq is zero, it will remain zero, but the output frequency will
still be limited.

When using the parallel port driver the step frequency can be doubled using
the <<sub:parport-functions,parport reset>> function together with stepgen's
'doublefreq' setting.

[[fig:StepDir-timing]]
.Step and Direction Timing

image::images/stepgen-type0.png[align="center"]

.Step Type 1
Step type 1 has two outputs, up and down. Pulses appear on one or the
other, depending on the direction of travel. Each pulse is 'steplen' ns
long, and the pulses are separated by at least 'stepspace' ns. The
maximum frequency is the same as for step type 0. If 'maxfreq' is set
higher than the limit it will be lowered. If 'maxfreq' is zero, it
will remain zero but the output frequency will still be
limited.

[WARNING]
Do not use the parport reset function with step types 2 - 14. Unexpected
results can happen.

.Step Type 2 - 14
Step types 2 through 14 are state based, and have from two to five
outputs. On each step, a state counter is incremented or decremented.
Figures <<fig:Two-and-Three-Phase,Two-and-Three-Phase>>, <<fig:Four-Phase,Four-Phase>>, and 
<<fig:Five-Phase,Five-Phase>> show the output patterns as a function of the state
counter. The maximum frequency is 1,000,000,000 divided by 'steplen',
and as in the other modes, 'maxfreq' will be lowered if it is above the
limit.

[[fig:Two-and-Three-Phase]]
.Two-and-Three-Phase Step Types
(((Two and Three Phase)))

image::images/stepgen-type2-4.png[align="center"]

[[fig:Four-Phase]]
.Four-Phase Step Types
(((Four Phase)))

image::images/stepgen-type5-10.png[align="center", width=800]

[[fig:Five-Phase]]
.Five-Phase Step Types
(((Five Phase)))

image::images/stepgen-type11-14.png[align="center"]

.Functions

The component exports three functions. Each function acts on all of
the step pulse generators - running different generators in different
threads is not supported.

* '(funct) stepgen.make-pulses' - High speed function to generate
   and count pulses (no floating point).
* '(funct) stepgen.update-freq' - Low speed function does position
   to velocity conversion, scaling and limiting.
* '(funct) stepgen.capture-position' - Low speed function for
   feedback, updates latches and scales position.

The high speed function 'stepgen.make-pulses' should be run in a very
fast thread, from 10 to 50 us depending on the
capabilities of the computer. That thread's period determines the
 maximum step frequency, since 'steplen', 'stepspace', 'dirsetup',
'dirhold', and 'dirdelay' are all rounded up to a integer multiple of
the thread periond in
nanoseconds. The other two functions can be called at a much lower
rate.

[[sec:PWMgen]]
== PWMgen(((pwmgen)))

This component provides software based generation of PWM (Pulse Width
Modulation) and PDM (Pulse Density Modulation) waveforms. It is a
realtime component only, and depending on CPU speed, etc, is capable of
PWM frequencies from a few hundred Hertz at pretty good resolution, to
perhaps 10KHz with limited resolution.

.Installing

----
loadrt pwmgen output_type=<config-array>
----

The '<config-array>' is a series of comma separated decimal integers. Each
number causes a single PWM generator to be loaded, the value of the number
determines the output type. The following example will install three PWM
generators. There is no default value, if '<config-array>' is not specified,
no PWM generators will be installed. The maximum number of frequency generators
is 8 (as defined by MAX_CHAN in pwmgen.c). Each generator is independent,
but all are updated by the same function(s) at the same time. In the following
descriptions, '<chan>' is the number of a specific generator. The first
generator is number 0.

.Example
----
loadrt pwmgen output_type=0,1,2
----

.Removing

----
unloadrt pwmgen
----

.Output Types

The PWM generator supports three different 'output types'.

* 'Output type 0' - PWM output pin only. Only positive commands are accepted,
   negative values are treated as zero (and will be affected by the parameter
   'min-dc' if it is non-zero).

* 'Output type 1' - PWM/PDM and direction pins. Positive and negative inputs
   will be output as positive and negative PWM. The direction pin is false
   for positive commands, and true for negative commands. If your control
   needs positive PWM for both CW and CCW use the <<sub:abs,abs>> component
   to convert your PWM signal to positive value when a negative input is input.

* 'Output type 2' - UP and DOWN pins. For positive commands, the PWM signal
   appears on the up output, and the down output remains false. For negative
   commands, the PWM signal appears on the down output, and the up output
   remains false. Output type 2 is suitable for driving most H-bridges.

.Pins

Each PWM generator will have the following pins:

* '(float) pwmgen.<chan>.value' - Command value, in arbitrary units.
   Will be scaled by the 'scale' parameter (see below).
* '(bit) pwmgen.<chan>.enable' - Enables or disables the PWM
   generator outputs.

Each PWM generator will also have some of these pins, depending on the
output type selected:

* '(bit) pwmgen.<chan>.pwm' - PWM (or PDM) output, (output types 0
   and 1 only).
* '(bit) pwmgen.<chan>.dir' - Direction output (output type 1 only).
* '(bit) pwmgen.<chan>.up' - PWM/PDM output for positive input value
   (output type 2 only).
* '(bit) pwmgen.<chan>.down' - PWM/PDM output for negative input
   value (output type 2 only).

.Parameters

* '(float) pwmgen.<chan>.scale' - Scaling factor to convert 'value'
   from arbitrary units to duty cycle.
* '(float) pwmgen.<chan>.pwm-freq' - Desired PWM frequency, in Hz.
   If 0.0, generates PDM instead of
    PWM. If set higher than internal limits, next call of 'update_freq()'
   will set it to the internal limit. If non-zero, and 'dither' is false,
   next call of 'update_freq()' will set it to the nearest integer
   multiple of the 'make_pulses()' function period.
* '(bit) pwmgen.<chan>.dither-pwm' - If true, enables dithering to
   achieve average PWM frequencies or
   duty cycles that are unobtainable with pure PWM. If false, both the PWM
   frequency and the duty cycle will be rounded to values that can be
   achieved exactly.
* '(float) pwmgen.<chan>.min-dc' - Minimum duty cycle, between 0.0
   and 1.0 (duty cycle will go to
   zero when disabled, regardless of this setting).
* '(float) pwmgen.<chan>.max-dc' - Maximum duty cycle, between 0.0
   and 1.0.
* '(float) pwmgen.<chan>.curr-dc' - Current duty cycle - after all
   limiting and rounding (read only).

.Functions

The component exports two functions. Each function acts on all of the
PWM generators - running different generators in different threads is
not supported.

* '(funct) pwmgen.make-pulses' - High speed function to generate PWM
   waveforms (no floating point).
* '(funct) pwmgen.update' - Low speed function to scale and limit
   value and handle other parameters.

The high speed function 'pwmgen.make-pulses' should be run in a very
fast thread, from 10 to 50 us depending on the
capabilities of the computer. That thread's period determines the
maximum PWM carrier frequency, as well as the resolution of the PWM or
PDM signals. The other function can be called at a much lower rate.

[[sec:Encoder]]
== Encoder(((encoder)))

This component provides software based counting of signals from
quadrature encoders. It is a realtime component only, and depending on
CPU speed, latency, etc, is capable of maximum count rates of 10kHz to
perhaps up to 50kHz.

The base thread should be 1/2 count speed to allow for noise and timing
variation. For example if you have a 100 pulse per revolution encoder on the
spindle and your maximnum RPM is 3000 the maximum base thread should be 25 us.
A 100 pulse per revolution encoder will have 400 counts. The spindle speed
of 3000 RPM = 50 RPS (revolutions per second). 400 * 50 = 20,000 counts per
second or 50 us between counts.

Figure <<fig:Encoder-Block-Diag,Encoder Counter Block Diagram>> is a block
diagram of one channel of encoder counter.

[[fig:Encoder-Block-Diag]]
.Encoder Counter Block Diagram
(((Encoder Block Diagram)))

image::images/encoder-block-diag.png[align="center"]

.Installing

----
halcmd: loadrt encoder [num_chan=<counters>]
----

'<counters>' is the number of encoder counters that you want to
install. If 'numchan' is not specified, three counters will be
installed. The maximum 
number of counters is 8 (as defined by MAX_CHAN in encoder.c). Each
counter is independent, but all are updated by the same function(s) at
 the same time. In the following descriptions, '<chan>' is the number
of a specific counter. The first counter is number 0.

.Removing

----
halcmd: unloadrt encoder
----

.Pins

* 'encoder.<chan>.counter-mode' (bit, I/O) (default: FALSE) - Enables
   counter mode. When true, the
   counter counts each rising edge of the phase-A input, ignoring the
   value on phase-B. This is useful for counting the output of a single
   channel (non-quadrature) sensor. When false, it counts in quadrature
   mode.
* 'encoder.<chan>.counts' (s32, Out) - Position in encoder counts.
* 'encoder.<chan>.counts-latched' (s32, Out) - Not used at this time.
* 'encoder.<chan>.index-enable' (bit, I/O) - When True, 'counts' and
   'position are' reset to zero on next rising edge of Phase Z. At the
   same time, 'index-enable' is reset to zero to indicate that the rising
   edge has occoured. The 'index-enable' pin is bi-directional. If
   'index-enable' is False, the Phase Z channel of the encoder will be
   ignored, and the
    counter will count normally. The encoder driver will never set
   'index-enable' True. However, some other component may do so.
* 'encoder.<chan>.latch-falling' (bit, In) (default: TRUE) - Not used
   at this time.
* 'encoder.<chan>.latch-input' (bit, In) (default: TRUE) - Not used at
   this time.
* 'encoder.<chan>.latch-rising' (bit, In) - Not used at this time.
* 'encoder.<chan>.min-speed-estimate' (float, in) - Determine the
   minimum true velocity magnitude at which
   velocity will be estimated as nonzero and postition-interpolated will
   be interpolated. The units of 'min-speed-estimate' are the same as the
   units of 'velocity' . Scale factor, in counts per length unit. Setting
   this parameter too
   low will cause it to take a long time for velocity to go to 0 after
   encoder pulses have stopped arriving.
* 'encoder.<chan>.phase-A' (bit, In) - Phase A of the quadrature encoder signal.
* 'encoder.<chan>.phase-B' (bit, In) - Phase B of the quadrature encoder signal.
* 'encoder.<chan>.phase-Z' (bit, In) - Phase Z (index pulse) of the quadrature encoder signal.
* 'encoder.<chan>.position' (float, Out) - Position in scaled units (see 'position-scale').
* 'encoder.<chan>.position-interpolated' (float, Out) - Position in
   scaled units, interpolated between
   encoder counts. The 'position-interpolated' attempts to interpolate
   between encoder counts, based on the most
   recently measured velocity. Only valid when velocity is approximately
   constant and above 'min-speed-estimate'. Do not use for position
   control, since its value is incorrect at
   low speeds, during direction reversals, and during speed changes.
   However, it allows a low ppr encoder (including a one pulse per
   revolution 'encoder') to be used for lathe threading, and may have
   other uses as well.
* 'encoder.<chan>.position-latched (float, Out)' - Not used at this time.
* 'encoder.<chan>.position-scale (float, I/O)' - Scale factor, in
   counts per length unit. For example, if
   position-scale is 500, then 1000 counts of the encoder will be reported
   as a position of 2.0 units.
* 'encoder.<chan>.rawcounts (s32, In)' - The raw count, as determined
   by update-counters. This value is
   updated more frequently than counts and position. It is also unaffected
   by reset or the index pulse.
* 'encoder.<chan>.reset' (bit, In) - When True, force 'counts' and
   'position' to zero immediately.
* 'encoder.<chan>.velocity' (float, Out) - Velocity in scaled units per
   second. 'encoder' uses an algorithm that greatly reduces quantization
   noise as compared
   to simply differentiating the 'position' output. When the magnitude
   of the true velocity is below
   min-velocity-estimate, the velocity output is 0.
* 'encoder.<chan>.x4-mode (bit, I/O) (default: TRUE)' - Enables
   times-4 mode. When true, the counter counts each edge of
   the quadrature waveform (four counts per full cycle). When false, it
   only counts once per full cycle. In counter-mode, this parameter is
   ignored. The 1x mode is useful for some jogwheels.

.Parameters

* 'encoder.<chan>.capture-position.time (s32, RO)' 
* 'encoder.<chan>.capture-position.tmax (s32, RW)'
* 'encoder.<chan>.update-counters.time (s32, RO)'
* 'encoder.<chan>.update-counter.tmax (s32, RW)'

.Functions

The component exports two functions. Each function acts on all of the
encoder counters - running different counters in different threads is
not supported.

* '(funct) encoder.update-counters' - High speed function to count
   pulses (no floating point).
* '(funct) encoder.capture-position' - Low speed function to update
   latches and scale position.

[[sec:PID]]
== PID(((pid)))

This component provides Proportional/Integral/Derivative control
loops. It is a realtime component only. For simplicity, this discussion
assumes that we are talking about position loops, however this
component can be used to implement other feedback loops such as speed,
torch height, temperature, etc. Figure <<fig:PID-block-diag,PID Loop Block Diagram>> is a
block diagram of a single PID loop.

[[fig:PID-block-diag]]
.PID Loop Block Diagram
(((PID Block Diagram)))

image::images/pid-block-diag.png[align="center"]

.Installing

----
halcmd: loadrt pid [num_chan=<loops>] [debug=1]
----

'<loops>' is the number of PID loops that you want to install. If
'numchan' is not specified, one loop will be installed. The maximum
number of
loops is 16 (as defined by MAX_CHAN in pid.c). Each loop is completely
 independent. In the following descriptions, '<loopnum>' is the loop
number of a specific loop. The first loop is number 0.

If 'debug=1' is specified, the component will export a few extra
parameters that
may be useful during debugging and tuning. By default, the extra
parameters are not exported, to save shared memory space and avoid
cluttering the parameter list.

.Removing

----
halcmd: unloadrt pid
----

.Pins

The three most important pins are

* '(float) pid.<loopnum>.command' - The desired position, as
   commanded by another system component.
* '(float) pid.<loopnum>.feedback' - The present position, as
   measured by a feedback device such as an encoder.
* '(float) pid.<loopnum>.output' - A velocity command that attempts
   to move from the present position to the desired position. 

For a position loop, 'command' and 'feedback' are in position units.
For a linear axis, this could be inches, mm, meters, or whatever is
relevant. Likewise, for an angular axis, it could be degrees, radians,
etc. The units of the 'output' pin represent the change needed to make
the feedback match the command. As such, for a position loop 'Output'
is a velocity, in inches/sec, mm/sec, degrees/sec, etc. Time units are
always seconds, and the velocity units match the position units. If
command and feedback are in meters, then output is in meters per
second.

Each loop has two pins which are used to monitor or control the
general operation of the component.

* '(float) pid.<loopnum>.error' - Equals '.command' minus '.feedback'.
* '(bit) pid.<loopnum>.enable' - A bit that enables the loop. If
   '.enable' is false, all integrators are reset, and the output is 
   forced to zero. If '.enable' is true, the loop operates normally.

Pins used to report saturation. Saturation occurs when the output of
the PID block is at its maximum or minimum limit.

* '(bit) pid.<loopnum>.saturated' - True when output is saturated.
* '(float) pid.<loopnum>.saturated_s' - The time the output has been saturated. 
* '(s32) pid.<loopnum>.saturated_count' - The time the output has been saturated. 

.Parameters

The PID gains, limits, and other 'tunable' features of the loop are
implemented as parameters.

* '(float) pid.<loopnum>.Pgain' - Proportional gain 
* '(float) pid.<loopnum>.Igain' - Integral gain 
* '(float) pid.<loopnum>.Dgain' - Derivative gain 
* '(float) pid.<loopnum>.bias' - Constant offset on output 
* '(float) pid.<loopnum>.FF0' - Zeroth order feedforward - output
   proportional to command (position).
* '(float) pid.<loopnum>.FF1' - First order feedforward - output
   proportional to derivative of command (velocity).
* '(float) pid.<loopnum>.FF2' - Second order feedforward - output
   proportional to 2nd derivative
   of command (acceleration)footnote:[FF2 is not currently implemented,
   but it will be added. Consider this note a “FIXME” for the code]. 
* '(float) pid.<loopnum>.deadband' - Amount of error that will be ignored 
* '(float) pid.<loopnum>.maxerror' - Limit on error 
* '(float) pid.<loopnum>.maxerrorI' - Limit on error integrator 
* '(float) pid.<loopnum>.maxerrorD' - Limit on error derivative 
* '(float) pid.<loopnum>.maxcmdD' - Limit on command derivative 
* '(float) pid.<loopnum>.maxcmdDD' - Limit on command 2nd derivative 
* '(float) pid.<loopnum>.maxoutput' - Limit on output value

All of the 'max' limits are implemented such that if the parameter
value is zero, there is no limit.

If 'debug=1' was specified when the component was installed, four
additional parameters will be exported:

* '(float) pid.<loopnum>.errorI' - Integral of error.
* '(float) pid.<loopnum>.errorD' - Derivative of error.
* '(float) pid.<loopnum>.commandD' - Derivative of the command.
* '(float) pid.<loopnum>.commandDD' - 2nd derivative of the command. 

.Functions

The component exports one function for each PID loop. This function
performs all the calculations needed for the loop. Since each loop has
its own function, individual loops can be included in different threads
and execute at different rates.

*  '(funct) pid.<loopnum>.do_pid_calcs' - Performs all calculations
   for a single PID loop.

If you want to understand the exact algorithm used to compute the
output of the PID loop, refer to figure <<fig:PID-block-diag,PID Loop Block Diagram>>, the
comments at the beginning of 'emc2/src/hal/components/pid.c' , and of
course to the code itself. The loop calculations are in the C
function 'calc_pid()'.

== Simulated Encoder[[sec:Simulated-Encoder]](((sim-encoder)))

The simulated encoder is exactly that. It produces quadrature pulses
with an index pulse, at a speed controlled by a HAL pin. Mostly useful
for testing.

.Installing

----
halcmd: loadrt sim-encoder num_chan=<number>
----

'<number>' is the number of encoders that you want to simulate. If not
specified, one encoder will be installed. The maximum number is 8 (as
defined by MAX_CHAN in sim_encoder.c).

.Removing

----
halcmd: unloadrt sim-encoder
----

.Pins

* '(float) sim-encoder.<chan-num>.speed' - The speed command for the
   simulated shaft.
* '(bit) sim-encoder.<chan-num>.phase-A' - Quadrature output.
* '(bit) sim-encoder.<chan-num>.phase-B' - Quadrature output.
* '(bit) sim-encoder.<chan-num>.phase-Z' - Index pulse output. 

When '.speed' is positive, '.phase-A' leads '.phase-B'.

.Parameters

* '(u32) sim-encoder.<chan-num>.ppr' - Pulses Per Revolution.
* '(float) sim-encoder.<chan-num>.scale' - Scale Factor for 'speed'.
   The default is 1.0, which means that 'speed' is in revolutions per
   second. Change to 60 for RPM, to 360 for
   degrees per second, 6.283185 for radians per seconed, etc.

Note that pulses per revolution is not the same as counts per
revolution. A pulse is a complete quadrature cycle. Most encoder
counters will count four times during one complete cycle.

.Functions

The component exports two functions. Each function affects all
simulated encoders.

* '(funct) sim-encoder.make-pulses' - High speed function to
   generate quadrature pulses (no floating point).
* '(funct) sim-encoder.update-speed' - Low speed function to read
   'speed', do scaling, and set up 'make-pulses'.

[[sec:Debounce]]
== Debounce(((debounce)))

Debounce is a realtime component that can filter the glitches created
by mechanical switch contacts. It may also be useful in other
applications where short pulses are to be rejected.

.Installing

----
halcmd: loadrt debounce cfg=<config-string>
----

'<config-string>' is a series of comma separated decimal integers.
Each number installs
a group of identical debounce filters, the number determines how many
filters are in the group. 

For example:

----
halcmd: loadrt debounce cfg=1,4,2
----

will install three groups of filters. Group 0 contains one filter,
group 1 contains four, and group 2 contains two filters. The default
value for '<config-string>' is '"1"' which will install a single group
containing a single filter. The
maximum number of groups 8 (as defined by MAX_GROUPS in debounce.c).
The maximum number of filters in a group is limited only by shared
memory space. Each group is completely independent. All filters in a
single group are identical, and they are all updated by the same 
function at the same time. In the following descriptions, '<G>' is the
group number and '<F>' is the filter number within the group. The
first filter is group 0, 
filter 0.

.Removing

----
halcmd: unloadrt debounce
----

.Pins

Each individual filter has two pins.

* '(bit) debounce.<G>.<F>.in' - Input of filter '<F>' in group '<G>'.
* '(bit) debounce.<G>.<F>.out' - Output of filter '<F>' in group '<G>'.

.Parameters

Each group of filters has one parameterfootnote:[Each individual
filter also has an internal state variable. There is a
compile time switch that can export that variable as a parameter. This
is intended for testing, and simply wastes shared memory under normal
circumstances.].

* '(s32) debounce.<G>.delay' - Filter delay for all filters in group '<G>'. 

The filter delay is in units of thread periods. The minimum delay is
zero. The output of a zero delay filter exactly follows its input - it
doesn't filter anything. As 'delay' increases, longer and longer
glitches are rejected. If 'delay' is 4, all glitches less than or
equal to four thread periods will be rejected.

.Functions

Each group of filters has one function, which updates all the filters
in that group 'simultaneously'. Different groups of filters can be
updated from different threads at different periods.

* '(funct) debounce.<G>' - Updates all filters in group '<G>'.

== Siggen[[sec:Siggen]](((siggen)))

Siggen is a realtime component that generates square, triangle, and
sine waves. It is primarily used for testing.

.Installing

----
halcmd: loadrt siggen [num_chan=<chans>]
----

'<chans>' is the number of signal generators that you want to install.
If 'numchan' is not specified, one signal generator will be installed.
The maximum
number of generators is 16 (as defined by MAX_CHAN in siggen.c). Each
 generator is completely independent. In the following descriptions,
'<chan>' is the number of a specific signal generator (the numbers
start at 0).

.Removing

----
halcmd: unloadrt siggen
----

.Pins

Each generator has five output pins.

* '(float) siggen.<chan>.sine' - Sine wave output.
* '(float) siggen.<chan>.cosine' - Cosine output.
* '(float) siggen.<chan>.sawtooth' - Sawtooth output.
* '(float) siggen.<chan>.triangle' - Triangle wave output.
* '(float) siggen.<chan>.square' - Square wave output.

All five outputs have the same frequency, amplitude, and offset.

In addition to the output pins, there are three control pins:

* '(float) siggen.<chan>.frequency' - Sets the frequency in Hertz,
   default value is 1 Hz.
* '(float) siggen.<chan>.amplitude' - Sets the peak amplitude of the
   output waveforms, default is 1.
* '(float) siggen.<chan>.offset' - Sets DC offset of the output
   waveforms, default is 0.

For example, if 'siggen.0.amplitude' is 1.0 and 'siggen.0.offset' is
0.0, the outputs will swing from -1.0 to +1.0. If 'siggen.0.amplitude'
is 2.5 and 'siggen.0.offset' is 10.0, then the outputs will swing from
7.5 to 12.5.

.Parameters

None. footnote:[Prior to version 2.1, frequency, amplitude, and offset
were parameters. They were changed to pins to allow control by other
components.] 

.Functions

* '(funct) siggen.<chan>.update' - Calculates new values for all five outputs. 

[[sec:lut5]]
== lut5(((lut5)))

The lut5 component is a 5 input logic component based on a look up table.

* 'lut5' does not require a floating point thread.

.Installing

----
loadrt lut5 [count=N|names=name1[,name2...]]
addf lut5.N servo-thread | base-thread
setp lut5.N.function 0xN
----

.Computing Function

To compute the hexadecimal number for the function starting from the top put
a 1 or 0 to indicate if that row would be true or false. Next write down every
number in the output column starting from the top and writing them from right
to left. This will be the binary number. Using a calculator with a program
view like the one in Ubuntu enter the binary number and then convert it to
hexadecimal and that will be the value for function.

.Look Up Table
[width="50%",cols="6*^",options="header"]
|====================================
|Bit 4|Bit 3|Bit 2|Bit 1|Bit 0|Output
|0|0|0|0|0|
|0|0|0|0|1|
|0|0|0|1|0|
|0|0|0|1|1|
|0|0|1|0|0|
|0|0|1|0|1|
|0|0|1|1|0|
|0|0|1|1|1|
|0|1|0|0|0|
|0|1|0|0|1|
|0|1|0|1|0|
|0|1|0|1|1|
|0|1|1|0|0|
|0|1|1|0|1|
|0|1|1|1|0|
|0|1|1|1|1|
|1|0|0|0|0|
|1|0|0|0|1|
|1|0|0|1|0|
|1|0|0|1|1|
|1|0|1|0|0|
|1|0|1|0|1|
|1|0|1|1|0|
|1|0|1|1|1|
|1|1|0|0|0|
|1|1|0|0|1|
|1|1|0|1|0|
|1|1|0|1|1|
|1|1|1|0|0|
|1|1|1|0|1|
|1|1|1|1|0|
|1|1|1|1|1|
|====================================

.Two Input Example

In the following table we have selected the output state for each line
that we wish to be true.

.Look Up Table
[width="50%",cols="6*^",options="header"]
|====================================
|Bit 4|Bit 3|Bit 2|Bit 1|Bit 0|Output
|0|0|0|0|0|0
|0|0|0|0|1|1
|0|0|0|1|0|0
|0|0|0|1|1|1
|====================================

Looking at the output column of our example we want the output to be on
when Bit 0 or Bit 0 and Bit1 is on and nothing else. The binary number is
'b1010' (rotate the output 90 degrees CW). Enter this number into the
calculator then change the display to hexadecimal and the number needed for
function is '0xa'. The hexadecimal prefix is '0x'.