Code + Components¶
Hardware & Components
- Arduino UNO
- MAX30102 heart rate sensor
- Soil moisture sensor (analog)
- NeoPixel LED strip (WS2812B)
- L298N motor driver
- MOSFET module
- 2x 12V DC air pumps
- Mini air pump / air valve (for soft robotic flower)
- Soft robotic pneumatic flower
- 12V power supply
- USB cable
- Breadboard
- Jumper wires
- Air tubing
Software
- Arduino IDE
- Pure Data
- TouchDesigner
Control Unit¶
Control Unit¶
Laser-cut acrylic enclosure fabricated at FabLab Lisbon
Material: 4 mm transparent acrylic (550 × 550 mm sheet)
The enclosure integrates the electronic control system and pneumatic infrastructure.
Design considerations:
- Separation between 5V logic and 12V power lines
- Dedicated routing paths for air tubes
- Ventilation openings for heat dissipation
- Kerf compensation applied for precise slot fitting
The transparent structure keeps the system visible while providing mechanical stability and cable organization.
Arduino UNO — Pin Mapping¶
| Pin | Component | Function |
|---|---|---|
| A1 | Soil Moisture Sensor | Analog input (0–1023) |
| A4 | MAX30102 (SDA) | I2C data line |
| A5 | MAX30102 (SCL) | I2C clock line |
| D3 | MOSFET Module | Air valve control (digital) |
| D5 | NeoPixel LED Strip | Data signal (WS2812B) |
| D10 | L298N (IN3) | Pump IN / Inflate (PWM) |
| D11 | L298N (IN4) | Pump OUT / Deflate (PWM) |
| 5V | Sensors + LEDs | Power supply |
| GND | Common Ground | Shared reference |
| 12V | Pumps (via L298N) | External power supply |
Data Streams¶
Two parallel data streams feed the interactive system:
Arduino → Pure Data (Serial, 57600 baud) Soil moisture state, heartbeat detection, and IR intensity are packed and transmitted as a 6-channel frame.
Pocket Scion → Pure Data (OSC) Plant bioelectrical activity is received via OSC and mapped to sonic micro-variations.
Serial Frame (Arduino → Pure Data)¶
Protocol: Binary Serial
Baud Rate: 57600
Header: 0xC0
Update Rate: ~25 Hz (40 ms)
| Order | Variable | Range | Description |
|---|---|---|---|
| 1 | humidityValue | 0–1023 | Raw soil moisture value |
| 2 | humState | 0–2 | 0=DRY, 1=OK, 2=WET |
| 3 | fingerPresent | 0 / 1 | Heart sensor active detection |
| 4 | irStrength | 0–1023 | Normalized IR intensity |
| 5 | BEAT | 0 / 1 | Beat detection event |
| 6 | beatAvg | 0–220 BPM | Averaged heart rate |
Each value is packed as a 10-bit integer (two 7-bit-safe bytes).
OSC Frame (Pocket Scion → Pure Data)¶
Protocol: OSC (Open Sound Control)
Transport: Network / USB bridge
Source: Pocket Scion bioelectrical plant signal
| Address | Type | Description |
|---|---|---|
| /min | float | Minimum signal value in window |
| /max | float | Maximum signal value in window |
| /mean | float | Average signal value |
| /delta | float | Instant variation |
| /variance | float | Signal variability |
| /deviation | float | Standard deviation |
These values are mapped in Pure Data to modulate sonic texture and micro-variations.
Data Mapping — Signal to Expression¶
| Signal Source | Parameter | Affects |
|---|---|---|
| Soil Moisture | humState | Breathing mode (DRY/OK/WET) |
| Soil Moisture | humidityValue | LED chromatic base |
| Heartbeat | BEAT | Pneumatic pressure accent |
| Heartbeat | irStrength / beatAvg | LED wave amplitude |
| Pocket Scion (OSC) | mean / delta / variance | Sonic texture modulation |
| Arduino (Serial) | humState / BEAT | Sound structural parameters |
Coding¶
Arduino (Control Logic)¶
The Arduino firmware is structured around three main subsystems:
Sensor acquisition¶
- analogRead(A1) → soil moisture value (0–1023)
- MAX30105 library → IR signal acquisition
- checkForBeat() → beat detection
- Moving average (RATE_SIZE = 4) → BPM smoothing
- Dynamic normalization → heartNorm (0.0–1.0)
The variable humState is derived from threshold comparison:
- < DRY_THRESHOLD → HUM_DRY
- => WET_THRESHOLD → HUM_WET
- otherwise → HUM_OK
Pneumatic Control (PumpController)¶
Breathing behavior is implemented through a state-based controller:
pumps.setMode(humState);
Each mode (DRY / OK / WET) corresponds to a dedicated control routine with:
- Different PWM ranges
- Different timing durations
- Different pause structures
Heartbeat modulation is applied only when:
if (fingerPresent && BEAT) pumps.onBeat();
The function onBeat() activates a temporary boost envelope based on:
Sinusoidal shaping (heartEnvelope01)
Duration-dependent modulation
PWM increment proportional to heartNorm
This boost is added to the current base PWM values without replacing them.
LED Control¶
LED behavior is handled via the NeoPixel library.
Base color is selected according to humState.
When BEAT == true:
- A red wave is triggered
- Wave amplitude scales with heartNorm
- Position updates at fixed interval (WAVE_STEP_MS)
The LED logic runs independently but relies on the same behavioral variables.
Pure Data (Sound Engine)¶
Pure Data receives two parallel input streams:
-
Arduino Serial Stream (Binary)
-
6 packed values (10-bit each)
- Header 0xC0
- 57600 baud
- ~25 Hz update rate
These parameters are mapped to:
- State-based structural control
- Beat-triggered events
-
Intensity modulation
-
Pocket Scion OSC Stream
OSC messages provide continuous statistical descriptors of plant bioelectrical activity:
- /mean
- /delta
- /variance
- /deviation
These values are used as modulation signals for granular texture, filter variation, and micro-parameter fluctuation.

