A tiny musical instrument. Turn the knob of the rotary encoder and the passive buzzer plays the next note up or down the scale. Press the knob and it plays a short tune that starts from the note you picked. Along the way you learn how rotary encoders work, the knobs used in car radios and 3D printers.
What you need
- UNO R3 board and USB cable
- Rotary encoder module (45-in-1 Sensor Kit)
- Passive buzzer module (45-in-1 Sensor Kit)
- Breadboard and jumper wires (not included in the Sensor Kit: use the ones from the UNO R3 Starter Kit or any others)
Wiring

| From | To |
|---|---|
| Encoder CLK | UNO pin 2 |
| Encoder DT | UNO pin 3 |
| Encoder SW (push button) | UNO pin 4 |
| Encoder + | 5V (breadboard + rail) |
| Encoder GND | GND (breadboard − rail) |
| Passive buzzer S | UNO pin 8 |
| Passive buzzer − | GND |
| Passive buzzer middle pin | Not needed |
Pin labels differ between module versions. Always follow the labels printed on your module.
Use the passive buzzer module here: it can play different notes. The active buzzer can only beep at one pitch.
Build it step by step
- Wire the encoder and the passive buzzer module as in the diagram.
- Upload the code and open the Serial Monitor at 9600 baud.
- Turn the knob slowly. Each click plays the next note and shows its name.
- Press the knob to play a tune starting from the selected note.
The code
const int CLK_PIN = 2;
const int DT_PIN = 3;
const int SW_PIN = 4;
const int BUZZER_PIN = 8;
// One octave of the C major scale (frequencies in Hz)
const int NOTES[8] = {262, 294, 330, 349, 392, 440, 494, 523};
const char* NAMES[8] = {"C", "D", "E", "F", "G", "A", "B", "high C"};
int note = 0;
int lastClk;
void setup() {
Serial.begin(9600);
pinMode(CLK_PIN, INPUT); // the module has its own pull-up resistors
pinMode(DT_PIN, INPUT);
pinMode(SW_PIN, INPUT_PULLUP); // pressed = LOW
lastClk = digitalRead(CLK_PIN);
Serial.println("Turn the knob to pick a note, press it to play");
}
void playTune() {
// Climb up the scale from the chosen note, then back down
for (int i = note; i < 8; i++) { tone(BUZZER_PIN, NOTES[i], 180); delay(220); }
for (int i = 7; i >= note; i--) { tone(BUZZER_PIN, NOTES[i], 180); delay(220); }
noTone(BUZZER_PIN);
}
void loop() {
int clk = digitalRead(CLK_PIN);
if (clk != lastClk && clk == LOW) { // one click of the knob
if (digitalRead(DT_PIN) != clk) note++; // clockwise
else note--; // anticlockwise
note = constrain(note, 0, 7);
tone(BUZZER_PIN, NOTES[note], 150);
Serial.println(NAMES[note]);
}
lastClk = clk;
if (digitalRead(SW_PIN) == LOW) {
playTune();
while (digitalRead(SW_PIN) == LOW) delay(10); // wait until released
}
}
How it works
Inside a rotary encoder, two switches (CLK and DT) open and close as you turn the knob, slightly out of step with each other. When CLK changes, the sketch checks DT: if it's different from CLK the knob turned clockwise, if it's the same it turned anticlockwise. tone() makes the passive buzzer vibrate at a chosen frequency: 262 times per second sounds like the note C, 440 like A.
Make it your own
- Add a second octave and let the knob go higher.
- Program your own melody into
playTune(). - Use the encoder to set the brightness of the RGB LED module instead.
Troubleshooting
- Notes skip or go the wrong way: swap the CLK and DT wires, or turn the knob more slowly.
- The buzzer only clicks: you may have the active buzzer. Use the passive one.
- Pressing does nothing: check the SW wire on pin 4.
Learn the basics first
New to these parts? These lessons explain them step by step: Make a tilt alarm with a buzzer and Set up the Arduino IDE and blink an LED.
0 comments