ESP32 Bench
Boards: ESP32, S2, S3, C3, C6
Flash and monitor: Web Serial
← All projects

Ultrasonic theremin

Play music by waving your hand over an ultrasonic sensor. Closer is higher. Open the bench to watch distance and pitch chart live.

Intermediate20 min115200 baud
Board
Fig. 1. Pins this project uses on the ESP32-DevKitC V4, 38 pin. USB connector at the bottom.

Wiring

FromTo boardNote
HC-SR04 VCC5V
HC-SR04 GNDGND
HC-SR04 TRIGGPIO 5
HC-SR04 ECHO, through 1 kΩGPIO 18Add 2 kΩ from GPIO 18 to GND to drop the 5 V echo to 3.3 V
Buzzer +GPIO 25Buzzer - to GND

Tested on this board

Not run on this board yet. Treat the wiring and code as a first draft.

Firmware, Arduino sketch for ESP32 Dev Module

// Ultrasonic theremin: hand distance sets the pitch. Closer is higher.
const int TRIG = 5;
const int ECHO = 18;
const int BUZZER = 25;

const float NEAR_CM = 5;    // highest note here
const float FAR_CM = 60;    // lowest note here; further away is silence
const float LOW_HZ = 220;   // A3
const int OCTAVES = 3;      // up to A6
const bool SNAP = true;     // round to the nearest semitone, so it plays in tune

float readCm() {
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  unsigned long us = pulseIn(ECHO, HIGH, 25000);  // about 4 m round trip
  return us == 0 ? -1 : us * 0.0343f / 2;
}

void setup() {
  Serial.begin(115200);
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
  Serial.println("Theremin ready. Wave a hand 5 to 60 cm above the sensor.");
}

void loop() {
  float cm = readCm();
  int hz = 0;
  if (cm >= NEAR_CM && cm <= FAR_CM) {
    float f = LOW_HZ * powf(2.0f, (FAR_CM - cm) / (FAR_CM - NEAR_CM) * OCTAVES);
    if (SNAP) f = 440.0f * powf(2.0f, roundf(12 * log2f(f / 440.0f)) / 12.0f);
    hz = (int)(f + 0.5f);
    tone(BUZZER, hz);
  } else {
    noTone(BUZZER);
  }
  Serial.printf("distance_cm=%.1f, freq=%d\n", cm < 0 ? 0.0f : cm, hz);
  delay(60);
}

Parts

QuantityPartWhere to buy
1×ESP32 dev boardBuy at Amazon
1×HC-SR04 ultrasonic sensor
1×1 kΩ resistor
1×2 kΩ resistor
1×Passive buzzer or piezoBuy at Adafruit
7×Jumper wires

Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.

Libraries

None beyond the ESP32 Arduino core.

Load it

  1. In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
  2. Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
  3. Close the IDE's serial monitor, then open the bench here to watch the output.

Field notes

  • The HC-SR04's echo pin is 5 V. The 1 kΩ and 2 kΩ divider brings it down to about 3.3 V, the same as the HC-SR04 distance project.
  • Set SNAP to false for a smooth, swooping theremin sound instead of notes.
  • A flat hand works better than fingers: more surface sends back a stronger echo.
  • Open the bench at 115200 baud: the plotter charts distance_cm and freq side by side as you play.

Not tested yet

  • Not tested on hardware yet. Compiles for every board listed with Arduino-ESP32 core 3.3.12.

Built it? Send a build report with your board and what the serial port printed. Working reports become the "Tested on this board" entries above.