The Auto Servo Tuning of linuxcncMulti is modelled on the AST of the SINUMERIK (HMI Operate, "Automat. Servo Optim."): the frequency responses of a servo axis are measured with a function generator and the position controller of LinuxCNC is optimised on them. The SINUMERIK owns the whole cascade - current, speed and position controller - in its drives. LinuxCNC owns the position controller (pid: P as the Kv factor, FF1 and FF2 as the velocity and acceleration feedforward) and the setpoint filters in HAL; the speed loop is closed in the drive (an analog velocity drive, a CSV drive on EtherCAT) and is measured as the plant "velocity setpoint → actual velocity", the current loop stays the drive’s own.

This chapter describes the first stage, the measurement. The evaluation of the position loop with the strategies, the page in mchmi and the EtherCAT part follow in the next stages (docs/multichannel/ast.md).

The function generator: mcast

mcast (loadrt mcast count=N, one instance per joint) sits between the position controller and the drive:

net u        pid.x.output      => mcast.0.cmd-in
net drive-in mcast.0.input-out => hm2_5i25.0.7i77.0.1.analogout0   # or the CSV setpoint
net pos-fb   ...               => mcast.0.pos-fb                    # the joint's feedback

The controller’s output enters on cmd-in, the excitation is added and the sum leaves on input-out. Nothing changes while no run is active: the excitation is 0 and the sum equals the controller’s output. A run starts with the rising edge of enable and lasts duration seconds; its signal is selected by mode:

mode signal

1

band-limited pseudo-random noise: chips at 2 f-max, low-passed at f-max, high-passed at f-min so that a velocity drive does not drift

2

a logarithmic sine sweep (chirp) from f-min to f-max

3

a step: 0 for half a second, then amplitude

4

a sine at f-min

The amplitude ramps in and out over ramp seconds. The travel guard is the safety of the measurement: when the joint leaves its start position by more than travel-limit the excitation goes to 0 in the same servo cycle, fault = 1 and the run ends; a falling enable ends a run with fault = 2. running, done, progress and travel report the run; inject-out, input-out and vel-out (the velocity, vel-fb with use-vel-fb = 1 or derived from pos-fb) are what the recorder stores.

With open-loop = 1 the controller’s output is not passed on during a run: the position loop is open and the axis is "free", as in the SINUMERIK’s measurement of the speed loop. The default keeps the loop closed - the controller holds the axis, the excitation acts as a disturbance, and the plant is computed from the measured response and the controller’s known gains (below). That is the recommended way: the axis does not drift and nothing jumps when the run ends.

The measurement and its evaluation

mcast-measure runs one measurement from the console against the running HAL (the machine or a simulation):

mcast-measure --instance mcast.0 --pid pid.x --mode prbs --amplitude 2 \
              --f-min 1 --f-max 200 --duration 10 --travel-limit 1 --out x_ast.json

It sets the instance’s parameters, records the excitation, the controller’s output, the plant input, the velocity and the position at the servo rate (through sampler, like the circularity test), enables the run, waits for its end and prints the evaluation: the static gain, the bandwidth, the resonances found and the coherence; --out writes the AST file (JSON: settings, the controller’s gains, all samples, the responses in dB and degrees) for the later stages and for an offline look.

The evaluation (lib/python/mcast.py, numpy) estimates the frequency response by the Welch cross-spectrum (H1 = Syu / Suu with the coherence) in the band of the excitation. The plant is the direct estimate from the drive’s input - the controller’s output plus the excitation - to the velocity: y = G u holds with the position loop closed as well, the estimate is exact without measurement noise and good while the excitation dominates the noise, which the amplitude and the coherence show. --pid names the pid instance whose gains are recorded with the run; they also allow the indirect estimate from the response to the excitation alone, G = H_r / (1 - H_r C / s) with the controller C and the integrator velocity → position, which the evaluation keeps as a check (it amplifies the estimation error where the loop gain is high, at the low frequencies).

