Programming a Resonant Cube with Python and Arduino

Introduction

Acoustic metamaterials can be programmed by mechanically altering their boundary conditions. In this post, I’ll show how I used Python and Arduino to control a cube with a servo motor, excite it with a 50 Hz tone, record its resonance, and classify its spectral fingerprints into symbolic logic outputs.

Hardware Setup

Cube experimental setup

Software Workflow

  1. Servo Control: Python sends commands (UNSTRETCHED or STRETCHED) to Arduino.
  2. Excitation: Python generates a 50 Hz sine wave and plays it through a speaker.
  3. Recording: Microphone captures the cube’s response.
  4. FFT Analysis: Python computes the frequency spectrum.
  5. Classification: Peaks are mapped to symbolic codes (A, C, etc.).

Python Code


import serial, time
import sounddevice as sd
import numpy as np
from scipy.signal import find_peaks

ser = serial.Serial('COM3', 115200)
fs = 44100
duration = 5.0
excitation_freq = 50.0

# Excitation signal
t = np.linspace(0, duration, int(fs*duration), endpoint=False)
signal = np.sin(2*np.pi*excitation_freq*t)

def excite_and_record(label):
    ser.write((label + "\n").encode())
    time.sleep(2)
    print(f"Exciting cube at {excitation_freq} Hz in {label} mode...")
    recording = sd.playrec(signal, samplerate=fs, channels=1, dtype='float64')
    sd.wait()
    samples = recording.flatten()
    fft_vals = np.abs(np.fft.rfft(samples))
    freqs = np.fft.rfftfreq(len(samples), d=1/fs)
    peaks, _ = find_peaks(fft_vals, height=np.max(fft_vals)*0.2)
    peak_freqs = freqs[peaks]
    print(f"{label} peaks: {np.round(peak_freqs,1)} Hz")
    return peak_freqs

def classify_output(peaks):
    peaks = list(peaks)
    if any(9 < p < 14 for p in peaks) or any(30 < p < 36 for p in peaks):
        return "A"
    elif any(abs(p-50)<2 for p in peaks) and any(140 < p < 210 for p in peaks):
        return "C"
    elif any(abs(p-50)<2 for p in peaks):
        return "C"
    else:
        return "?"

while True:
    peaks_un = excite_and_record("UNSTRETCHED")
    code_un = classify_output(peaks_un)
    print(f"UNSTRETCHED logic output: {code_un}")
    time.sleep(5)
    peaks_st = excite_and_record("STRETCHED")
    code_st = classify_output(peaks_st)
    print(f"STRETCHED logic output: {code_st}")
    time.sleep(5)

Results

- Unstretched mode often produces low-frequency clusters (≈12–33 Hz) → classified as A.
- Stretched mode produces strong 50 Hz + harmonics (≈150–200 Hz) → classified as C.
- Sometimes both states collapse to a single 50 Hz peak, still classified as C.

Cube resonance spectrum overlay
Overlay of unstretched vs. stretched resonance spectra.

Multi-Cycle Analysis

By running multiple cycles and plotting spectra, we can demonstrate repeatability. Here’s an example of overlaying multiple cycles:

Cube resonance spectrum across cycles
Resonance spectra across multiple cycles showing reproducibility.

Extended Spectrum

Beyond the 50 Hz excitation, the cube shows a rich resonance landscape with multiple peaks between 80 Hz and 400 Hz. This broader spectrum highlights how stretching alters not just the fundamental mode but also higher harmonics.

Cube resonance spectrum full range
Full resonance spectrum of the cube, showing multiple peaks across 0–600 Hz.

Conclusion

This workflow turns a resonant cube into a programmable element: servo input → resonance fingerprint → symbolic logic output. By expanding the codebook and combining multiple cubes, you can build logic gates and analogue computing structures. This is a powerful way to explore how physical systems can be programmed through resonance.

Live Experiment Output

To make the process more tangible, here’s a snapshot of the Python script running and classifying resonance peaks into logic outputs:

Python script terminal output
Terminal output showing detected peaks and logic classification for UNSTRETCHED and STRETCHED modes.

In this run, the cube alternated between modes, producing fingerprints such as [24.0, 50.0] Hz (classified as C) and [11.6, 12.0, 12.6, 13.0, 20.6, 49.0, 50.0, 100.2, 150.2, 200.2, 300.2] Hz (classified as A). This demonstrates how the cube’s resonance spectrum can be interpreted as programmable logic outputs in real time.

Wrap-Up

From servo control to FFT analysis, the resonant cube can be programmed to output symbolic codes based on its acoustic fingerprints. Adding live output screenshots alongside plots gives readers both the quantitative and experiential view of the experiment. This combination of hardware, software, and resonance analysis makes for a compelling blog post on programmable acoustic metamaterials.