Sl Seq

SL_SEQ #

Brief #

The sl_seq component starts a motor without an encoder and hands it to the observer (obs), for a PMSM and an induction motor alike.

States #

  1. off: en = 0. Everything reset, obs tracks.
  2. align: current i_f on d at a standing frame for align_time. PMSM: the rotor turns onto the d axis. Induction motor: the flux builds (about 3 tr, what align_time 0 uses).
  3. I/f: the frame turns at f, which ramps toward vel_cmd at acc, with i_f on d. The rotor follows the rotating current. obs tracks the frame below w_hand / 2, so it starts with the right direction, then runs free.
  4. observer: angle0 from obs (src 2), d and q from the drive (d_in, q_in, pmsm_ttc0 or acim_foc0), pid_en = 1, pid closes the speed loop on obs0.vel_m, while d goes from i_f to d_in over fade_time so the current does not step. Entered once obs is ok, |f| >= w_hand and obs ran free lock_time. Back to 2 when obs drops ok or |obs0.vel_m| < w_hand - hyst, with f seeded from obs0.vel_m.

vel_ref and acc_ref replace the command into pid: they follow f in I/f and, from the handover, ramp from the observed speed to vel_cmd at acc, so the handover is bumpless and pid gets acceleration feedforward.

Encoder plausibility guard (optional, enc_tol > 0, needs vel_enc from an encoder with the same sign and scale as obs0.vel_m, e.g. a spindle orientation encoder). The tolerance is enc_tol times the slip model’s own limit, slip_max (acim_flux0.slip_max, electrical) / polecount, so about 1 fits any motor: in I/f the frequency stays within it of the encoder speed, so a rotor that does not follow is not left behind. In state 3 an observer speed further than it from the encoder for enc_time falls back to I/f, seeded from the encoder, and sets enc_err (link it to a fault input to trip instead). Steady, slip_err is the slip model’s error, a check on acim_flux0.tr without the MRAS (the sl_acim template links it to acim_flux0.slip_err, for tr_ks). Outside state 3 there is no observer speed to compare, so slip_err is held at 0 and tr_ks does not adapt on the last value. enc_tol 0 = off.

Defaults from the motor (each 0 = derived, a value set in the config wins):

  • align_time 0 = 3 * tr (acim_flux0.tr: the flux has built), 0.3 s without tr (PMSM: the rotor has turned onto d).
  • w_hand 0 = the speed where the emf is 5 * e_min (obs0.e_min, the observer’s own trust level): 5 * e_min / (polecount * flux), flux = psi (conf0.psi, PMSM) or lmr * i_f (acim_flux0.lmr, induction motor after align). 50 rad/s without either.
  • obs_bw = 5 * hand * polecount, the observer bandwidth. The sl_acim template links obs0.bw to it (it used to be set by hand, spindle 300); an obs0.bw in the config wins.

Speeds are mechanical rad/s. vel_e is f * polecount.

Low speed: below w_hand - hyst the drive is in I/f, with no speed loop and no torque control, so that is the lowest closed loop speed. w_hand belongs where the emf, w_hand * polecount * lmr * i_f (PMSM: psi), is about 5 times obs0.e_min, which is what w_hand 0 derives; the sl_acim template links i_f to acim_foc0.id_n, so the induction motor’s flux is the rated one.

Pins #

NameDescription
eninput, fault0.en_pid
vel_cmdinput, speed command [rad/s mech], vel0.vel
polecountparameter, pole pairs
i_fparameter, align and I/f current on d [A peak], default 3, sl_acim links acim_foc0.id_n
align_timeparameter, [s], 0 = 3 * tr
accparameter, I/f acceleration [rad/s^2 mech]
w_handparameter, handover speed [rad/s mech], 0 = from e_min and the flux
hystparameter, fall back below w_hand - hyst [rad/s mech], 0 = w_hand / 3
lock_timeparameter, obs free running before handover [s]
fade_timeparameter, i_f fades out over this after the handover [s]
obs_okinput, obs0.ok
obs_velinput, obs0.vel_m
d_ininput, d current from the drive in state 3
q_ininput, q current from the drive in state 3
stateoutput
foutput, I/f frequency [rad/s mech]
vel_eoutput, to angle0.vel_cmd [rad/s electrical]
srcoutput, to angle0.src
trackoutput, to obs0.track
pid_enoutput, to pid0.en
d_cmdoutput, to hv0.d_cmd
q_cmdoutput, to hv0.q_cmd
vel_refoutput, speed command for pid [rad/s mech], to pid0.vel_ext_cmd
acc_refoutput, its slope [rad/s^2], to pid0.acc_ext_cmd
vel_encinput, encoder rotor speed [rad/s mech], for the guard
enc_tolparameter, allowed abs(speed - vel_enc) as a multiple of slip_max, 0 = no guard
slip_maxparameter, slip limit [rad/s electrical], acim_flux0.slip_max
enc_timeparameter, observer error longer than this falls back [s]
enc_erroutput, 1 = observer disagreed with the encoder, held until en 0
slip_erroutput, obs0.vel_m - vel_enc in state 3, 1 Hz low pass, 0 in the other states [rad/s mech]
trinput, rotor time constant [s], acim_flux0.tr, for align_time 0
psiinput, magnet flux [V s], conf0.psi, for w_hand 0 (PMSM)
lmrinput, magnetizing inductance [H], acim_flux0.lmr, for w_hand 0 (induction motor)
e_mininput, obs0.e_min [V], for w_hand 0, default 3
alignoutput, align time in use [s]
handoutput, handover speed in use [rad/s mech]
obs_bwoutput, observer bandwidth for obs0.bw, 5 x hand x polecount [rad/s electrical]

References #

Source: .c File