HV_F3 #
Brief #
hv on the F3 (HV board) side: it turns the three phase voltages from idq0 into TIM8 compare values that drive the power stage. It adds a dead time compensation, then the space vector (midpoint) common mode offset, keeps every pulse above a minimum on and off time, follows the PWM period that ls0 sets to phase lock the board to the F4, and holds all low sides on while io0 short-circuit brakes. It is loaded by stm32f303/src/main.c as hv0 (rt_prio 6, after idq0) and is not configured by the user directly: its settings (drop_k, drop_knee, arr) come from the F4 through ls0. This page is the F3 component and is published as hv_f3. The F4-side counterpart, which configures the HV board and sends it the commands, is the hv component.
Component Explanation #
- Wiring on the F3 (fixed in main.c):
hv0.u/v/w = idq0.u/v/w(phase voltages centred on 0;svm0is no longer loaded,hvtakes the offset itself),hv0.udc = io0.udc_duty(the fast link voltage),hv0.arr = ls0.arr,hv0.drop_k = ls0.drop_k,hv0.drop_knee = ls0.drop_knee,hv0.sbrake = io0.sbrake_on, andls0.duty_max = hv0.duty_max.- For the dead time compensation:
hv0.d_cmd/q_cmd = ls0.d_cmd/q_cmd,hv0.si/co = idq0.si_out/co_out(sin/cos of the voltage angleangle0.pos_v),hv0.id_fb/iq_fb = dq0.d/q,hv0.cmd_mode = ls0.cmd_mode,hv0.phase_mode = ls0.phase_mode. drop_band,drop_volt,drop_vlp,min_onandmin_offare not wired and not F4 config words: they keep their nrt_init defaults unless changed from the F3 terminal.- All three half bridges always switch.
- PWM period (rt):
arris written to the TIM8 auto reload register every tick.ls0moves it by a few counts once per F4 packet to lock the PWM to the F4’s packets. nrt_init setsarr=PWM_RES.- TIM8 runs centre aligned at 144 MHz (
PWM_TIM_CLK), so one PWM period is 2 * ARR ticks. The PWM (and F3 rt) frequencyPWM_FREQis a build option (stm32f303/Makefile, 10, 15 or 20 kHz, default 15 kHz; the F4 reads it back ashv0.pwm_freq), andPWM_RES = PWM_TIM_CLK / (2 * PWM_FREQ)is 7200, 4800 or 3600.
- Dead time compensation (rt):
- While a phase current keeps its sign the bridge loses the dead time’s share of the PWM period times the link voltage. The size of the correction in volts (
udchas a floor of 0.1 V):
dt_drop = drop_k * PWM_DEADTIME_TICKS / (2 * pwm_res) * udc;
PWM_DEADTIMEis the BDTR.DTG code 196, which decodes to 288 ticks (2.0 us), sodrop_k= 1 is 3 % ofudcat 15 kHz (2 % at 10 kHz, 4 % at 20 kHz). Adrop_kbelow 1 accounts for the part of the dead time the switches’ own delays eat. The result is clamped to 0..10 % ofudc, so a mistypeddrop_kdistorts the waveform but cannot harm the bridge.- Its sign per phase comes from a reference current, never the instantaneous measured one (keyed on that, the compensation drives the current it reads and runs away). The reference phase currents
iu,iv,iware built from a d/q reference withsi/co(inverse Park and 120 deg inverse Clarke), every tick, also when the compensation is off.si/cobelong to the voltage angle, the angle at which this tick’s voltage is applied on average (seeangle0.pos_vandls0.v_lead). - Voltage mode (
cmd_mode= 0, e.g. the spindle’s V/f): there is no current command, so the reference is the measuredid_fb/iq_fb, low pass filtered in the d/q frame with the time constantdrop_vlp(floor one period), so the sign follows the fundamental and not the ripple. The compensation is only applied here whendrop_volt> 0 (only its sign is used). drop_knee= 0 (default): latched sign. Per phase a Schmitt trigger flips to +1 abovedrop_bandand to -1 below-drop_bandand holds its value in between. The sign starts at 0, and rt_start resets it to 0, so nothing is added until a phase has carried current once. The price is a sign that is stale while a zero crossing passes through the band, and an axis that draws less thandrop_bandnever flips it at all.drop_knee> 0 (A): curve instead of latch. Each phase getsdt_drop * k(i)with the sign of its reference current, where
k(i) = 1 - 1 / (1 + |i| / drop_knee)^2;
- This follows the real loss, which fades out at low current (where the ripple carries the phase through zero inside the PWM period) and settles above a couple of amps. It cannot stick like the latch.
drop_kneehas a floor of 0.02 A.
- Space vector offset (rt):
- The compensation is added to
u,v,wfirst, then the common mode is chosen on the compensated phases:off = (min + max) / 2 - udc / 2, subtracted from all three, so the midpoint of the highest and lowest phase sits atudc / 2. Because the offset sees the compensation, near full modulation the clamp below no longer cuts it. - Each phase is then converted to a compare value,
CLAMP(x, 0, udc) / udc * pwm_res.
- Minimum on and off time (rt):
min_onandmin_offare converted to compare units atPWM_TIM_CLK / 2(one compare unit is 2 timer ticks in centre aligned mode, whatever ARR is), 216 units at 3 us. Both have a floor of the dead time plus 0.5 us (2.5 us): a shorter high side pulse never turns on through the driver interlock, and a shorter low side pulse leaves nothing for the current sample.duty_max = (pwm_res - min_on - min_off) / pwm_resis output every tick (0.91 at the defaults and 15 kHz, 0.94 at 10 kHz, 0.88 at 20 kHz).ls0scalespwm_voltby it, socurpid0’s voltage limit matches what this stage passes.- If the spread between the highest and lowest phase is larger than
pwm_res - min_on - min_off, all three are scaled down around their centre (a float scale). - Then, judged on the values before any shift: if any phase is above 0 but below
min_on, all three are moved up by what the lowest phase lacks (min_on - min); if the highest phase is abovepwm_res - min_off, all three are moved down by its excess. The shift is only the deficit, so the neutral moves no more than needed; line to line voltages are unchanged. - Finally each phase between 0 and
min_onis raised tomin_on, and every phase is clamped to 0..pwm_res - min_off. A phase at exactly 0 (low side on for the whole period) is allowed.
- Short-circuit braking (rt):
- While
sbrake> 0 (io0.sbrake_on) all three compares are forced to 0, so the low side switches of all phases are on and the back EMF drives current round the windings.io0switches the bridge on and off to chop that current;hvonly provides the compare values.
- Output:
- The values go to
PWM_U/V/W(TIM8 CCR3/CCR2/CCR1), inverted when the board definesPWM_INVERT.
hvhas no enable or fault handling of its own. The bridge is switched on and off byio0(TIM8 MOE and the driver enable pin) and, on an overcurrent comparator break, by the hardware break plus the TIM8 break interrupt in main.c, sohvkeeps writing compare values even while the bridge is off.- The voltage mode compensation (
drop_volt) is new and off by default; it has not been tried on the spindle yet.- The compensation is added on top of the voltage
curpid0was limited to, so near full modulation the spread can exceedpwm_res - min_on - min_offagain and the spread scaling cuts it by a few percent.ls0.pwm_voltis computed from the slowio0.udc, while this component divides by the fastio0.udc_duty, so during a fast link voltage change the two limits differ briefly.
Pins #
| Name | Description |
|---|---|
| drop_k | input, Dead time compensation as a fraction of the ideal dead time drop, 0 = off, from ls0.drop_k, default 0 |
| drop_band | parameter, Latched sign flips outside +-drop_band (A), min 0.05, not wired, default 0.5 |
| drop_knee | input, > 0: knee of the compensation curve on the reference current (A), 0 = latched sign, from ls0.drop_knee |
| cmd_mode | input, Command mode from ls0, 0 = voltage (reference from id_fb/iq_fb), else current (reference from d_cmd/q_cmd) |
| phase_mode | input, Phase mode from ls0, the compensation runs only in 120 deg 3ph mode (2) |
| d_cmd | input, D-axis current command from the F4 (A), reference for the compensation in current mode |
| q_cmd | input, Q-axis current command from the F4 (A), reference for the compensation in current mode |
| si | input, Sine of the voltage angle, from idq0.si_out |
| co | input, Cosine of the voltage angle, from idq0.co_out |
| iu | output, Reference U phase current for the compensation sign (A) |
| iv | output, Reference V phase current for the compensation sign (A) |
| iw | output, Reference W phase current for the compensation sign (A) |
| drop_volt | parameter, > 0 turns the compensation on in voltage mode, not wired, default 0 |
| drop_vlp | parameter, Low pass time constant of the voltage mode reference current (s), not wired, default 0.003 |
| id_fb | input, Measured d-axis current (A), from dq0.d, voltage mode reference |
| iq_fb | input, Measured q-axis current (A), from dq0.q, voltage mode reference |
| u | input, U phase voltage centred on 0 (V), from idq0.u |
| v | input, V phase voltage centred on 0 (V), from idq0.v |
| w | input, W phase voltage centred on 0 (V), from idq0.w |
| udc | input, DC link voltage (V), from io0.udc_duty, scales the PWM, min 0.1 |
| min_on | parameter, Minimum on time (s), floored at dead time + 0.5 us, default 3 us |
| min_off | parameter, Minimum off time (s), floored at dead time + 0.5 us, default 3 us |
| duty_max | output, Usable duty after min_on and min_off (0..1), to ls0.duty_max |
| arr | input, PWM timer reload value from ls0.arr, clamped to 90..110 % of PWM_RES (4800 at 15 kHz) |
| sbrake | input, Short-circuit braking from io0.sbrake_on, > 0 forces all compares to 0 (all low sides on) |
References #
Source: .c File