Skip to content

troutstar/esp32-cyd-system_testing_suite

Repository files navigation

Test Harness

A second CYD module running separate firmware for pitch detection validation. It connects to WiFi and exposes an HTTP API that streams every detection frame — algorithm internals, ground truth comparison, and runtime parameter control — accessible from any machine on the network.

Why This Exists

Validating pitch detection accuracy from serial logs is too slow and too opaque. The test harness lets you:

  • See every detection in real time, including the full NSDF curve internals
  • Compare detected Hz against ground truth from a known audio source
  • Tune algorithm parameters (threshold, smoothing, frequency bounds) at runtime without reflashing
  • Inject synthetic frequencies directly over HTTP for controlled single-frequency tests
  • Collect rolling statistics (mean, std, min, max) across hundreds of frames
  • Watch the strobe display behave identically to the main device while gathering data

Hardware

Same CYD module as the main device. The LCD displays the strobe pattern using the same display.c driver as the main firmware. The test harness runs the full audio→pitch→display pipeline plus WiFi and HTTP on top.


WiFi Setup

Credentials are not in the source. Before building:

  1. Copy main/wifi_credentials.h.example to main/wifi_credentials.h
  2. Fill in your SSID and password
#define WIFI_SSID  "your_network_name"
#define WIFI_PASS  "your_password"

wifi_credentials.h is gitignored — it will never be committed.

On boot the device connects, then registers as cydtuner-test.local via mDNS. All endpoints are reachable at either http://cydtuner-test.local or the IP printed to serial.


Audio Sources

The test harness supports two audio sources, switchable at runtime:

WAV file (default)

Reads sweep.wav from the SD card root. Generate the file with:

cd tools
python gen_tuning_sim.py
# rename tuning_sim.wav to sweep.wav and copy to SD card

The WAV contains discrete plucks at known deviations per string — no continuous sweeps. Each pluck pops immediately to a fixed frequency and decays naturally, matching real guitar tuning behaviour.

Synthetic sine wave

A software-generated sine wave at a tunable frequency. Useful for single-frequency accuracy testing without needing an SD card.

Switch sources via POST /source.


HTTP API

All responses are application/json.

GET /params

Current algorithm parameters.

{"threshold_coeff":0.8000,"pitch_min_hz":40.0,"pitch_max_hz":1200.0,"smooth_alpha":0.0000}

POST /params

Update parameters (partial JSON accepted — omitted fields unchanged).

curl -X POST http://cydtuner-test.local/params -d '{"threshold_coeff":0.75}'

GET /snapshot

Full frame including the complete NSDF curve (~20 KB). Useful for inspecting algorithm behaviour at a specific moment.

curl http://cydtuner-test.local/snapshot > snapshot.json

GET /stats

Rolling statistics over the last 200 frames.

{
  "n": 200, "n_detected": 185, "n_with_gt": 180,
  "detected_hz": {"mean": 55.012, "std": 0.043, "min": 54.9, "max": 55.1},
  "cents_error": {"mean": 0.038, "std": 0.412, "min": -1.2, "max": 1.1},
  "nsdf_peak_val": {"mean": 0.921, "std": 0.018}
}

GET /history?n=N

Last N compact frames (default 50, max 200), in chronological order.

curl "http://cydtuner-test.local/history?n=100"

POST /history/clear

Reset the ring buffer.

GET /source

Current audio source.

{"source":"wav"}

POST /source

Switch audio source. Switching to wav seeks back to the start of the file.

curl -X POST http://cydtuner-test.local/source -d '{"source":"synth"}'
curl -X POST http://cydtuner-test.local/source -d '{"source":"wav"}'

GET /synth

Current synth frequency (0 if source is not synth).

POST /synth

Set synth frequency.

curl -X POST http://cydtuner-test.local/synth -d '{"hz":440.0}'

GET /diag

System diagnostics: uptime, heap, DMA memory, task stack high-water marks, queue depth.

{
  "uptime_ms": 45231,
  "heap_free": 142000, "heap_min": 138000,
  "dma_free": 62000, "dma_min": 60000,
  "sample_q_waiting": 0, "buf_sem_count": 1,
  "audio_stack_hwm": 1024, "pitch_stack_hwm": 2048, "display_stack_hwm": 980
}

GET /ws

WebSocket endpoint. Pushes compact frames at ~10 Hz to all connected clients. Each message is a JSON object with the same fields as a history entry.


Ground Truth

When playing sweep.wav (generated by gen_tuning_sim.py), the test harness knows the expected Hz at every point in the file. Each frame includes:

  • ground_truth_hz — expected Hz from the schedule (0 during silence or transient)
  • cents_error1200 * log2(detected / ground_truth) when both are non-zero

The first 300ms of each pluck is excluded from ground truth (pick transient). /stats reports aggregate cents error across all frames with ground truth.


Build and Flash

Requires ESP-IDF 5.5. From the test_harness/ directory:

idf.py build
idf.py -p COMx flash monitor

After boot, the green LED turns on and the IP address is printed to serial.

About

Testing suite for ESP32 CYD (cheap yellow displays) capabilities via web for higher resolution than a serial connection can provide.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors