Optical Music Device









 Building a custom optical music box requires an array of sensors that can distinguish between the white background of your paper and the dark ink of your dots, paired with a microcontroller to translate those visual changes into musical notes or MIDI data.

1.Select your optical sensors:Hardware.

You have two primary options for reading the black dots:

  • TCRT5000 IR Reflective Sensors: These are standard for line-following robots. They emit an IR beam and measure the reflection. White paper reflects the IR light well, while black ink absorbs it, giving you a sharp contrast.

2.Build the sensor array and paper guide:Mechanical setup.

Position one sensor for each "track" (musical note) you want to read on the paper strip. The sensors must be placed very close to the paper—usually 2 to 5 millimeters away—to get a reliable reading without bleeding into adjacent tracks.

You will need a rigid channel (which can be laser-cut, 3D printed, or built from layered cardboard) to keep the paper strip perfectly flat and aligned as it passes over or under the sensor array.

3.Wire the sensors to your microcontroller: Circuitry.

If using analog TCRT5000 modules or photoresistors, wire the sensor outputs to the analog pins on your microcontroller (e.g., A0 through A5). If using photoresistors, ensure you use a 10kΩ pull-down resistor for each to create a voltage divider, otherwise the analog pins will float and trigger false notes.

Verification: Before writing the audio code, write a simple sketch that uses Serial.print() to output the analog values of the sensors. Open the Serial Plotter or Monitor and slide a black dot over the sensor. You should see a distinct drop or spike in the numerical value.

4.Program the note-triggering logic:Code.

In your loop(), continuously read the analog pins. Establish a threshold value based on your Serial Monitor tests (e.g., < 500 indicates a black dot).

When a pin crosses the threshold, trigger the note. For the audio output, you can use an Arduino Pro Micro configured as a USB MIDI device to send noteOn and noteOff commands directly to a DAW like GarageBand. Alternatively, you can use an Arduino Mega stacked with a Sparkfun VS1053b Musical Instrument Shield to generate the audio in hardware using the SoftwareSerial library.

----------------------

Prompt: For a paper-strip electronic music player consisting consisting of an Arduino Mega, Sparkfun Music Instrument Shield, and paper tape reader with 8 TCRT Reflective IR light sensors, describe wiring and Arduino code that will play music via MIDI codes sent to the musical instrument shield as a paper tape with black dots is hand-cranked through the sensor array 


For a paper-strip electronic music player consisting consisting of an Arduino Mega, Sparkfun Music Instrument Shield, and paper tape reader with 8 TCRT Reflective IR light sensors, describe wiring and Arduino code that will play music via MIDI codes sent to the musical instrument shield as a paper tape with black dots is hand-cranked through the sensor array

