Once upon a time, it was exam week at my university. I think most of my exams must have been over because I was slowly writing this inefficient but functional code forever. Anyways, my roommate and I had just ordered a bunch of ATMega328 chips along with a bunch of other electronics. I was trying to think of a way to use them, so I did this.
With the two official Arduinos my roommate and I had and the four chips I immediately breadboarded into Arduino clones, there were 6 Arduinos at my disposal. You know what has six parts? "Sumer Is Icumen In". It's a middle English round that we sing a lot. It bothers everyone around us, but with this new technology, the annoyance possibilities were endless.
So I went and did this. It's my first foray into multiple arduino interaction. Each Arduino plays its part on its own speaker. There's a movie of the results at the bottom. The sound quality is rather deplorable because it's recorded on my laptop's microphone. College did that to my recording resources. I may add another video if I can get a hold of my roommate's arduino again.
And a last bit of self-promotion. Instructables is awesome and has cool contests. You know what's cooler than contests? Winning contests. Vote for your favorite instructables in the Arduino contest if and only if that's this instructable (I'm kidding, of course). Check out the other things people have done with Arduinos and enter your own instructable at https://www.instructables.com/contest/arduino2013/
Step 1: Before We Begin …
First, if you haven't messed with Arduinos before, this isn't a good first instructable for you. I recommend that you go to arduino.cc and spend a while in their reference and forums or search Instructables for something like LED blinking or simple tone() functions. My first program involved making an LED blink in patterns, so we all start somewhere. Play with the tone() function and make sure you can make a speaker work. Also, if this is your first Arduino instructable, why do you have 6 Arduinos?
Second, I don't have 6 official Arduinos. I made a bunch of breadboard Arduinos. See the link in materials. This complicates some things and might make it difficult if you aren't using a breadboard Arduino. The worst part is that I built 4 Arduinos on the same breadboard with one reset button and a common power. (Instructable to follow?) This is hella confusing and I apologize for the ensuing confusion.
Step 2: Materials
-A way to program those Arduinos. http://arduino.cc/en/Tutorial/ArduinoToBreadboard the Arduino programming software, and a flat to square USB
-Assorted resistors (used to equalize volume for non-identical speakers)
-9V pover source (optional; the USB connection may be enough to power them all if you connect their power pins. See step 6.)
I apologize for the image quality. You get the idea … I hope.
Step 3: Code
You don't have to read this unless you want to mess with what it's playing or make your own. If you like middle English rounds, then you can skip this.
Instructables won't attach my .ino files. Instead, I'm going to use patebin.com. It's a cool place where you just put text or code and people can see it and copy it out. It's great.
Part 5: the syncing one: http://pastebin.com/uUEDBbew
Parts 1-4: http://pastebin.com/UZHmVzSr
And Part 6: http://pastebin.com/7MK8h4tQ
Part 5 is the controlling board. It sends out a sync pulse for the shortest duration of the notes.
There are two big arrays that contain the notes. The first one contains the frequency in Hz. The second contains the duration in terms of the sync pulse speed. There's extra spaces in the array because on the last note, the program will still be looking for the start time of the next note to stop. The program converts this into start time of each note because that just seems to work better. I'm not that good of a programmer, if you couldn't tell.
Part 5 waits in a while loop until all the other boards send a ready signal when they're done processing the big arrays.
Okay, we're done waiting for the other boards. The microseconds() function returns the microseconds since the program started. It converts frequency into period. It will write HIGH to the speaker for a fraction of the period, write LOW, then wait for the period to end. This will make a square wave (with adjustable duty cycle). Once the total run time of the program reaches some multiple of the sync pulse period, part 5 writes HIGH to the other boards to signal the next beat. It writes LOW again after a while. Once the correct number of beats passes, it moves on to the next pitch.
The other boards are easier. They count beats instead of microseconds. Using the same square wave process, they wait until the correct number of beats pass, then move to the next note.
Step 4: The Controller Board
Upload the Part 5 code to it (see step 3 for pastebin link). I chose the 5th part of Sumer Is Icumen In for the controller because it wasn't doing much in the ways of notes. It turns out that any part could have done it well, though.
At the top of the code, there are variables for the speed of the sync pulses (temp) (use the beat per minute of the shortest note duration, in this case, 8th notes), pitches of each note in Hz (float pitch[ ]), and duration (unsigned int time[ ])of each note in multiples of the time variable I mentioned earlier.
Put a jumper wire in pin 7. This sends a sync pulse out to the other boards at the tempo rate t.
Put a jumper wire in pin 8 and connect it to a speaker in series with a resistor to ground. The value of the resistor determines the volume of the speaker. If you have 6 potentiometers, you could use those for adjustment.
Put a jumper wire in pins 9-13. These are for a ready signal all the other boards send back once they've finished the initialization code. The controller board waits until everyone is ready.
Step 5: All the Other Boards
Connect pin 8 to the speaker. I used a breadboard to add a series resistor to equalize the volumes out of my speakers. The value of the resistor is experimentally determined once all the speakers are playing.
Connect pin 7 to the controller board's pin 7. Use a breadboard to accommodate all five boards connecting to one pin on the controller.
Connect the five wires from pins 9-13 of the controller board to pin 6 of each of the other boards. The controller board waits until each board sends a ready signal from their pin 6 before beginning the song.
Step 6: Okay, Now Plug It In.
I don't have a close-up from when I had all 6 Arduinos together, unfortunately. There are 5 here, so it gets the point across. It also goes to show that jumper wires tend to make a big rat's nest, so be careful how you're wiring.
If you are using fewer (or more) Arduinos, go into part 5 and remove (or add) an input pin at the beginning of void setup() and the corresponding digitalRead in the last while loop in the void setup() code.
Plug them in. Hit the reset on the controller board and then reset all the other ones if they don't start.
Step 7: Troubleshooting
If it doesn't work: uh oh. Check your wiring. You might want to just start it over if the jumper wires start getting tangled. Check that the ready signal wires (pin 6 to pins 9-13 on the controller) and the sync pulse wires (all pin 7s are connected together) are all properly connected. Check that the speakers are all connected to a signal and ground through a resistor. Check the power to each board. If one board is un-powered or isn't sending its ready signal correctly, the song will never start.