HOLLY JOLLY ROBOT
Have a Holly, Jolly Robot…
What You’ll Need
What You’ll Learn About
A sumo robot kit
Programming the Buzzer
Writing Functions
A wall-socket USB power supply
Reading from the Distance Sensor
Blinking the LED
Project Requirements
To create a festive holiday spirit, we’re going to turn our MRK-2 Sumo Robot into a joyful holiday motion-activated decoration that plays a randomly selected Christmas tune whenever someone walks in front of the robot.
Our major requirements for this project are:
- Detect if an object is detected within three feet of the front ultrasonic sensor.
- If an object is detected, randomly select a song to play.
- Play the song.
- Blink the LED each time we play a note.
This project requires the Pitches.h header file first introduced in Chapter 5 of An Introduction to Robot Programming. If you need to get this file, you can find it on Github at https://github.com/SumoRobotLeague/MRK-2/blob/master/Chapter_5/Lesson_5.2/Pitches.h
Setup Your Project
To begin programming the Holly Jolly Robot, fire up your Arduino editor and create a new project. When you first load the editor with a new project, you should see the editor and an empty sketch with the following code:
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
First, click the small down arrow to the far right of the editor and click “New Tab”. You’ll be prompted to enter a name for this new file and you’ll want to name this “Pitches.h”. In this new tab, paste in the full contents of the code found in the Github repository.
Switch back to your primary tab and save the sketch by clicking “File >> Save” in the top menu. Since this is a new project, Arduino will ask you what you want to name your project. Enter something fun like “HollyJollyRobot” and hit enter.
To speed things along, copy the project template below into your Arduino editor and save your project again. Most of the code below should be familiar if you’ve previously worked through the book “An Introduction to Robot Programming” and are familiar with programming your MRK-2. After pasting this code into your editor, save your project and get ready to get festive!
#include "Pitches.h"
/************************/
/** PIN CONFIGURATIONS **/
/************************/
#define led 13
#define buzzer 3
#define echoPin A0
#define pingPin 10
// roughly three feet
#define christmasDistance 91
void setup() {
pinMode(led, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(pingPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// See if an object is in front of us
int distance = msToCm(ping());
if ( distance < christmasDistance ) {
// get a random song
// play the song
}
}
void playSong(int song) {
// our music goes here
}
// Note-playing buzzer helper function.
void playNote(int note, int duration, float rest) {
// our note player goes here
}
/**********************/
/** Helper Functions **/
/**********************/
// Helper function to manage our ultrasonic sensor.
long ping() {
long duration;
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
duration = pulseIn(echoPin, HIGH);
return duration;
}
// Helper function to return the distance to an object
// detected by the ultrasonic sensor in centimeters.
long msToCm(long microseconds) {
return microseconds / 29 / 2;
}
// Simple blink function called in loop() whenever a state
// change is made by a user button press.
void blink(int blinks) {
for ( int i = 0; i <= blinks; i++ ) {
digitalWrite(led, HIGH);
delay(250);
digitalWrite(led, LOW);
delay(250);
}
}
Randomly Picking Songs
As with all Arduino-based projects, most of the action starts in the loop() built-in function. In the previous step, we pasted in code that contained the following code:
void loop() {
// See if an object is in front of us
int distance = msToCm(ping());
if ( distance < christmasDistance ) {
// get a random song
// play the song
}
}
The first line of real code measures the distance in front of the robot. We call the helper function ping() and convert the echo response time into centimeters and then store that distance into an integer variable called “distance”.
The next line of code is an “if block” that checks that distance variable to see if the value is less than the number of centimeters that we’ve specified as our robot’s range.
The first new concept that we’re going to introduce is random number picking. We want to pick a random number and play a song. In later steps, we’re going to learn how to write songs, but for now we need to just pick a random number between 1 and 4. Arduino C++ has a function called “random(MIN, MAX)” that returns a random integer. This function returns a value that includes the MIN argument, but excludes the MAX argument.
random(1,4) - can return 1, 2, 3
random(4,8) - can return 4, 5, 6, 7
random(4,9) - can return 4, 5, 6, 7, 8
We’re going to write three songs in the next step, but to pick the song we need to get a 1, 2, or 3 from our random function.
void loop() {
// See if an object is in front of us
int distance = msToCm(ping());
if ( distance < christmasDistance ) {
// get a random song
int song = random(1, 4);
// play the song
}
}
If you later decide to write more songs, you’ll want to change the 4 to some other number, but always remember to have the MAX value be one higher than the total number of songs you’ve defined.
Playing Notes
Our project template had a function stub called “playNote(int note, int duration, float rest)” pre-defined and ready for us to code.
// Note-playing buzzer helper function.
void playNote(int note, int duration, float rest) {
// our note player goes here
}
The first thing that will put us in the holiday spirit is turning on the LED whenever we are playing a note, and turning it off as soon as we’ve finished. This will let our little robot happily blink along with the music.
// Note-playing buzzer helper function.
void playNote(int note, int duration, float rest) {
// our note player goes here
digitalWrite(led, HIGH);
}
This line of code will turn on the LED at the start of each note.
To actually play the tone, we’ll use the built-in Arduino function “tone(BUZZER_PIN, NOTE, DURATION)”.
// Note-playing buzzer helper function.
void playNote(int note, int duration, float rest) {
// our note player goes here
digitalWrite(led, HIGH);
tone(buzzer, note, duration);
}
If you called playNote() inside your loop() with a line of code like this:
playNote(NOTE_G5, 200, 2);
Your robot would beep for 200 milliseconds every time the loop() function runs which should end up sounding like a non-stop beeeeeeeeeeeeeep.
Now that we have our robot buzzing like a bee in the key of G, let’s turn this buzz into the beginnings of a music player.
To have each note chime off as a separate individual note, we need to force the Arduino to stop executing as fast as it can in each note. To do this, we need to use the delay() function to force the Arduino to take a break before speeding off to its next action.
The playNote() function has a third argument of “rest”, which we’ve defined as a float.
For the purposes of this tutorial, we’re going to keep things simple and just multiply duration by the rest and pass that to delay. To give our blinker time to blink, we’re going to divide that number by two, then turn off the LED, and then delay again with the second half of our delay.
The whole playNote function should now look like this:
// Note-playing buzzer helper function.
void playNote(int note, int duration, float rest) {
digitalWrite(led, HIGH);
tone(buzzer, note, duration);
delay((duration * rest)/2);
digitalWrite(led, LOW);
delay((duration * rest)/2);
}
Playing Songs
Now that we have a method to play songs, we need a function to write our sheet music and call our playNote function.
Inside the playSong() function, we’ll want to write a song switcher. Because we’ve randomly selected a song inside the loop(), we’ll want to play a different depending on the value we’ve passed in to the function.
void playSong(int song) {
// our music goes here
if ( song == 1 ) {
} else if ( song == 2 ) {
} else if ( song == 3 ) {
}
}
This simple if block will give us space to write our Christmas tunes. For song one, we’re going to have our robot play “Oh Come, All Ye Faithful” and “Hark the Herald Angels Sing” as song two.
void playSong(int song) {
// our music goes here
if ( song == 1 ) {
// Oh Come, All Ye Faithful
// ggdgadbabCba
playNote(NOTE_G5, 200, 2);
playNote(NOTE_G5, 400, 2);
playNote(NOTE_D5, 200, 2);
playNote(NOTE_G5, 200, 2);
playNote(NOTE_A5, 400, 2);
playNote(NOTE_D5, 400, 2);
playNote(NOTE_B5, 200, 2);
playNote(NOTE_A5, 200, 2);
playNote(NOTE_B5, 200, 2);
playNote(NOTE_C6, 200, 2);
playNote(NOTE_B5, 400, 2);
playNote(NOTE_A5, 400, 2);
} else if ( song == 2 ) {
// Hark the Herald Angels Sing
// cffefaagCCCa#aga
playNote(NOTE_C5, 200, 2);
playNote(NOTE_F5, 200, 2);
playNote(NOTE_F5, 400, 1.5);
playNote(NOTE_E5, 200, 2);
playNote(NOTE_F5, 200, 2);
playNote(NOTE_A5, 200, 2);
playNote(NOTE_A5, 200, 2);
playNote(NOTE_G5, 200, 2);
playNote(NOTE_C6, 200, 2);
playNote(NOTE_C6, 200, 2);
playNote(NOTE_C6, 200, 2);
playNote(NOTE_AS5, 200, 2);
playNote(NOTE_A5, 200, 2);
playNote(NOTE_G5, 200, 2);
playNote(NOTE_A5, 400, 2);
} else if ( song == 3 ) {
}
}
Once you’ve added these two songs, you can activate your robots music by calling playSong(song) inside your loop() function.
void loop() {
// See if an object is in front of us
int distance = msToCm(ping());
if ( distance < christmasDistance ) {
// get a random song
int song = random(1, 4);
// play the song
playSong(song);
}
}
To finish your Holly Jolly Robot, you need to compose a third song. You can make up any song you want, or write in Jingle Bells with the following notes:
// eeeeeeegcde fffffeeeeddedg
Play around with the note duration and rest length until you figure out the right mix for wonderful music.
Future Experimentation
You have just created a wonderful Christmas decorative robot. Now you’re ready to conquer the world with your Christmas spirit, so try writing code to have your robot drive around your house and only play music when it runs into an obstacle, then pick a new direction and drive off in search of more people to infect with joy.
On behalf of Sumo Robot League -- Merry Christmas and Happy Holidays!
Full source code can be found at:
https://github.com/SumoRobotLeague/HollyJollyRobot
Click on the link to GitHub.
https://github.com/SumoRobotLeague/HollyJollyRobot