The simulated plant: mcast_plant

For the simulation and the tests mcast_plant stands in for the drive and the mechanics: the speed loop as a first-order lag (tau), the mechanics as one resonance (f-res, zeta), a dead time (delay) and a velocity noise; vel-cmd in, vel, pos and torque (the motor acceleration, what a drive reports as its actual torque) out. The test tests/multichannel/ast closes a position loop around it, measures with noise and checks that the gain, the resonance and the coherence come out, and that the guard trips on a step beyond the travel limit.

The position loop and its optimisation

lib/python/mcast_opt.py puts LinuxCNC’s position loop on the measured plant: the setpoint filters F (biquad notch or low-pass on the pid’s output, modelled with the component’s own coefficients), the controller C (the discrete pid with P, I, D at the servo period), the plant G and the integrator velocity → position give the open loop L = C F G / s and the closed loop T = L / (1 + L). The figures are those of the SINUMERIK’s AST: the phase margin at the gain crossover, the gain margin at the phase crossover, the bandwidth (-3 dB of T, and the -90 degree crossing of T - the "Reglerbandbreite" of the article) and the peak of the closed loop.

The strategies set the margins to keep:

strategy phase margin gain margin closed-loop peak

schnell (fast)

40 deg

8 dB

3 dB

normal

55 deg

12 dB

2 dB

robust

70 deg

15 dB

1 dB

The optimisation finds the largest P (the Kv factor) that keeps the margins and the peak - a logarithmic scan and a bisection on the measured curves, no model fit. Resonances of the plant beyond the bandwidth that lift the closed loop above -10 dB (the article’s rule) get a notch filter at their frequency (Q 3), at most four filters, and P is searched again with them. The feedforward follows from the plant: FF1 = 1 / gain (the velocity feedforward of a velocity drive), FF2 = equivalent lag / gain, the lag from the slope of the plant’s phase at low frequencies (the speed loop’s lag plus the dead time) - the article’s "FFW maximieren". A manual set of parameters is evaluated the same way without a new measurement, so the curves answer every change at once (the "Manuell" column of Operate).

The result carries P, I, D, FF1, FF2, the filters and the figures; report() writes it as text, apply_lines() gives the halcmd setp lines for the pid and the biquad instances (type 2 notch, 1 low-pass, enable 0 for an unused one) and ini_values() the [JOINT_n] keys (P, I, D, FF1, FF2, AST_FILTER_k = type f0 Q). The test tests/multichannel/ast/test_opt.py checks the margins of a known loop, the strategies, the feedforward, the notch on a strong resonance and the biquad model against the analytic filter.

The page in mchmi: Antriebsoptimierung

The page Antriebs-optim. of the diagnosis area is the operator’s view, laid out after Operate’s "Automat. Servo Optim.":

  • The form: the axis (one key per joint of [AST]JOINTS, named by its letter in the channel), the strategy (schnell / normal / robust) and the run - amplitude, f max, duration and the travel limit of the guard, with the defaults of [AST] (AMPLITUDE, F_MIN, F_MAX, DURATION, TRAVEL_LIMIT, USE_VEL_FB).

  • The table Reglerdaten: the parameter sets Manuell, Optimiert, Aktiv (the gains and filters in HAL now) and Original (the INI at the first visit) with P (Kv), I, D, FF1, FF2, the four filters and, once a measurement exists, their figures: phase margin, gain margin, the bandwidths (-3 dB, -90 degrees) and the peak.

  • The Bode diagram (amplitude in dB and phase over the frequency, log) with a legend of check marks: the measured plant, the coherence, the filters, the open and the closed loop of the set chosen with Anzeige, and the closed loop of the active set for comparison; the -10 dB line, -90 and -180 degrees and the bandwidth are marked.

