LFO_Pulse
The square wave with an adjustable duty cycle
- FLOAT
LFO_Pulse is the square wave's adjustable sibling - the one node in the Comfy-LFO pack with a sixth input. Where LFO_Square toggles 50/50 and calls it done, Pulse lets you decide how long the output stays high before dropping low. Default it to 0.3 and it's high 30% of the cycle, low 70%. That "high for a burst, quiet for a while" shape is where pulses earn their name.
For ComfyUI that means a value that mostly sits low and occasionally spikes - think a ControlNet strength that's barely there most of the time but kicks in hard for a third of each cycle, or a denoise that mostly runs gentle with periodic sharp bursts. If you found yourself wanting LFO_Square but with control over the high time, this is the node you were looking for.
How it works
The implementation is the square wave with the threshold pulled out of the constant:
phase = (position * frequency) - int(position * frequency)
return offset + amplitude * (1 if phase < pulse_width else -1)
Same fractional-phase trick as the other nodes. While the phase sits below pulse_width, the output is offset + amplitude (high); past it, offset - amplitude (low). So pulse_width is the fraction of the cycle spent in the high state - 0.3 means high for the first 30% of each cycle, then low until it wraps. The output ranges from offset - amplitude to offset + amplitude like everything else in the pack.
Here's the trap worth knowing: pulse_width is a phase fraction, and the code compares phase < pulse_width directly. Set pulse_width to 1.0 or higher and phase is always less than it - the node stays permanently high. Set it to 0 or negative and it's permanently low. Keep it between 0 and 1 or you've turned a pulse into a dead wire. That's not a bug, it's just what the math does.
Same pack rule as always: this is a function of position, not a self-running oscillator. It won't pulse unless position changes, so wire position to a frame counter, batch index, or animation-scheduler value. Unwired, it outputs one constant value forever and looks broken.
The inputs that matter
Six float inputs - the pack standard five plus the one that makes this node special:
- pulse_width - the fraction of the cycle spent high. Default 0.3. This is the knob that distinguishes Pulse from Square.
- position - the driver. Wire an advancing value here.
- frequency - cycles per unit of position. Default 1.
- amplitude - swing distance from center. Default 1.
- offset - the midpoint. Default 0.
- phase_offset - start point in the cycle, default 0.5.
Output is a single FLOAT that wires into any float socket - KSampler denoise, ControlNet strength, IPAdapter weight, AnimateDiff motion scale, CFG. The usual deterministic-oscillator trick, minus the audio dependency.
Install and troubleshooting
The whole pack is one Python file with no dependencies and no model downloads. From your ComfyUI folder:
cd custom_nodes
git clone https://github.com/richinsley/Comfy-LFO.git
Restart ComfyUI and the nodes appear under the LFO menu. ComfyUI Manager can usually install the pack by searching "Comfy-LFO".
Frozen output means position isn't moving. A node stuck permanently high or low means pulse_width escaped the 0–1 range. Missing node means you didn't restart. That's the full troubleshooting list for this one - it's a genuinely simple node, and the simplicity is the feature. When you need an adjustable-burst switch instead of a 50/50 one, this is the one you reach for.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| position | FLOAT | 0.000 | — |
| phase_offset | FLOAT | 0.500 | — |
| frequency | FLOAT | 1.000 | — |
| amplitude | FLOAT | 1.000 | — |
| offset | FLOAT | 0.000 | — |
| pulse_width | FLOAT | 0.300 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| FLOAT | FLOAT | — |