Introduction: Making Songs With an Arduino and a DC Motor
The other day, while scrolling through some articles about Arduino, I spotted an interesting project which used Arduino-controlled stepper motors to create short melodies. The Arduino used a PWM (Pulse Width Modulation) pin to run the stepper motor at specific frequencies, corresponding to musical notes. By timing which frequencies played when, a clear melody could be heard from the stepper motor.
However, when I tried it out myself, I found that the stepper motor I have can’t rotate fast enough to create a tone. Instead, I used a DC motor, which is relatively simple to program and connect to an Arduino. A common L293D IC can be used to easily drive the motor from an Arduino PWM pin, and the native tone() function in Arduino can generate the necessary frequency. To my surprise, I did not find any examples or projects using a DC motor online, and so this Instructables is my response to remedy that. Let’s get started!
P.S. I assume that you already have some experience with the Arduino and are familiar with its programming language and hardware. You should know what arrays are, what PWM is and how to use it, and how voltage and current work, just to name a few things. If you are not there yet or just began Arduino, don’t worry: try this getting started page from the official Arduino website and come back whenever you’re ready. :)
- Arduino (I used an UNO but you can use a different Arduino if you’d like)
- Standard 5V DC Motor, preferably one able to have a fan attached (see picture in "Assembling the Circuit"
- L293D IC
- As many push buttons as notes in the song you want to play
- Jumper Wires
Step 1: Overview
Here's how the project works: the Arduino will generate a square wave at a given frequency, which it outputs to the L293D. The L293D is hooked up to an external power supply which it uses to power the motor at the frequency it is given by the Arduino. By preventing the DC motor's shaft from rotating, the motor can be heard turning off and on at the frequency, which produces a tone, or note. We can program the Arduino to play notes when buttons are pressed, or to automatically play them.
Step 2: Assembling the Circuit
To assemble the circuit, simply follow the Fritzing diagram above.
Tip: The note from the motor is best heard when the shaft is not spinning. I put a fan on the shaft of my motor and used some duct tape to hold the fan still while the motor ran (see picture). This prevented the shaft from turning and produced a clear, audible tone. You may have to do some tweaking to get a clean tone from your motor.
Step 3: How the Circuit Works
The L293D is an IC used for driving relatively high voltage, high current devices such as relays and motors. The Arduino is unable to drive most motors directly from its output (and the back EMF from the motor can damage the Arduino's sensitive digital circuitry), so an IC like the L293D can be used with an external power supply to easily drive the DC motor. Inputting a signal into the L293D will output the same signal to the DC motor without risking damage to the Arduino.
Above is a pinout/functional schematic of the L293D from its datasheet. Since we are only driving 1 motor (the L293D can drive 2), we only need one side of the IC. Pin 8 is power, pins 4 and 5 are GND, pin 1 is the PWM output from the Arduino, and pins 2 and 7 control the direction of the motor. When pin 2 is HIGH and pin 7 is LOW, the motor spins one way, and when pin 2 is LOW and pin 7 is HIGH, the motor spins the other way. Since we don’t care which way the motor spins, it doesn’t matter if pins 2 and 7 are LOW or HIGH, as long as they are different from each other. Pins 3 and 6 connect to the motor. You can connect everything to the other side (pins 9-16) if you wish, but be aware that the power and PWM pins switch places.
Note: If you are using an Arduino which doesn’t have enough pins for each button, you can use a network of resistors to connect all of the switches to one analog pin, such as in this instructables. How this works is outside the scope of this project, but if you’ve ever used an R-2R DAC you should find it familiar. Note that using an analog pin will require large portions of the code to be rewritten, as the Button library can’t be used with analog pins.
Step 4: How the Code Works
To make it easier to handle all the buttons, I used a library called “Button” by madleech. I included the library first thing. Next, in lines 8-22, I defined the frequencies for the notes needed to play Twinkle, Twinkle, Little Star (the example song), the pin I’ll use to drive the L293D, and the buttons.
In the setup function, I initialized the Serial, the buttons, and set the driver pin for the L293D to output mode.
Finally, in the main loop I checked to see if a button has been pressed. If it has, the Arduino plays the corresponding note and prints the note name to the Serial Monitor (useful for knowing which notes are which on your breadboard). If a note is released, the arduino stops any sound with noTone().
Unfortunately, due to the way the library is structured, I could not find a way to check if a button has been pressed or released in a less verbose way than using 2 conditionals per note. Another flaw with this code is that if you were to press two buttons simultaneously and then release one of them, both notes would be stopped, because noTone() stops any notes being generated regardless of which note triggered it.
Step 5: Programming a Song
Instead of using buttons to play notes, you can also program the Arduino to play a melody for you automatically. Here is a modified version of the first sketch which plays Twinkle, Twinkle, Little Star on the motor. The first part of the sketch is the same - defining note frequencies and the tonePin. We get to the new part at bpm="100". I set the beats per minute (bpm), and then use some math to figure out the number of milliseconds per beat that the bpm equates to. To do this, I used a technique called dimensional analysis (don’t worry - it’s not as hard as it sounds). If you’ve ever taken a high school chemistry course, you definitely used dimensional analysis to convert between units. The floats() are there to ensure that nothing in the equation is rounded until the very end for accuracy.
After we have the number of ms/beat, I divided or multiplied it appropriately to find the millisecond values of the different note durations found in music. I then make an array of every note in chronological order, and another one with the duration of each note. It is critical that the index of each note matches the index of its duration, otherwise, your melody will sound off. I put in the notes for Twinkle, Twinkle, Little Star here as an example but you can try any song or sequence of notes you’d like.
The real magic happens in the loop function. For each of the notes, I play the tone for a time I specified in the beat_values array. Instead of using delay here, which would cause the tone to not be played, I recorded the time since the program started with the millis() function, and subtract it from the current time. When the time exceeds the time I specified the note to last in the beat_values array, I stop the note. The delay after the for loop is there to add a gap between notes, ensuring that subsequent notes with the same frequency won’t blend together.
Step 6: Feedback
That’s it for this project. If there is something you don’t understand, or if you have any suggestions, please don’t hesitate to contact me. As this is my first Instructables, I would greatly appreciate comments and suggestions about how to improve this content. See you next time!
2 years ago on Step 5
Am I supposed to use DC motors or Stepper motors?? L293D is meant to drive stepper motors as I know..
Reply 2 years ago
DC Motors are what I used. According to the datasheet (https://www.ti.com/lit/ds/symlink/l293.pdf), the L293D can actually drive many types of inductive loads, including both DC and stepper motors.
3 years ago
Thanks for sharing! : )