Skip to content

LLM Resources

Spectral: light as an instrument โ€‹

Every other layer in this library listens. This one asks.

The central problem in plant electrophysiology is equifinality: different causes produce the same waveform. A thirsty plant and a malnourished one can look identical on a single electrode, and no amount of passive sensing separates them.

So stop waiting for the plant to volunteer an ambiguous signal. Excite one photoreceptor pathway at a time and read what comes back. Blue reaches the guard cells, red reaches Photosystem II, green reaches the tissue neither of them touches โ€” and the pattern across colours is diagnostic in a way no single channel can be.

js
await plant.useSpectral( { light : { driver : 'mock' } } )   // or serial / mqtt / callback

const sweep = await plant.interrogate()
console.log( sweep.summary )
๐ŸŸ  Amber  (590nm) โ†’ baseline: control channel
๐Ÿ”ต Blue   (450nm) โ†’ stomatal_response: weak (1.6ร— control, SNR 6.2)
   Blunted or delayed response: ABA is holding the stomata shut, which means water stress.
๐Ÿ”ด Red    (660nm) โ†’ photosynthetic_response: strong (5.1ร— control, SNR 21.4)
   Electron transport is efficient; the photosynthetic apparatus is intact.

Cross-band diagnosis:
  water stress (80%)
    ยท blue probe blunted (amplitude 2, 1.6ร— control) โ€” stomata are not opening
    ยท red probe normal (10) โ€” the photosynthetic apparatus is intact

What each colour does to a plant โ€‹

BandPhotoreceptor๐Ÿ” As a probe, it reads๐Ÿ’Š As a treatment, it doesRisk
๐ŸŸฃUV-B 300nmUVR8never probed โ€” DNA-damagingFlavonoid synthesis, thicker cuticle, pathogen resistance๐Ÿ”ด critical
๐ŸŸชUV-A 380nmCryptochrome, phototropinCryptochrome responseCompacts leaf expansion, raises pigment density๐ŸŸก medium
๐Ÿ”ตBlue 450nmPhototropin, cryptochromeStomatal competence โ†’ hydration & turgorForces stomata open, raising transpiration๐ŸŸ  high
๐ŸŸขGreen 530nmWeakly absorbed โ†’ penetratesDeep mesophyll โ†’ the lower canopyLights inner canopy nothing else reaches๐ŸŸข low
๐ŸŸ Amber 590nmMinimalThe control channel โ€” what "no stimulus" looks likeWorking light for the camera, minimal perturbation๐ŸŸข low
๐Ÿ”ดRed 660nmChlorophyll a/b, Photosystem IIElectron transport โ†’ photosynthetic capacityDrives ATP/NADPH synthesis and carbon fixation๐ŸŸก medium
๐ŸŸฅFar-red 730nmPhytochrome (Pfrโ†’Pr)Phytochrome stateStem elongation, end-of-day signal, flowering๐ŸŸ  high
โฌ›NIR 940nmnone โ€” thermal onlynever probed โ€” no receptorRadiant warming without photosynthesis๐ŸŸ  high

The diagnostic that needs two colours โ€‹

This is the whole point:

Blue probeRed probeConclusion
๐Ÿ”ต weak๐Ÿ”ด strongWater stress. Stomata shut while photosynthesis is fine โ€” that is ABA-mediated closure, not damage.
๐Ÿ”ต strong๐Ÿ”ด weakNutrient deficiency. Water is adequate but electron transport is impaired: N, Mg, Fe, or photosystem damage.
๐Ÿ”ต weak๐Ÿ”ด weakSevere stress โ€” or a bad electrode. The system says so rather than guessing.
๐Ÿ”ต strong๐Ÿ”ด strongNo cross-band pattern. The pathways agree.

Add ๐ŸŸข green and you also see the lower canopy: a healthy top with a quiet interior means self-shading or senescing lower leaves.

Waveform distortion with amplitude preserved โ€” a harmonic ratio above 0.5 โ€” flags ionic imbalance (often salinity) before any visible symptom.

Minutes, not milliseconds โ€‹

The single fact that decides whether any of this works:

Stomatal opening takes 5 to 30 minutes.

So the blue probe runs on a 16-minute period, not a flicker. A probe faster than its pathway measures the noise floor and returns a confident-looking zero โ€” which is worse than an error, because you would believe it.

