Many CNC spindles, VFD interfaces, and industrial controllers expect a 0-10 V analog setpoint, while an Arduino or GRBL controller only outputs 0-5 V PWM. Getting from one to the other takes two stages: an RC low-pass filter that turns the PWM duty cycle into a clean DC voltage, and an op-amp gain stage that scales that DC voltage up to the full 0-10 V range. Both stages need a bit of extra care to stay reliable once the signal has to survive a real cable run to the spindle controller, not just a few centimeters on a breadboard.
Hardware Parts
- Arduino UNO or any GRBL-compatible controller with a PWM spindle output
- LM358 dual op-amp
- 2× resistor \(3.3\,\text{k}\Omega\) and 2× capacitor \(4.7\,\mu\text{F}\) for the RC filter stages
- 2× resistor \(10\,\text{k}\Omega\) for the gain-setting resistors \(R_f\) and \(R_g\)
- Resistor \(100\,\Omega\) for the output series resistor
- 12 V to 24 V supply for the op-amp
Part 1: RC Low-Pass Filter Stage (PWM to DC)
PWM Average Voltage
Let the PWM amplitude be \(V_\text{PWM}\) and the duty cycle be \(D\in[0,1]\). The time average of the PWM waveform is
\[V_\text{DC}=D\cdot V_\text{PWM}.\]
An RC filter preserves this average while attenuating the ripple that PWM switching introduces on top of it. PWM frequency is an input to the filter design: Arduino's analogWrite() runs at roughly 490 Hz on most Uno pins and roughly 980 Hz on a few of them, and many GRBL spindle PWM configurations use around 1 kHz.
Why an RC Filter Is Enough
The series resistor \(R\) and shunt capacitor \(C\) here form exactly the analog RC low-pass filter derived from Kirchhoff's voltage law in Introduction to the Low-Pass Filter, with transfer function \(H(j\omega)=1/(1+j\omega RC)\) and cutoff frequency \(f_c=1/(2\pi RC)\). Writing its magnitude in terms of ordinary frequency \(f=\omega/(2\pi)\),
\[|H(f)|=\frac{1}{\sqrt{1+(f/f_c)^2}},\]
and for \(f\gg f_c\) this falls off as \(|H(f)|\approx f_c/f\): every doubling of the PWM frequency above cutoff halves the ripple that reaches the output, which is the whole reason a low cutoff relative to the PWM frequency is enough to leave a clean DC level.
Two Cascaded RC Stages
A single RC stage can be sufficient at higher PWM frequencies, but two cascaded stages are usually preferable for 490 Hz to 1 kHz PWM, since the attenuations multiply:
\[|H_\text{total}(f)|\approx|H(f)|^2.\]
This improves ripple suppression noticeably while still keeping the circuit down to standard components.
Recommended Standard Values
A compact two-stage filter that works well for both 490 Hz and 1 kHz PWM is:
- \(R_1=R_2=3.3\,\text{k}\Omega\)
- \(C_1=C_2=4.7\,\mu\text{F}\)
Per-stage cutoff:
\[f_c\approx\frac{1}{2\pi\cdot3.3\,\text{k}\Omega\cdot4.7\,\mu\text{F}}\approx10\,\text{Hz}.\]
Optional additions that help in noisy environments:
- \(100\,\text{nF}\) in parallel with each electrolytic capacitor, for better high-frequency shunting.
- \(100\,\text{k}\Omega\) from the final filter node to ground, to discharge that node to 0 V during reset or if the input becomes floating.
A lower \(f_c\) reduces ripple further but increases settling time after a duty-cycle change. For spindle speed control, a settling time in the sub-second range is usually acceptable.
Part 2: Amplification (0-5 V DC to 0-10 V DC)
Non-Inverting Gain Stage
After filtering, the signal is a DC voltage \(V_\text{DC}\in[0,5\,\text{V}]\). Scale it with a non-inverting amplifier:
\[G=1+\frac{R_f}{R_g}.\]
For \(G=2\), choose \(R_f=R_g\), for example:
- \(R_f=10\,\text{k}\Omega\)
- \(R_g=10\,\text{k}\Omega\)
Then \(V_\text{OUT}=2\cdot V_\text{DC}\), which produces the 0-10 V setpoint.
Op-Amp Supply Voltage
To generate a 10 V output, the op-amp needs a sufficiently high supply. If it is powered from 5 V, it simply cannot swing to 10 V. A 12 V to 24 V supply is appropriate; with a 24 V supply, an LM358 produces 10 V comfortably, since the output then sits far below the upper rail.
Supply Decoupling
Place decoupling capacitors from \(V_+\) to ground:
- \(100\,\text{nF}\) ceramic capacitor, placed physically close to the op-amp's supply pins.
- \(10\,\mu\text{F}\) to \(100\,\mu\text{F}\) electrolytic capacitor nearby.
These sit in parallel, not in series. Together they reduce the supply impedance right at the op-amp and help prevent oscillation and sensitivity to the current spikes at every PWM edge.
Unused Second Amplifier in the LM358
The LM358 contains two op-amps, and the unused channel should never be left floating. A standard termination is to connect its non-inverting input to ground, wire it as a follower by connecting its output back to its own inverting input, and leave that output unconnected externally.
Driving Long Cables: The Output Series Resistor
A short bench setup can look perfectly stable even when the final installation is not. A long control cable adds capacitance and more exposure to EMI, and op-amps can become marginal or outright oscillate when driving a capacitive load directly. A common symptom is an output that reaches 10 V on the bench but never quite gets there once the real cable and spindle interface are connected.
Placing a series resistor at the amplifier output fixes this:
- \(R_\text{OUT}\approx100\,\Omega\) (values up to \(220\,\Omega\) are commonly acceptable)
This isolates the op-amp from the cable's capacitance and improves stability.
For long or noisy runs, an additional receiver-end capacitor helps further:
- \(C_\text{END}=10\,\text{nF}\) to \(47\,\text{nF}\) from signal to signal ground, placed near the 0-10 V input.
This suppresses high-frequency noise without materially affecting the DC setpoint.
Wiring and Grounding for Long Runs
The 0-10 V signal is only meaningful relative to its reference, so use a twisted pair for signal and signal ground, and avoid routing it alongside motor and mains conductors over long distances. If the same cable also carries 24 V power, the return current can modulate that reference; if spare conductors are available, dedicating one to signal ground improves robustness noticeably.
Gain Calibration With a Trimmer
If calibration is needed, \(R_g\) or \(R_f\) can be adjusted, but \(R_g\) should never be allowed to approach zero, since the gain then grows without bound and the output saturates. A bounded approach is a fixed resistor in series with a trimmer, for example:
- \(R_g=8.2\,\text{k}\Omega\) in series with a \(2\,\text{k}\Omega\) to \(5\,\text{k}\Omega\) trimmer.
This keeps the adjustment range centered around the target gain instead of letting it run away.
Failure Patterns and Likely Causes
- Output never reaches 10 V: the op-amp supply is too low, commonly because it is powered from 5 V.
- Works on the bench but fails once connected: missing \(R_\text{OUT}\), inadequate decoupling, or a reference/wiring issue.
- Ripple or speed jitter: cutoff frequency too high, missing second RC stage, or EMI coupling into the analog line.