To build a paper-strip music player, you need to configure the Arduino Mega to read the 8 TCRT5000 sensors, detect the edges of the black dots (so a note doesn't re-trigger continuously while a dot passes), and send standard MIDI serial commands to the Musical Instrument Shield.

Because the Sparkfun Musical Instrument Shield is an Arduino Uno-sized shield, it mounts directly on the front half of the Arduino Mega, leaving the extended digital pins (22–53) exposed and perfect for wiring the 8-sensor array.

1

Mount the Shield

Align the pins of the SparkFun Musical Instrument Shield with the Arduino Mega headers (starting at the 0/1 side) and press it firmly into place. The shield defaults to receiving MIDI data on pin D3 and uses pin D4 as a hardware reset.

2

Wire Sensor Power

Connect the VCC pins of all 8 TCRT5000 sensor modules to the Mega's 5V pin. Connect all 8 GND pins to the Mega's GND pins. Use a breadboard or terminal strip to distribute the power if your sensors don't have a daisy-chain capability.

3

Wire Sensor Data Pins

Connect the Digital Output (DO) of the 8 sensors to the Arduino Mega's extended digital pins D22 through D29. Note: Raw TCRT5000 phototransistors (without a breakout board) require a 10kΩ pull-up resistor on the signal pin, but standard modules have this built-in.

Arduino Code

This code uses state-change (edge) detection to ensure a MIDI "Note On" is only sent when the sensor transitions from white paper to a black dot, and a "Note Off" is sent when it transitions back to white.

When interfacing an Arduino Mega with the SparkFun Musical Instrument Shield (VS1053), the shield expects serial MIDI commands on Digital Pin 2 or 3 (default D3 via solder jumper) and uses Pin 4 for hardware reset. Because the Mega cannot map arbitrary hardware UART pins to D3 directly without rerouting, we use SoftwareSerial targeting pin 3 at the standard MIDI baud rate of 31,250 bps. 

Hardware Wiring Reference

Component

Arduino Mega Pin

Description

Musical Instrument Shield

Stacked on Mega

Uses D3 (MIDI RX on shield) and D4 (VS1053 Reset)

TCRT5000 IR 1–8 (DO pins)

Pins 22, 24, 26, 28, 30, 32, 34, 36

Digital output from sensor modules

TCRT5000 VCC / GND

5V rail / GND rail

Power for IR emitters/detectors

Optical Logic: TCRT5000 comparator breakout modules output HIGH over dark/cutout holes (no IR reflection) and LOW over white reflective paper tape (adjust the on-board potentiometers so holes reliably trip the state).


Key Operational Notes

* True Polyphony: Because each sensor independently evaluates state transitions through isNotePlaying[], any combination of the 8 notes can sound simultaneously or sustain independently without blocking the loop.

* Hardware UART Alternative: If you prefer avoiding SoftwareSerial, bend shield pin D3 out of the header so it doesn't plug into D3 on the Mega, and solder a jumper wire from shield pin D3 to TX1 (Pin 18) on the Mega. Then replace midiSerial with Serial1.begin(31250).

* Sensor Calibration: Adjust the blue trimpot on each TCRT5000 module until the onboard indicator LED switches crisply between dark paper/punched holes and reflective white tape.





 Polyphonic Laser Harp

 * Target: Arduino Mega 2560 + SparkFun Musical Instrument Shield (VS1053)

 * Communication: Hardware Serial1 (Pin 18 TX -> Shield RX)


#define VS1053_RESET 9
// Number of laser strings/beams
const uint8_t NUM_BEAMS = 8;
// Analog pins connected to voltage dividers
const uint8_t beamPins[NUM_BEAMS] = {A0, A1, A2, A3, A4, A5, A6, A7};
// MIDI note assignments (C Major scale: C4 to C5)
const uint8_t midiNotes[NUM_BEAMS] = {60, 62, 64, 65, 67, 69, 71, 72};
// Detection thresholds (0-1023)
// When hand blocks beam, light level drops below THRESHOLD_NOTE_ON

const int THRESHOLD_NOTE_ON = 350;
const int THRESHOLD_NOTE_OFF = 450; // Hysteresis prevents rapid re-triggering

// State tracking for polyphony

bool beamActive[NUM_BEAMS] = {false};

// MIDI Command Constants

const uint8_t MIDI_NOTE_ON = 0x90;
const uint8_t MIDI_NOTE_OFF = 0x80;
const uint8_t MIDI_CHAN_MSG = 0xB0;
const uint8_t MIDI_PROGRAM = 0xC0;

void sendMIDI(uint8_t status, uint8_t data1, uint8_t data2) {

Serial1.write(status);
Serial1.write(data1);
Serial1.write(data2);

}

void sendMIDI(uint8_t status, uint8_t data1) {

Serial1.write(status);
Serial1.write(data1);
}

void setupVS1053() {

pinMode(V1053_RESET, OUTPUT);
digitalWrite(VS1053_RESET, LOW);
delay(10);
digitalWrite(VS1053_RESET, HIGH);
delay(50);
// Set MIDI Master Volume (Channel 0, Controller 7, Value 127)

sendMIDI(0xB0, 0x07, 127);
// Set Instrument Patch (e.g., 46 = Orchestral Harp, 0 = Acoustic Grand Piano)
sendMIDI(MIDI_PROGRAM, 46);
}

void setup() {

// Debug monitor

Serial.begin(115200);
// MIDI standard baud rate via Arduino Mega TX1 (Pin 18)
Serial1.begin(31250);
setupVS1053();
Serial.println(F("Polyphonic Laser Harp Initialized."));
}

void loop() {
for (uint8_t i = 0; i < NUM_BEAMS; i++) {
int sensorValue = analogRead(beamPins[i]);

// Beam interruption detection (hand blocks beam -> sensor darkens)

if (!beamActive[i] && sensorValue < THRESHOLD_NOTE_ON) {
beamActive[i] = true;
sendMIDI(MIDI_NOTE_ON, midiNotes[i], 110); // Note On, Channel 0, Velocity 110

#ifdef DEBUG
Serial.print(F("Beam "));
Serial.print(i);
Serial.println(F(" ON"));
#endif
}
// Beam restoration (hand removed -> sensor brightens)
else if (beamActive[i] && sensorValue > THRESHOLD_NOTE_OFF) {
beamActive[i] = false;
sendMIDI(MIDI_NOTE_OFF, midiNotes[i], 0); // Note Off, Channel 0

#ifdef DEBUG
Serial.print(F("Beam "));
Serial.print(i);
Serial.println(F(" OFF"));
#endif
}
}
}

No comments:

Post a Comment

Nov 3rd Class- Experimenting with Neopixels; MIDI Prototyping

Above: Kerem makes calculations...  The planned projects seemed to have coalesced into two projects: Project 1(Stanley-Kexin-Rohan) is a clo...