Make Your Own Arduino-Powered Deskbot Pal - Lesson 5: Programming for Interactive Response

Desktop Pal, with "stereo" vision using two ultrasonic sensorsDesktop Pal, with "stereo" vision using two ultrasonic sensors
Arduino-Powered Deskbot Pal – Lesson 1: Assembly Arduino-Powered Desktop Pal – Lesson 2: Program Setup and Testing Arduino-Powered Desktop Pal – Lesson 3: Integrating the Servos, Ultrasonic, and Switch Arduino-Powered Desktop Pal – Lesson 4: Adding “Stereo” Ultrasonic Vision Arduino-Powered Deskbot Pal - Lesson 5: Programming for Interactive Response Desktop Pal is an animatronic friend, powered by an Arduino-compatible microcontroller and a small assortment of basic sensors. Using two servos for movement, Pal’s head moves up and down and side to side, reacting to objects that come nearby. This is Lesson 5 of the Desktop Pal series. If you’re just starting with the project, you’ll want to begin with Lesson 1, Make Your Own Arduino-Powered Deskbot Pal. In this installment you’ll learn how to program the Desktop Pal so it integrates all of its components – motors, switches, and sensors – to work together as a single unit.  You can download the Arduino sketch for this lesson from the following link.

Getting the File Download

Download this archive, and extract the individual folder inside to your Arduino sketchbook. Important! You must also download and install several Arduino libraries, required by the sketches in this installment. These libraries are provided in Lesson 3, so if you’ve been following along in this series, you should already have them. This lesson does not require any additional libraries other than those provided for in Lesson 3. Remember When adding new libraries, you must exit the Arduino IDE if it is open. Once you have copied he library files to the Arduino sketchbook libraries folder, you may restart the Arduino IDE.

Fusing the Components and Code

In the previous installments, you learned about Desktop Pal’s various components, and you ran test code with those components to verify operation. This is a good practice for any project: test each piece of the puzzle to make sure everything works.  Building a full robot by trying to program everything all at once can lead to mistakes and lots of frustration; the by-the-piece method is a lot easier in the end. Desktop Pal contains the following core components.
  • Foam ball head with two micro servos. One servo pans the head back and forth, while the other servo tilts the head up and down. The servos are simply glued together to form this pan-tilt or X/Y arrangement.
The servo motors of the Desktop Pal are glues together to make a pan-tilt pairThe servo motors of the Desktop Pal are glues together to make a pan-tilt pair
  • Two ultrasonic distance sensors, spaced about 5 inches apart, to create a kind of stereo vision. By using two sensors, the Desktop Pal can react to objects positioned to the left, right, or center. During regular operation, the two sensors constantly send out sonic pings to determine if something is nearby.
  • A pushbutton switch acts as a controller to turn Desktop Pal on and off. The switch doesn’t actually alter the power to the Itead Leonardo board; instead, it acts as a mode selector to put the robot to “sleep.” In sleep mode, the robot’s servos and sensors are disabled. Pushing this button again leaves sleep mode, and Desktop Pal comes back to life.
  • A small passive infrared (PIR) sensor detects motion. This sensor is used to control a secondary mode called “doze.” When dozing, Desktop Pal’s servos stop, and its ultrasonic sensors pause their constant ranging. The doze mode ends when the PIR is triggered.
  • Because Desktop Pal’s microcontroller board is tucked inside an enclosure, there’s no way to use the Itead Leonardo’s indicator lights to check for status. Instead, a small self-contained electronic buzzer is connected to the same Arduino pin as the standard Pin13 LED. Whenever this LED flashes, the buzzer emits a tone. In addition to serving as a Pin13 LED replacement, the buzzer is also used to make quick chirping sounds whenever Desktop Pal detects an object.
Main Components of Desktop PalMain Components of Desktop Pal

Inside the PalLookAround Sketch

All the various functions of the Desktop Pal are combined in the PalLookAround.ino sketch. Download the sketch to your Arduino sketchbook, open it in the Arduino IDE, and upload it to your Desktop Pal. Note When uploading, it’s normal for the Pin13 LED to flash – this denotes upload progress. During this time, the electronic buzzer will warble, letting you know uploading is in progress. Desktop Pal will then emit a single short tone, as well as flash the LED on the side pushbutton switch, to indicate that the sketch is loading and ready to run. The main loop of the PalLookAround sketch does the following:
  • When no objects are detected in front of the Desktop Pal, the pan servo is slowly rotated so the head scans side-to-side. This makes it look like the robot is looking around the room.
  • When an object is detected by either ultrasonic sensor, the slow panning motion is temporarily interrupted. The pan servo is positioned toward the ultrasonic sensor that registers the closest proximity to the detected object, and the electronic buzzer emits a short chirp to signal detection.
  • The tilt servo moves the head upward, as an additional cue suggesting that Desktop Pal is “looking up” at the object in front of it (human, cat, zombie, whatever).
  • One half second after the object moves away, the slow servo scan resumes.