The softkeys: Messen (a second press within four seconds starts the run; the machine must be on and idle; Abbrechen while it runs), Optimieren (the strategy on the last measurement), Übernehmen Optimiert / Übernehmen Manuell (the set into HAL with setp on the pid and the biquad instances of [AST]FILTERS_n, and into the INI: [JOINT_n] P, I, D, FF1, FF2, AST_FILTER_k, the INI backed up as .bak; the section is found in an #INCLUDE file too), Wert - / Wert + (the selected row of the manual set by 5 %, a filter’s frequency likewise), and on the second key page Zurück zu Original, Optimiert → Manuell, Filtertyp (off, notch, low-pass of the selected filter row), Speichern (the AST file, the picture and the report under ast/ below [DISPLAY]PROGRAM_PREFIX), Laden (the newest file of the axis, evaluated again - the offline look of Operate) and Anzeige (which set the loop curves are drawn for).

The INI: [AST] JOINTS lists the joints with a mcast instance, PID_n the pid of joint n (default pid.n), MCAST_n its instance (default mcast.n), FILTERS_n the biquad instances of its setpoint filters in the chain (pid → filters → mcast → drive; none means the optimisation proposes filters that cannot be applied). The sim configs/sim/multichannel/ast shows the chain for three axes on the simulated plant with a different resonance each.

EtherCAT drives: the speed loop of the drive

A drive on EtherCAT (CiA 402, through linuxcnc-ethercat) reports more than an analog one: its actual torque (object 0x6077) and velocity (0x606C) come as PDOs every servo cycle. The torque goes to torque-in of mcast (the pin of lcec’s drive, or an analog input that carries a torque signal; 0 when there is none), and the recording holds it:

  • the mechanical frequency response torque → velocity (the curve Mechanikfrequenzgang of the legend) with its resonances - the "Systemstrecke" of the SINUMERIK;

  • the open speed loop of the drive (curve Offener Drehzahlregelkreis), which needs no torque: the drive’s closed speed loop is the plant normalised to unity gain, T_v, and its open loop L_v = T_v / (1 - T_v); its phase and gain margins and its crossover are the figures of the drive’s own tuning.

The key page Antrieb (the third page of softkeys) works on this: Drehzahlregler rechnen shows the margins of the drive’s loop and, with a torque recorded, the PI speed controller on the mechanics for the chosen strategy: the largest Kp with the strategy’s margins as a P controller, Tn five times the crossover period (not below 5 ms, the article’s rule), Kp searched again with it. Drehzahlregler schreiben writes Kp, Tn or Ki and the notch filters into the drive through SDOs, Antrieb lesen shows the drive’s present values, Antriebs-Autotuning triggers the drive’s own tuning where the family knows the command.

The drive family and the slave come from the INI: [AST] DRIVE_n = delta-a3 | sinamics-coe | generic, SLAVE_n = the slave’s position on the bus, MASTER (0). A family is a table lib/python/mcast_drives/ <family>.json that maps the logical parameters (speed_kp, speed_tn or speed_ki, inertia_ratio, notch1_f, notch1_q or notch1_depth, notch2_…​, lowpass_f, auto_tune as a command) to the drive’s objects with index, subindex, type, scale and unit; the reading and writing use the IgH tool (ethercat upload / download). The tables of the Delta ASDA-A3-E (its parameters Pg.nnn on 0x2000 + g * 0x100 + nnn) and of SINAMICS with CoE (p<n> on 0x2000 + n) carry the mapping as documented but are marked unverified until a drive confirmed them: the page says so after a write, and a dry run is available in mcast_ecat.write_params. The current loop of the drive stays with its own identification; an EtherCAT cycle of 1 kHz limits the evaluation to roughly 400 Hz.

Files

File Content

src/hal/components/mcast.comp

the function generator with the travel guard

src/hal/components/mcast_plant.comp

the simulated plant

lib/python/mcast.py

settings, the Welch estimate, the closed-loop correction, the measurement, the AST file

bin/mcast-measure

the measurement from the console

tests/multichannel/ast

the evaluation on a known plant, the halrun run with the guard