carrier.cir · 37 lines
* 1 kHz triangle-wave carrier for PWM, 2 V peak-to-peak
*
* Astable oscillator built from two op-amp stages:
* 1) an inverting integrator (Rint, Cint) that produces the triangle,
* 2) a non-inverting Schmitt trigger (R1, R2) that produces the square
* wave which drives the integrator.
* The feedback loop itself sustains the oscillation: no PULSE/SIN/AC
* source is used, only the two DC supply rails.
* --- DC supply rails (the only independent sources) ---
Vcc vcc 0 DC 12
Vee vee 0 DC -12
* --- Inverting integrator: vc -- Rint -- n1, Cint n1->carrier, Rf DC bias ---
Rint vc n1 25k
Cint n1 carrier 100n
Rf n1 carrier 1Meg
* ideal op-amp: gain 1e5, smooth output saturation at +/-10 V
Bint carrier 0 V = 10*(1e5*(0-V(n1)))/(1e-5+abs(1e5*(0-V(n1))))
* --- Non-inverting Schmitt trigger ---
* vp = (vcarrier/R1 + vc/R2)/(1/R1+1/R2)
* thresholds are -/+ (R1/R2)*Vsat = -/+1 V, giving a 2 Vpp triangle
R1 carrier vp 1k
R2 vc vp 10k
Cvp vp 0 1p
Bcomp vc 0 V = 10*(1e5*V(vp))/(1e-5+abs(1e5*V(vp)))
* start the integrator off-centre so the astable starts oscillating
.ic V(carrier)=1
.tran 1u 20m uic
.control
run
wrdata carrier.txt v(carrier)
.endc
.end1002.2 Hz and 1.99 V on the first render.
modeldeepseek/deepseek-v4.1-flashtaskspice-frother-triangle@v1date2026-09-22rounds1 of 8 allowedcost$0.0542thinkingmediumtokens674,500 in, 26,345 out, of which 18,145 reasoningtime8 min 3 s
DC supplies onlydecided by a number, from the filepass
1 kHzdecided by a number, from the filepass
2 V peak to peakdecided by a number, from the filepass
Straight, even rampsdecided by a number, from the filepass
There is no post about this one, since only some results need one, so the picture, the source and the scoring are here instead.
A milk frother's heater is driven by PWM, and the PWM needs a 1 kHz triangle-wave carrier of 2 V peak to peak. Build that oscillator in ngspice using only DC supplies, so the oscillation comes from the circuit itself, and simulate 20 ms. In a .control block, save the carrier voltage with wrdata to a .txt file so it can be plotted.Frozen at v1. This model got this and nothing else.
The netlist, re-run in ngspice offline and the written carrier read back. A triangle comes from integrating a square wave, so a PULSE into an RC, whose ramps curve, fails, and so does any source that is told the time. How it is scored, and this run's files on GitHub.

