BLDC(9)

πŸ“¦
version 2.9.4 Β· 4 versions
, in ubuntu resolute, ubuntu stonking

πŸ’– BLDC(9) β€” HAL Component πŸ’–

okay so bestie, this is the manual for the bldc component, and it's giving main character energy. let's get into it, no cap.


✨ NAME ✨

bldc β€” BLDC and AC-servo control component. periodt.


🌸 SYNOPSIS 🌸

loadrt bldc cfg=qi6,aH

πŸ¦‹ DESCRIPTION πŸ¦‹

so this component is designed as an interface between the most common forms of three-phase motor feedback devices and the corresponding types of drive. but here's the tea: there is no requirement that the motor and drive should necessarily be of inherently compatible types. fr fr, you can mix and match.

each instance of the component is defined by a group of letters describing the input and output types. a comma separates individual instances of the component. for example loadrt bldc cfg=qi6,aH. yep, that's the vibe.


🏷️ Tags 🏷️

input type definitions are all lower-case, bestie. let's break them down:

  • n β€” No motor feedback. this mode could be used to drive AC induction motors, but is also potentially useful for creating free-running motor simulators for drive testing. it's giving "simulation slay".
  • h β€” Hall sensor input. Brushless DC motors (electronically commutated permanent magnet 3-phase motors) typically use a set of three Hall sensors to measure the angular position of the rotor. a lower-case h in the cfg string indicates that these should be used. so if you see an h, that's what's up.
  • a β€” Absolute encoder input. (Also possibly used by some forms of Resolver conversion hardware). the presence of this tag over-rides all other inputs. note that the component still requires to be be connected to the rawcounts encoder pin to prevent loss of commutation on index-reset. do not skip that, bestie, it's important. (and yes, the original says "be be", we're keeping that energy.)
  • q β€” Incremental (quadrature) encoder input. if this input is used then the rotor will need to be homed before the motor can be run. so don't forget to home it, okay?
  • i β€” Use the index of an incremental encoder as a home reference. it's the little reference point that could.
  • f β€” Use a 4-bit Gray-scale patttern to determine rotor alignment. this scheme is only used on the Fanuc "Red Cap" motors. this mode could be used to control one of these motors using a non-Fanuc drive. (yes, "patttern" β€” we don't make the rules, we just report them.)

output type descriptions are all upper-case. and here's the defaults tea:

Defaults β€” The component will always calculate rotor angle, phase angle and the absolute value of the input value for interfacing with drives such as the Mesa 8I20. It will also default to three individual, bipolar phase output values if no other output type modifiers are used. so that's the baseline, bestie.

now the output modifiers:

  • B β€” Bit level outputs. Either 3 or 6 logic-level outputs indicating which high or low gate drivers on an external drive should be used. it's giving "gatekeeping, but literally".
  • 6 β€” Create 6 rather than the default 3 outputs. In the case of numeric value outputs these are separate positive and negative drive amplitudes. Both have positive magnitude. double the outputs, double the fun.
  • H β€” Emulated Hall sensor output. This mode can be used to control a drive which expects 3x Hall signals, or to convert between a motor with one hall pattern and a drive which expects a different one. it's the translator of the motor world.
  • F β€” Emulated Fanuc Red Cap Gray-code encoder output. This mode might be used to drive a non-Fanuc motor using a Fanuc drive intended for the "Red-Cap" motors. cross-compatibility? we love to see it.
  • T β€” Force Trapezoidal mode. sometimes you just gotta force it, iykyk.

πŸ”₯ OPERATING MODES πŸ”₯

the component can control a drive in either Trapezoidal or Sinusoidal mode, but will always default to sinusoidal if the input and output modes allow it. this can be over-ridden by the T tag. Sinusoidal commutation is significantly smoother (trapezoidal commutation induces 13% torque ripple). so like, sinusoidal is the smooth operator, and trapezoidal has that 13% torque ripple. choose wisely.


πŸŽ€ ROTOR HOMING. πŸŽ€

to use an encoder for commutation a reference 0-degrees point must be found. the component uses the convention that motor zero is the point that an unloaded motor aligns to with a positive voltage on the A (or U) terminal and the B & C (or V and W) terminals connected together and to -ve voltage. there will be two such positions on a 4-pole motor, 3 on a 6-pole and so on. they are all functionally equivalent as far as driving the motor is concerned. so don't stress about which one, bestie.

if the motor has Hall sensors then the motor can be started in trapezoidal commutation mode, and will switch to sinusoidal commutation when an alignment is found. if the mode is qh then the first Hall state-transition will be used. if the mode is qhi then the encoder index will be used. this gives a more accurate homing position if the distance in encoder counts between motor zero and encoder index is known. to force homing to the Hall edges instead simply omit the i. so qh vs qhi is the vibe check here.

motors without Hall sensors may be homed in synchronous/direct mode. the better of these options is to home to the encoder zero using the iq config parameter. when the init pin goes high the motor will rotate (in a direction determined by the rev pin) until the encoder indicates an index-latch (the servo thread runs too slowly to rely on detecting an encoder index directly). if there is no encoder index or its location relative to motor zero can not be found, then an alternative is to use magnetic homing using the q config. in this mode the motor will go through an alignment sequence ending at motor zero when the init pin goes high It will then set the final position as motor zero. unfortunately the motor is rather springy in this mode and so alignment is likely to be fairly sensitive to load. so like, it's a little extra, but it works.


πŸ’… FUNCTIONS πŸ’…

bldc.N (requires a floating-point thread)


bestie this is only part 1, part 2 is coming πŸ’…

πŸ’… PINS πŸ’…

okay bestie, strap in, because this is the whole pin list and honestly it's giving encyclopedia energy πŸ“š but we do NOT skip pins in this house, every single one is getting its moment, periodt. ✨

🚨 heads up before you plug ANYTHING in: a whole bunch of these pins only exist if the personality bitmask test in the brackets passes. If the [if ...] thing is false, that pin literally does not exist β€” not quiet, not hidden, just gone. Read the bracket first, wire second. iykyk πŸ’€

  • bldc.N.hall1 β€” bit in [if personality & 0x01] β€” Hall sensor signal 1 πŸŒ€ (that's the first one, bestie)
  • bldc.N.hall2 β€” bit in [if personality & 0x01] β€” Hall sensor signal 2 πŸŒ€
  • bldc.N.hall3 β€” bit in [if personality & 0x01] β€” Hall sensor signal 3 πŸŒ€
  • bldc.N.hall-error β€” bit out [if personality & 0x01] β€” screaming (politely) that the hall pattern you picked is giving inconsistent rotor position data 😭 this can happen because the pattern is just wrong for that motor, or because one or more of the sensors is unconnected / broken. and here's the tea: a consistent pattern isn't necessarily a valid one, but an inconsistent one can never be valid. so like, consistency is necessary not sufficient, okurrr πŸ’…
  • bldc.N.C1 β€” bit in [if ( personality & 0x10 )] β€” Fanuc Gray-code bit 0 input 🧚
  • bldc.N.C2 β€” bit in [if ( personality & 0x10 )] β€” Fanuc Gray-code bit 1 input 🧚
  • bldc.N.C4 β€” bit in [if ( personality & 0x10 )] β€” Fanuc Gray-code bit 2 input 🧚
  • bldc.N.C8 β€” bit in [if ( personality & 0x10 )] β€” Fanuc Gray-code bit 3 input 🧚
  • bldc.N.value β€” float in β€” the PWM master amplitude input πŸ‘‘ the big boss amplitude, no cap
  • bldc.N.lead-angle β€” float in [if personality & 0x06] (default: 90) β€” the phase lead between the electrical vector and the rotor position, measured in degrees πŸ“
  • bldc.N.rev β€” bit in β€” set this bad boy true and the motor spins backwards πŸ”„ and lowkey there's more than one way to do it: negative PWM amplitudes will also reverse the motor, and generally there'll be a Hall pattern that runs the motor in each direction too. options, bestie ✨
  • bldc.N.frequency β€” float in [if ( personality & 0x0F ) == 0] β€” frequency input for motors with no feedback at all, or the ones that only have an index (which, btw, gets ignored) πŸ™ˆ
  • bldc.N.initvalue β€” float in [if personality & 0x04] (default: 0.2) β€” the current used for the homing sequence, for when you've got an incremental encoder and zero hall-sensor feedback ⚑
  • bldc.N.rawcounts β€” s32 in [if personality & 0x06] (default: 0) β€” encoder counts input. and this is a must: it has to be linked to the encoder rawcounts pin, otherwise encoder index resets will make the motor commutation just. fail. πŸ’€ no cap, link it
  • bldc.N.index-enable β€” bit io [if personality & 0x08] β€” hook this up to the matching encoder index-enable pin so the encoder gets zeroed when it passes index 🎯 its only job here is letting the bldc control component know an index has been seen, that's it, that's the whole assignment
  • bldc.N.init β€” bit in [if ( personality & 0x05 ) == 4] β€” a rising edge on this pin kicks off the motor alignment sequence πŸ”₯ and it should be wired up in a way that makes the motor re-align anytime encoder monitoring has been interrupted β€” typically that only happens at machine power-off. the alignment process involves powering the motor phases such that the motor ends up in a known position. the encoder counts then get stored in the offset parameter. ⚠️ big warning though: the alignment process will tend to cause a following error if it gets triggered while the axis is enabled, so set it before the matching axis.N.enable pin. the complementary init-done pin exists to handle the sequencing you need. 🫢

and good news: both of these pins can be ignored entirely if the encoder offset is already known explicitly β€” like with an absolute encoder 🌈 in that case you just set the offset parameter directly in the HAL file and move on with your life. slay.

  • bldc.N.init-done β€” bit out [if ( personality & 0x05 ) == 4] (default: 0) β€” indicates the homing sequence is complete βœ… the little green checkmark of the pin world
  • bldc.N.A-value β€” float out [if ( personality & 0xF00 ) == 0] β€” output amplitude for phase A 🌊
  • bldc.N.B-value β€” float out [if ( personality & 0xF00 ) == 0] β€” output amplitude for phase B 🌊
  • bldc.N.C-value β€” float out [if ( personality & 0xF00 ) == 0] β€” output amplitude for phase C 🌊
  • bldc.N.A-on β€” bit out [if ( personality & 0xF00 ) == 0x100] β€” output bit for phase A πŸ’‘
  • bldc.N.B-on β€” bit out [if ( personality & 0xF00 ) == 0x100] β€” output bit for phase B πŸ’‘
  • bldc.N.C-on β€” bit out [if ( personality & 0xF00 ) == 0x100] β€” output bit for phase C πŸ’‘
  • bldc.N.A-high β€” float out [if ( personality & 0xF00 ) == 0x200] β€” high-side driver for phase A ⬆️
  • bldc.N.B-high β€” float out [if ( personality & 0xF00 ) == 0x200] β€” high-side driver for phase B ⬆️
  • bldc.N.C-high β€” float out [if ( personality & 0xF00 ) == 0x200] β€” high-side driver for phase C ⬆️
  • bldc.N.A-low β€” float out [if ( personality & 0xF00 ) == 0x200] β€” low-side driver for phase A ⬇️
  • bldc.N.B-low β€” float out [if ( personality & 0xF00 ) == 0x200] β€” low-side driver for phase B ⬇️
  • bldc.N.C-low β€” float out [if ( personality & 0xF00 ) == 0x200] β€” low-side driver for phase C ⬇️
  • bldc.N.A-high-on β€” bit out [if ( personality & 0xF00 ) == 0x300] β€” high-side driver for phase A ⬆️ (the bit version this time)
  • bldc.N.B-high-on β€” bit out [if ( personality & 0xF00 ) == 0x300] β€” high-side driver for phase B ⬆️
  • bldc.N.C-high-on β€” bit out [if ( personality & 0xF00 ) == 0x300] β€” high-side driver for phase C ⬆️
  • bldc.N.A-low-on β€” bit out [if ( personality & 0xF00 ) == 0x300] β€” low-side driver for phase A ⬇️
  • bldc.N.B-low-on β€” bit out [if ( personality & 0xF00 ) == 0x300] β€” low-side driver for phase B ⬇️
  • bldc.N.C-low-on β€” bit out [if ( personality & 0xF00 ) == 0x300] β€” low-side driver for phase C ⬇️
  • bldc.N.hall1-out β€” bit out [if ( personality & 0x400 )] β€” Hall 1 output πŸŒ€
  • bldc.N.hall2-out β€” bit out [if ( personality & 0x400 )] β€” Hall 2 output πŸŒ€
  • bldc.N.hall3-out β€” bit out [if ( personality & 0x400 )] β€” Hall 3 output πŸŒ€
  • bldc.N.C1-out β€” bit out [if ( personality & 0x800 )] β€” Fanuc Gray-code bit 0 output 🧚
  • bldc.N.C2-out β€” bit out [if ( personality & 0x800 )] β€” Fanuc Gray-code bit 1 output 🧚
  • bldc.N.C4-out β€” bit out [if ( personality & 0x800 )] β€” Fanuc Gray-code bit 2 output 🧚
  • bldc.N.C8-out β€” bit out [if ( personality & 0x800 )] β€” Fanuc Gray-code bit 3 output 🧚
  • bldc.N.phase-angle β€” float out (default: 0) β€” the phase angle, including the lead/lag angle, after encoder zeroing etc. super useful for angle/current drives πŸ’œ value ranges 0 to 1 and it measures electrical revolutions. so for a 4 pole motor you get two zeros, a 6-pole gives you three, and so on 🌈
  • bldc.N.rotor-angle β€” float out (default: 0) β€” rotor angle after encoder zeroing etc. this one's the moment for angle/current drives that add their own phase offset β€” the 8I20 says hi πŸ‘‹ range is 0 to 1, measured in electrical revolutions, and again: two zeros for a 4 pole motor, three for a 6-pole, etc. etc. πŸ’«
  • bldc.N.out β€” float out β€” current output, and yes it includes the effect of the dir pin and the alignment sequence 🎬 the whole ensemble, together
  • bldc.N.out-dir β€” bit out β€” direction output, and it goes high if value is negative XOR rev is true πŸ”€ exclusive or sweetie, it's exclusive or
  • bldc.N.out-abs β€” float out β€” absolute value of the input value ✨ (what it says on the tin, bestie, no plot twist)

πŸ’– PARAMETERS πŸ’–

okay bestie, this is the big one β€” every knob, dial and secret setting on your drive lives here. take notes πŸ“

  • bldc.N.in-type s32 r (default: -1) β€” state machine output, and ngl it will probably get hidden once the debug era ends πŸ™ˆ
  • bldc.N.out-type s32 r (default: -1) β€” also state machine output, and also probably getting hidden after debug. twins πŸ’…
  • bldc.N.scale s32 rw [if personality & 0x06] (default: 512) β€” how many encoder counts fit in one full rotor revolution. the math girlies know πŸ”₯
  • bldc.N.poles s32 rw [if personality & 0x06] (default: 4) β€” how many poles your motor has. here's the tea: the encoder scale gets divided by this number, and that tells you how many encoder counts there are per electrical revolution ⚑
  • bldc.N.encoder-offset s32 rw [if personality & 0x0A] (default: 0) β€” the offset, in encoder counts, between the motor electrical zero and the encoder zero, modulo the number of counts per electrical revolution 🎯
  • bldc.N.offset-measured s32 r [if personality & 0x04] (default: 0) β€” the encoder offset that the homing sequence actually measured (in certain modes). it did the work itself, iconic πŸ’–
  • bldc.N.drive-offset float rw (default: 0) β€” the angle, in degrees, that the drive applies to the commanded angle, in degrees. this one is only used during the homing sequence of drives with incremental encoder feedback, where it back-calculates from commanded angle to actual phase angle. it only matters for drives that want rotor-angle input instead of phase-angle demand. should be 0 for most drives, fr fr.
  • bldc.N.output-pattern u32 rw [if personality & 0x400] (default: 25) β€” the commutation pattern to output when you're in Hall Signal translation mode. see the description of pattern for the whole saga πŸ‘‘
  • bldc.N.pattern u32 rw [if personality & 0x01] (default: 25) β€” the commutation pattern to actually use, from 0 to 47. default is type 25. they included every plausible combination, no cap. the table has the excitation pattern along the top and the pattern code down the left side, and each entry is the hall patterns in H1, H2, H3 order. the common ones, bestie:
    • 0 β€” 30 degree commutation
    • 26 β€” its reverse
    • 17 β€” 120 degree
    • 18 β€” alternate 60 degree
    • 21 β€” 300 degree, Bodine
    • 22 β€” 240 degree
    • 25 β€” 60 degree commutation

⚠️ lowkey important: a bunch of incorrect commutations will still have non-zero net torque, so they can look like they're working when they absolutely are not. it's giving fake bestie energy πŸ’€

and if your motor came with zero documentation? honestly just try every single pattern. vibe check the whole table 🌈

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Phases, Source - Sink          β”‚
β”œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ pat β”‚ B-A   C-A   C-B   A-B   A-C   B-C β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  0  β”‚ 000   001   011   111   110   100 β”‚
β”‚  1  β”‚ 001   000   010   110   111   101 β”‚
β”‚  2  β”‚ 000   010   011   111   101   100 β”‚
β”‚  3  β”‚ 001   011   010   110   100   101 β”‚
β”‚  4  β”‚ 010   011   001   101   100   110 β”‚
β”‚  5  β”‚ 011   010   000   100   101   111 β”‚
β”‚  6  β”‚ 010   000   001   101   111   110 β”‚
β”‚  7  β”‚ 011   001   000   100   110   111 β”‚
β”‚  8  β”‚ 000   001   101   111   110   010 β”‚
β”‚  9  β”‚ 001   000   100   110   111   011 β”‚
β”‚ 10  β”‚ 000   010   110   111   101   001 β”‚
β”‚ 11  β”‚ 001   011   111   110   100   000 β”‚
β”‚ 12  β”‚ 010   011   111   101   100   000 β”‚
β”‚ 13  β”‚ 011   010   110   100   101   001 β”‚
β”‚ 14  β”‚ 010   000   100   101   111   011 β”‚
β”‚ 15  β”‚ 011   001   101   100   110   010 β”‚
β”‚ 16  β”‚ 000   100   101   111   011   010 β”‚
β”‚ 17  β”‚ 001   101   100   110   010   011 β”‚
β”‚ 18  β”‚ 000   100   110   111   011   001 β”‚
β”‚ 19  β”‚ 001   101   111   110   010   000 β”‚
β”‚ 20  β”‚ 010   110   111   101   001   000 β”‚
β”‚ 21  β”‚ 011   111   110   100   000   001 β”‚
β”‚ 22  β”‚ 010   110   100   101   001   011 β”‚
β”‚ 23  β”‚ 011   111   101   100   000   010 β”‚
β”‚ 24  β”‚ 100   101   111   011   010   000 β”‚
β”‚ 25  β”‚ 101   100   110   010   011   001 β”‚
β”‚ 26  β”‚ 100   110   111   011   001   000 β”‚
β”‚ 27  β”‚ 101   111   110   010   000   001 β”‚
β”‚ 28  β”‚ 110   111   101   001   000   010 β”‚
β”‚ 29  β”‚ 111   110   100   000   001   011 β”‚
β”‚ 30  β”‚ 110   100   101   001   011   010 β”‚
β”‚ 31  β”‚ 111   101   100   000   010   011 β”‚
β”‚ 32  β”‚ 100   101   001   011   010   110 β”‚
β”‚ 33  β”‚ 101   100   000   010   011   111 β”‚
β”‚ 34  β”‚ 100   110   010   011   001   101 β”‚
β”‚ 35  β”‚ 101   111   011   010   000   100 β”‚
β”‚ 36  β”‚ 110   111   011   001   000   100 β”‚
β”‚ 37  β”‚ 111   110   010   000   001   101 β”‚
β”‚ 38  β”‚ 110   100   000   001   011   111 β”‚
β”‚ 39  β”‚ 111   101   001   000   010   110 β”‚
β”‚ 40  β”‚ 100   000   001   011   111   110 β”‚
β”‚ 41  β”‚ 101   001   000   010   110   111 β”‚
β”‚ 42  β”‚ 100   000   010   011   111   101 β”‚
β”‚ 43  β”‚ 101   001   011   010   110   100 β”‚
β”‚ 44  β”‚ 110   010   011   001   101   100 β”‚
β”‚ 45  β”‚ 111   011   010   000   100   101 β”‚
β”‚ 46  β”‚ 110   010   000   001   101   111 β”‚
β”‚ 47  β”‚ 111   011   001   000   100   110 β”‚
β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ‘‘ AUTHOR πŸ‘‘

Andy Pugh β€” the legend, the moment, the main character ✨


πŸŽ€ LICENSE πŸŽ€

GPL β€” free as in freedom, bestie, go forth and slay πŸ’–


and that's the whole page, babe!! 🌸 this is from the LinuxCNC Documentation, dated 2026-03-17, and the page is BLDC(9). mwah, go wire a motor, you got this πŸ«ΆπŸ’…

πŸ“¦ where this page comes from