Dancing Machine involves a skeleton figure moving its arms and legs to the cues of musical tones played by a 4-buttoned keyboard. On each button press, a distinct sound is generated and all 4 limbs of the skeleton move in clockwise/anticlockwise motion.
- 1x Arduino Leonardo
- 1x Breadboard
- 4x Push Buttons
- 4x TowerPro Servo Motor SG92R Micro or Micro Servo 9g SG90
- 1x 3V Piezo Buzzer
- 1x 220Ω resistor
- 3x 10KΩ resistor
- 3X AA batteries, 1.5V each
- Battery holder for 3 AA batteries
Optional materials - you can design your model using other methods! These are the supplies and equipment I used:
- 3D Printer
- Superglue
- 23X25 cm cardboard
- Box with holes for letting push buttons through
- Toy/doll/Robot model with light, movable arms and legs
- Crocodile clips
- Spare conducting wires
Anytime I've had to tell someone what my idea is, this scene would be one of the first things that would come to my mind. This is a dance sequence from a movie called "Moonwalker". It has the robot/dancing machine as the character that I wanted to bring to life with this project. Having a keyboard that produced different tones seemed like the most accessible way of playing music for the robot to dance to. I decided to piece the two ideas together by making a robotic figure that "dances" to a musical keyboard.
Before the project's inception, I had already looked through a book uploaded on my module's page which coincidentally mentioned an example of a keyboard. That became my primary starting point to implement a keyboard first. More specifically, the "keyboard" referenced there is an analog monophonic (produces a melody only one at a time – like being able to play a key on the piano at once) synthesizer.
I thought one of the simplest ways of recreating the robotic motion would be through servos. I knew from my previous classes that their motion resembled robotic, stiff movements in angles and also made a classic machine-y sound when their motor operated. I decided I wanted to add at least 4 servos to the project which controlled four major movements of the body: two arms and two legs.
I first began with the keyboard instrument example from the project book I had. This was the original circuit:
I tried working it out simply with two buttons first.
My first button wasn't working at the time which, to the best of my memory, was because I couldn't recognize the right digital output for it. I was still trying to wrap my head around a lot of the concepts being employed in the sketch, such as the resistor ladder, wiring and circuit diagram, and working with the serial monitor, just to make sure I knew what was going on under the hood. As a result I also couldn't figure out my mistakes right away. Meanwhile, the second button produced a clean, clear tone as demonstrated in the video.
I added two more keys and completed the entire circuit but still had the issue of buttons not working – this time being the first and second ones. One of the reasons was the selection of resistors: the original example used 3 different resistors (220Ω, 2x 10KΩ, 1MΩ), but at the time I substituted them for 1x 220Ω and 3x 10KΩ resistors. The lack of variation probably contributed to the fact that distinct values weren't generated for each button press. This prevented each button from producing its unique sound. A lot of the values for the first two buttons had an overlap in the monitor, explaining why sound wouldn't be produced at all sometimes. I chose my resistors in specific simply because I didn't have access to other ones back then, and continued using them as I just ended up working my way around them in case of any issues. In this case (first two buttons not working), I found a convenient split in the range of values generated by the two buttons, making it clearer when and what sound would be produced. There were also minor errors such as insufficiently populating the array of frequencies to be played by the buzzer.
In the end I also added some code where a new sound is produced when pressing two buttons at the same time (the first two here).
When I added my first servo to the circuit, none of my keys made any sound. As an alternative, I tried controlling the servo's movements by activating it only when I pressed a button. I thought it would probably fix the issue of no sound since the servo's addition somehow influenced the analog values being generated in the circuit. But it was really a confusing time for me since I couldn't pinpoint where the problem actually originated – experimenting with my code was the only way I could get some direction. At one point the solution simply came out to be the wiring not being fixed hard enough into the breadboard and pins.
Soon, I did get my keys all working again, but I still had to figure out cuing the servo on button presses. For the moment I simply hard coded the servo to sweep an angle every time the button's analog value was detected.
At the time, I also made a decision to change my servo pin to analog inputs than use digital ones. Unfortunately, I cannot remember with much certainty why I chose to do that back then. Yet my best guess is that I thought using analog inputs for both the buttons and servos would ensure better compatibility or communication between the two. I still need to research more on that matter to gain a better understanding of what difference it really makes.
Before moving any further, I wanted to create more dynamic way of sweeping the servos. I created two angle variables that decreased and increased their values linearly, with every button press, so that their angle changed itself with the next shift. I also added the time_atsweep variable to track how many seconds elapsed since the last button press. This was useful when the arms reached 0 or 180 degrees, as I reset them in the opposite directions after approximately 3 seconds of staying at 0/180 degree limits.
https://create.arduino.cc/editor/apizzafromfrance/c513ccd3-7d41-43ae-8f9a-840c042c8175/preview (My code at the time)
Both motors had been using the Arduino's power supply so far and I had to use an external power supply from that point on to add on 2 more servos. I discussed with a technician and was advised to use 3 AA batteries (1.5V each) to power all 4 servos. I just had to replicate some of the previous tasks here: join the ground and positive terminals of batteries and servos to their respective power rails, connect servos' signal wires to analog pins, etc.
Now that I added 4 servos for the 4 main movements of 2 arms and 2 legs of the robot, this was the stage to start assembling the physical model as the face of the project. I made a 3D design to illustrate my visual in mind and also drew some rough sketches to pan out how the circuit components would act in conjunction with the physical parts.
The bottom face sketch was simply a back-up plan of mine to execute in case only two of my servos worked. It was supposed to be a talking face of some sort with the lips as servos.
https://www.tinkercad.com/things/bbsFaMjLRqO
I changed the cylinder body and spherical face to skeleton parts since it resembled the original dancing machine more. The black box is supposed to be the rough visualization of the musical keyboard, having 4 buttons. Below I added the skeleton's hips, thighs and shoulders. At first I was struggling to finalize how the robot would come out. I had a wooden mannequin in mind where I would attach the servos to the limbs, but this all needed a lot of external support or scaffolding to hold itself. Moreover, I was skeptical whether the limbs would be light enough for the servo arms to move them. While designing in Tinkercad, it already seemed like a good idea to just have the exact replica of my designs 3-d printed. I was also able to customize the dimensions and scaling of all the parts to fit the circuit around.
https://www.tinkercad.com/things/b1HcHxQ1YpmArms and legs: https://www.tinkercad.com/things/dJ5YFFO9ECT
Despite these measures I still wished to change a lot of things as I didn't think everything through unfortunately! For instance, the keyboard box was too squarish and compact to fit the breadboard, Arduino, and all the wiring inside. The holes I punctured for the switches also had to be drilled larger later on since there were minor fitting problems. I knew that I could glue most parts together just in case the fittings weren't ideal, which did happen, but the glue also wasn't very efficient. A lot of times it would easily scrape off of surfaces and I had to reapply it numerous times. In addition, this was my first time doing 3D printing and I didn't see a lot of issues coming through. My box began printing normally and the whole process was very smooth, but printing the arms and legs took about 4 tries to even get the machine running right!
A resistor ladder in combination with buttons is used here. It creates a voltage divider circuit, wherein pressing each button can sort of toggle its specific voltage. The resultant voltage produced is an analog signal which feeds into the "A0" analog input pin on the Arduino board. This pin converts analog values to digital values between 0 and 1023. The serial monitor which comes along with the Arduino displays all serial communication between your computer and Arduino; it is where all the analog-to-digital values will be shown. As a result, each switch press will generate its corresponding number, anywhere between 0 and 1023, in the monitor. These numbers accordingly trigger a sound through the piezo buzzer in the circuit - this part is externally coded into the circuit using if/else statements. When the specific value for each press is recognized, the Arduino tells the buzzer to produce a certain frequency at that instant (the sound wave is a square wave). The tone() function accepts the desired frequency as input and sends it to the same pin used as the output by the buzzer.
Within those same if/else statements, I've placed the code for moving the servos. With every press of the switch, the servos change their angle dynamically: I created two variables which increase and decrease their values linearly at every press. There is separate code at the end which resets the angles in the opposite direction once they reach their limit in the servo (0 or 180 deg).
I have attached three AA batteries, each 1.5V, for powering the 4 servos.
This was my first run through after having all my models printed. The circuit and code work just as before (I didn't change anything) but the only problems boiled down to the assembly/set up itself. Connecting the alligator clips to the switches and then back to the breadboard was a hard task. The switch terminals and sockets in breadboards were all coalesced into one place, so introducing relatively large clips was rather difficult. Another problem that I encountered (as shown in the video) was how the erratic the sounds were. Sometimes the buzzer would be silent, but otherwise it would beep the whole time. When I would move the box along with the wiring inside, it would abruptly set the buzzer on and off without any keyboard input. My best guess is that it was mainly due to the raw metal wire connecting the clips to the breadboard in place of all the buttons (left picture). Since they were all exposed and remained very close to each other, I trimmed them down and twisted them apart so the connections were clear. As soon as this change was made, things looked much better. The buzzer wasn't constantly on and only worked when a button was pressed.
I recorded a video with this result which I'm unable to show here, but ultimately the arms and legs operate on cue of the sounds much more accurately. The dancing machine is ready!
The code for this project was primarily adapted from the book "Arduino Projects Book", example "Keyboard Instrument" on page 79.
Presently, it has evolved into the current project's demands.
Link to the book: https://www.eitkw.com/wp-content/uploads/2020/03/Arduino_Projects_Book.pdf
Following are other links that my code and circuit used during the development of the project:
https://github.com/v-a-s-t/CCI_PhysicalComputing_week3/blob/main/Servo_bb.pdf
(Sketch to add a servo to the circuit)
https://github.com/v-a-s-t/CCI_PhysicalComputing_week3/blob/main/03_Button_Echo/03_Button_Echo.ino
(Adapted this code to make the servo move only on button presses)