The system refuses rather than letting that happen quietly:

js
await plant.spectral.probe( 'blue', { periodMinutes : 0.008 } )   // 2 Hz
// Error: A 0.008min period gives a 0.0min pulse, but the blue pathway needs
//        at least 5min to respond. The probe would read noise, not the plant.

Each band carries the period its own physiology allows: ๐Ÿ”ด red 8min ยท ๐ŸŸ  amber 10min ยท ๐ŸŸช UV-A 12min ยท ๐Ÿ”ต blue 16min ยท ๐ŸŸข green 20min ยท ๐ŸŸฅ far-red 30min.

How the measurement works โ€‹

Drive the plant with a periodic light/dark cycle and the surface potential locks to that period, forming a carrier. The plant's internal state then appears as modulation of that carrier โ€” which is far easier to detect than a transient you have to catch.

  • Phase locking โ€” power concentrated at the stimulus frequency, with an SNR against the surrounding noise floor. This is what separates a real evoked response from drift that happened to coincide.
  • Cycle folding โ€” every cycle averaged onto one. Uncorrelated noise falls as 1/โˆšN while the locked response survives, so twelve cycles recover a signal buried under twice its own amplitude in noise.
  • Harmonic content โ€” distortion rises when a pathway saturates or is stressed, carrying information the fundamental alone does not.
  • Everything relative to the ๐ŸŸ  amber control, because absolute millivolts depend on electrode placement and contact impedance and are not comparable across sessions, let alone across plants.

Safety: the interlocks โ€‹

Light is the one actuator here that can damage a plant while looking like care. A pump that overruns floods visibly; a lamp that forces stomata open on a drought-stressed plant kills it quietly while the log says "treatment applied".

So treatment is decided by arithmetic, never by a model's confidence:

js
await plant.spectral.treat( 'blue', { seconds : 300, context : plant.context() } )
// REFUSED: The plant closed its stomata to conserve water. Forcing them open
//          with blue light overrides that defence and accelerates dehydration.
InterlockRule
๐Ÿ”ต Blue on dry soilHard refusal. Soil under 30%, humidity under 25%, or over 32ยฐC. The plant closed its stomata to survive.
Missing dataBlocks. undefined < 30 is false, so an absent soil sensor must never silently permit the treatment that most needs it.
๐ŸŸฃ UV-BExplicit human authorization, 15 min/day, capped intensity. Eye and skin hazard โ€” the warning says so.
๐ŸŸฅ Far-redBlocked by default. It induces shade-avoidance elongation, which weakens an indoor plant.
Dose budgetsPer band, per day, reset at midnight. Authorizations expire with the day too.
Dark periodProtected. The circadian rhythm is a health signal the rest of the library reads; irradiating through the night destroys it.

Probes are held to the dose budget but not to the treatment interlocks: a four-minute blue pulse reads the stomata, it does not force them.

Hardware โ€‹

Any multi-channel LED works. The driver's only job is to emit channel intensities and report honestly what it actually did.

js
await plant.useSpectral( {
  light : { driver : 'serial', path : '/dev/ttyUSB0' },   // an ESP32 driving LED channels
} )
DriverFor
mockNo hardware โ€” the whole stack is testable and demonstrable
serialESP32 / Arduino, one JSON line per command
mqttESPHome, Tasmota, Zigbee2MQTT
callbackPhilips Hue, DMX, WLED, GPIO PWM โ€” anything with its own SDK

A fixture declares which bands it has; requesting a channel it lacks is an error, not a silent no-op. Calibrated fixtures can declare irradiance per channel and the dose ledger will use photon flux; without calibration the system tracks time rather than pretending to know ยตmolยทmโปยฒยทsโปยน.

Feeding the rest of the system โ€‹

Spectral findings enter the evidence ledger as an independent source, because they come from controlled excitation rather than from the same passive channel everything else reads. That is what lets a high-risk action clear its corroboration requirement honestly:

js
await plant.embody()
await plant.interrogate()

plant.justifies( 'water_stress', RISK.HIGH )
// now backed by soil, vision *and* spectral โ€” three independent sources

Full example: lib/examples/06-spectral-probe.js, and the @smartplant/spectrum plugin wraps all of it.