Engines: steam cylinders and multi-cylinder piston engines
@ferret/physics-engines (PLAN-DYNAMICS.md stage A10). Both engines are a torque source for a drivetrain shaft (d.drive(shaft, engine.torque)); the torque comes from the cycle, not from an averaged power, so the pulsation, the dead centre and the stall come out of the physics.
Steam#
SteamEngine({ bore, crank, rod, boiler, inlet, exhaustPort, back?, clearance?, phases?, gear?, reciprocatingMass?, mounts? }) is one or more double-acting SteamCylinders on one crank (phases: the crank pin of each; a locomotive has [0, π/2]).
- Each end of the cylinder is a mass of steam as a perfect gas (γ = 1.3, the model of
steamWork), fed from aBoilerthrough a port, exhausting toback(the atmosphere by default, or a condenser pressure). - The valve gear is a function of the crank angle:
gear = { cutoff, lead, release, compression, reverse }. Cut-off, release and compression are shares of the stroke;leadis a crank angle. The controls change the gear while the engine runs.reversetakes the events in the other turning direction, so the engine runs backwards. - Energy closes: the boiler gives up the steam's real enthalpy; the chamber gets the perfect-gas enthalpy
cp·T(the latent heat the model does not use leaves with the exhaust, as it does in a real engine) and doesp dVon the piston. The work per turn is the area of the indicator diagram, within 20 % of the ideal one for the cut-off (tested). - At standstill an open port still fills the chamber, so a two-cylinder engine at 90° starts from either dead centre; a single cylinder can stick on the centre.
Combustion#
MultiCylinderEngine({ cylinder: EngineSpec, count, order?, cycle?, reciprocatingMass?, mounts? }) puts count PistonEngines on one crank. order is the firing order from 1 ([1, 3, 4, 2]); each cylinder is shifted in the crank angle so that it fires at i·4π/n (firing lists the angles). The crank pins follow from the order.
Controls (also EngineControl, what the forms use): throttle(v), ignition(advance) (rad before top dead centre, moved while running), fuel(on) (off is the ignition cut), cutCylinder(i, cut).
Housings and mounts#
Give the shaft a housing (A0) and whatever the engine does to the shaft acts the other way on the block. engine.applyInertia(omega, theta, mount) puts the unbalanced forces of the reciprocating masses on the mounts: along each cylinder's axis at its point, -m·a of the piston at the shaft's speed. A single cylinder shakes at the first order; the primary forces of an inline four cancel and the secondary ones add (4·m·r·(r/l)·ω²).
In the language#
engineForms(bridge, { engines, boilers }) registers, with argument checks at load:
| word | |
|---|---|
(throttle e v) (cutoff e v) (reverse e on) (ignition e rad) (fuel e on) | controls; an engine without that control refuses the call |
(engine-rpm e) (pressure b) (level b) | sensors |
A centrifugal governor is a program: (loop (cutoff "engine" (clamp (+ 0.3 (* 0.03 (- 25 (speed-now)))) 0.1 0.9)) (wait 0.02)). A starter is a program that cranks until the engine catches: (seq (starter #t) (wait-until (> (engine-rpm "car") 700)) (starter #f)).