Several software timers are used to control Desktop Pal’s operation. These timers are provided by two add-in libraries: SimpleTimer and Metro. See Lesson 3: Integrating the Servos, Ultrasonic, and Switch for more details on how these timers are implemented in the Desktop Pal sketch. A SimpleTimer timer is used to control the slow-motion sweeping of the pan servo. Every time this timer is triggered, the pan servo moves (approximately) one degree clockwise or counter-clockwise. A Metro timer controls the direction of the pan servo. The timer is set to reverse the direction of the servo every seven seconds. Another Metro timer controls Desktop Pal’s "doze" mode. Whenever this timer is triggered, it updates a counting variable that keeps track of the number of elapsed “ticks.” When the ticks reach a certain number, Desktop Pal enters doze mode. It reawakens when the PIR sensor detects nearby motion.

Adjusting Events and Timer Delays

In previous installments I showed how to go about using the various timers individually. Examining each timer by itself is a useful way of experimenting with how the timers work, but it doesn’t take into consideration the combined effects of all the timers working together. It also doesn’t reflect real-world limitations of working with hardware like the ultrasonic sensors, which require a certain minimum reaction time in order to properly function. So for PalLookAround, all the timer delays have to be adjusted from the examples in the previous installments. This allows the system to work cooperatively. For example, rather than a 50 millisecond delay between scan movement of the pan servo, the delay is now just one 1 millisecond. The main reason for the resetting of the timers comes from the multiple firing of the ultrasonic sensors. These sensors work by measuring the time delay between an outgoing burst of sound, and when its echo is returned. According to the datasheet for the sensors, the maximum echo time is 38 milliseconds; therefore the sketch must wait a minimum of 38 ms before obtaining a reliable result. What’s more, I’ve opted to filter out erroneous sensor measurements by taking successive readings, and averaging out the results . Since there are two sensors, the time it takes to acquire multiple readings from both sensors defines a minimum baseline for the main loop in the sketch. The sketch can’t loop through any faster than this. As a compromise between accuracy and animatronic operation, I elected to reduce the number of averaged ultrasonic readings from three to two. Given two sensors, with a 40 millisecond gap between firing them (to avoid cross-talk in any returned echoes), this leaves a minimum time delay – or “tick” -- of about 200 milliseconds. This minimum “tick” duration mostly affects the time delay for putting Desktop Pal into doze mode, as well as the delay for moving the pan servo. As noted above, the pan servo is now triggered at 1ms intervals. The doze mode is set to 120 “ticks,” or about 24 seconds. The doze delay is set in this part of the code:
if (dozer++ >= 120) {
  doze = true;
You can change the amount of time before Desktop Pal dozes off by changing the number 120 to another value.

Mapping Servo Positions from Ultrasonic Distances

To give Desktop Pal a more anthropomorphic feel, the readings from the ultrasonic sensors are used to move the pan servo to the approximate left/right/center position of the object that has been detected. This is accomplished with just a few lines of code, thanks to the Arduino map statement. Here’s the relevant code from the sketch:
int sonicValR = getUltrasonic(ultrasonicR);
delay (40);
int sonicValL = getUltrasonic(ultrasonicL);
if (sonicValL < triggerDistance || sonicValR < triggerDistance) {
  int mapper = 0;
  if (sonicValR - sonicValL < 0) {
    mapper = map(sonicValR, 2, triggerRange, panRight, panNeutral);
    makeTone(5, 50);
  } else {
    mapper = map(sonicValL, 2, triggerRange, panLeft, panNeutral);
    makeTone(75, 50);
First, distance measurements are obtained from the right and left ultrasonic sensors. These values are stored in the sonicValR and sonicValL variables, respectively. Note The 40 millisecond delay between sensor readings ensures that there is no cross-talk between the detectors. The line
if (sonicValL < triggerDistance || sonicValR < triggerDistance)
checks if the detected object is within a preset trigger distance, in this case 50 centimeters. If either detector has registered an object under this threshold, Desktop Pal reacts to it. Depending on whether the object is situated more close to the right or left sensor, the sketch processes the distance measurement using either of two map functions. The Arduino map function translate one set of value into another set of values. This acts to correlate the results from the ultrasonic sensors – values of about 2 to 50 – into position values for the pan servo. These position values span a range from 90 degrees (center or neutral) to either:
  • 60 degrees, if the object registers more closely to the left ultrasonic sensor, or
  • 120 degrees, if the object registers more closely to the right ultrasonic sensor.
Once the new position of the pan servo has been calculated, the sketch then updates both the pan and tilt servo with this code:
currentPanPosition = mapper;
Take note of the line
currentPanPosition = mapper;
The currentPanPosition variable holds the current position of the pan servo when Desktop Pal is slowly scanning back and forth. By updating this variable with the new position of the pan servo, your Pal’s head doesn’t snap to some other place when the slow scan mode is resumed.

Altering the Tone of the Electronic Buzzer

The electronic buzzer module is designed to produce a tone of a set frequency. This allows you to make noise simply by turning the buzzer on and off (setting Pin13 to HIGH turns it on; setting it to LOW turns it off). By using pulse width modulation (PWM), you can alter the tone of the buzzer to some degree. Don’t expect music here, but the variance in frequency can be used to indicate different phases or reactions in the Desktop Pal. PWM works by changing the duty cycle of the LOW-HIGH signal that controls the buzzer. By changing the duty cycle, you can alter the pitch of the buzzer, and make different kinds of sounds. You already know that to control a device using simple LOW-HIGH signals, you use the Arduino digitalWrite statement. To control a device using PWM, you use the analogWrite statement. The syntax is:
analogWrite(pin, pwm);
where pin is the pin number you want to control, and pwm is the duty cycle – from 0 to 255 – of the signal waveform.
Pulse Width ModulationPulse Width Modulation
  • 0 = the same as setting the pin to LOW
  • 1 = the same as setting the pin to HIGH
In the Desktop Pal, the electronic buzzer is connected to Pin13. To make a tone using 50 percent PWM duty-cycle, the code would be:
analogWrite(13, 127);   // 127 is half of 255
This turns the sound on. To turn it off, you’d use
analogWrite(13, 255);
I created a short function in the sketch, makeTone, to make it easier to control the electronic buzzer. The function takes two arguments: the PWM value, and a time delay value. For example, here’s how to set the buzzer to 5% PWM, for 50 milliseconds:
makeTone(5, 50);
The makeTone function is defined as
void makeTone(byte freq, int wait) {
  analogWrite(13, freq);
  analogWrite(13, 255);
The freq argument sets the PWM duty-cycle, while the wait argument sets the delay, in milliseconds. Note Not all of the pins on an Arduino are capable of PWM signals. Different models of Arduino boards expose PWM functionality on different pins, so what works on one board may not work in another. Pin13 (on an Arduino Uno or Leonardo) is PWM-capable. If you chose to move the electronic buzzer to a different pin, first check that the pin supports PWM.

Experimenting with Settings

PalLookAround uses a number of global variables to define settings for things like the minimum and maximum rotation of the pan servo, and the maximum distance for detecting an object with the ultrasonic sensors. I encourage you to experiment with these values to fine-tine your Desktop Pal. The values I used were derived experimentally, and should not be considered ideal or perfect. You may find other settings more to your liking. Simply change a value, recompile, and upload the revised sketch. Among the more useful settings to change are:

int triggerRange = 20;

Sets the trigger range, in cm, for the ultrasonic sensors. The trigger range is the maximum value used for the map functions.

int triggerDistance = 20;

Sets the trigger distance, in cm, for the ultrasonic sensors. The trigger distance is the maximum range that Desktop Pal will use for detecting objects. Only objects under this distance are seen. You can try different values for triggerRange and triggerDistance, though most of the time, you’ll probably want to set these to be the same.

int tiltNeutral = 85;

Defines the neutral position of the tilt servo. Increase or decrease to have your Pal gaze higher or lower.

int tiltBack = 70;

Defines the position of the head when tilting back (looking up).

int panNeutral = 90;

Defines the neutral, or middle, position of the pan servo. This sets the head to look straight forward. All servos are a little different, and the construction of your Desktop Pal may dictate a different setting here.

int panLeft = 60;

Sets the extreme left position of the pan servo.

int panRight = 120;

Sets the extreme right position of the pan servo.

Playing with Desktop Pal

Desktop Pal isn’t a complicated robot, but it demonstrates many of the most important robotics concepts. There are servos for movement, and sensors for detecting its environment. And don’t forget the opportunity to simply have fun with it. Robots are great for both teaching and entertaining. To use Desktop Pal, place it on your desk or table, away from you or other objects so that you don’t influence its sensors. Turn it on, and wait for the tell-tale “beep” that it’s started up and is ready. The pan servo will start to scan the room. Walk in front of it, and watch its head quickly move in your approximate direction. Step away, and just as quickly, Pal will resume scanning the room. Wait patiently for about 25 seconds, and Desktop Pal will get drowsy, and enter into doze mode. The side-to-side scanning will stop. Step back in front of Pal, and it’ll quickly notice you and wake up. When you don’t want the Pal to interact – you need to sleep, study, or just watch TV – press the sleep mode switch on the side. The stops all movement and sound until you depress the mode switch again.

Coming Up…

In the next and final lesson, you’ll learn about some additional optional features you can give your Desktop Pal, including much improved sound, sound detection, and more. After all, there are still several empty pins on the Itead Leonardo board, so there’s lots of room for expansion!    
LikedLike this to see more

Spread the word

Flag this post

Thanks for helping to keep our community civil!

Notify staff privately
It's Spam
This post is an advertisement, or vandalism. It is not useful or relevant to the current topic.

You flagged this as spam. Undo flag.Flag Post
You have to be logged in to chat

Our chat is a buzzing-with-life place where our community members join to discuss and foster great conversations.

Whether it's about their latest robotics project, questions about electronics, debates about the industry, or just talking between friends.

You have to be logged in to chat