Built-in project · Arduino Uno R3

Music box on an Arduino Uno

A tune on an 8 ohm speaker through 100 ohms, a continuous-rotation servo turning the drum, and a coin vibration motor on a transistor buzzing on the beat. The whole build, an Arduino Uno and 7 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

IntermediateRuns in your browser. Free, and no account needed.

Music box · Arduino Uno R3live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Music box: a tune, a turning drum, and a buzz on the beat.
//
//   pin 8  the speaker, through 100 ohms (its other tag to GND)
//   pin 9  the continuous-rotation servo's signal
//   pin 6  the vibration motor's transistor, through 1 k to its base
//
// Three outputs that all move something, and each needs driving differently.
//
// The speaker is eight ohms. A pin across eight ohms is nearly a short, so it
// goes through 100 ohms, as in the Arduino's own melody example: about 46 mA,
// and a note you can hear. The note is a square wave made the way mokxiTone
// makes one: toggle the pin, wait, for as long as the note lasts.
//
// The servo is the continuous kind: the pulse is a speed, not an angle. 90 is
// stopped, 180 is full speed one way, 0 the other. 100 is a slow turn, and the
// servo keeps it until it is told something else.
//
// The vibration motor wants 75 mA and at least 2.3 V to start, so a 2N2222
// switches it off the Uno's 3.3 V pin, near its rated 3 V, with a diode across
// it for the kick a real motor gives when its current stops.

#include "mokxi_servo.h"
#include "mokxi_tone.h"

const int SPEAKER = 8;
const int DRUM = 9;
const int BUZZ = 6;

Servo drum(DRUM);
bool forwards = true;

// Twinkle, twinkle: a note and its length in eighths.
const uint16_t NOTES[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_G4,
                          349,     349,     NOTE_E4, NOTE_E4, 294,     294,     NOTE_C4};
const uint8_t LENGTHS[] = {2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 4};
const int COUNT = sizeof(LENGTHS);

const uint16_t EIGHTH_MS = 150;

// Half a cycle of the note: the pin to one level, then a wait. Out of line on
// purpose. Inlined, delayMicroseconds() makes the loop below too long for the
// AVR's short branches and the link fails; as a call it is one rcall.
__attribute__((noinline)) void half(uint8_t level, uint16_t us) {
  digitalWrite(SPEAKER, level);
  delayMicroseconds(us);
}

// One note of `ms` milliseconds: what mokxiTone does, a square wave made by
// toggling the pin and waiting, spelled out here so it can be read.
void play(uint16_t hz, uint16_t ms) {
  uint16_t us = (uint16_t)(500000uL / hz);
  uint32_t cycles = ((uint32_t)ms * 1000uL) / (2uL * us);
  for (uint32_t i = 0; i < cycles; i++) {
    half(HIGH, us);
    half(LOW, us);
  }
}

void setup() {
  pinMode(BUZZ, OUTPUT);
  digitalWrite(BUZZ, LOW);
  pinMode(SPEAKER, OUTPUT);
  Serial.begin(115200);
  Serial.println("Mokxi Uno: a music box");
  drum.begin();
  drum.write(100);   // a slow turn
}

void loop() {
  for (int i = 0; i < COUNT; i++) {
    // A buzz on the first beat of every bar.
    digitalWrite(BUZZ, i % 4 == 0 ? HIGH : LOW);
    play(NOTES[i], LENGTHS[i] * EIGHTH_MS - 30);
    digitalWrite(BUZZ, LOW);
    delay(30);
  }
  forwards = !forwards;
  Serial.println(forwards ? "once more, forwards" : "once more, the drum the other way");
  drum.write(forwards ? 100 : 80);
  delay(600);
}

Parts list

9 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

10 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Arduino Uno R3 pin 9; Hobby servo pin PWM
  • Arduino Uno R3 pin 8; Resistor, 100 Ω pin 1
  • Arduino Uno R3 pin 6; Resistor, 1k Ω pin 1
  • Arduino Uno R3 pin 3V3; Diode pin C; Vibration motor pin 1
  • Arduino Uno R3 pin 5V; Hobby servo pin VCC
  • Ground: Arduino Uno R3 pin GND; Transistor (NPN or PNP) pin E; Speaker, 8 ohm pin 2
  • Ground: Arduino Uno R3 pin GND; Hobby servo pin GND
  • Transistor (NPN or PNP) pin C; Diode pin A; Vibration motor pin 2
  • Transistor (NPN or PNP) pin B; Resistor, 1k Ω pin 2
  • Resistor, 100 Ω pin 2; Speaker, 8 ohm pin 1

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.