Introduction: Kid-friendly PuppyDuino 0.31

Picture of Kid-friendly PuppyDuino 0.31

OK, this is not a fully autonomous "get you a beer, open it for you and then tweet about it" robodog (yet ;) but if you're itching to get past the blinky lights on a breadboard stage with your Arduino and you're ten or know somebody that's ten this might appeal to you.

This is actually the first published part of an afterschool learning project I'm working on that demonstrates the Arduino UNO beyond flashing LEDs. Hopefully this will find its way into a lesson plan for next semester that will roughly follow the Arduino lessons on the Adafruit Learning System website.

What 0.31 does: When you pet PuppyDuino she wags her tail in gratitude. Stop petting her and tail wagging stops too.

How it works: A light sensor (made with a photoresistor) on the face reacts to the shadow of a passing hand. Less light = higher voltage on an analog pin. Once a threshold voltage is exceeded, the servo motor is signaled to wag the tail.

A similar arrangement with a trim potentiometer on another analog pin allows you to adjust that threshold voltage so to match ambient light conditions.

Concepts learned: Analog input, digital input, potentiometers, photoresistors, servo control, serial monitor, breadboarding and the satisfaction of making a real thing that reacts by doing real stuff.

Why 0.31? Because PuppyDuino is a platform that has lots of room for upgrading - LED eyes, motorized wheels, distance sensors, etc. So, keep that "get a beer for you" thing alive in the back of your mind for some future version. Also, I skipped over some introductory Arduino projects that could be taught PuppyDuino-style that I'll document later. Those can be 0.1 and 0.2.

Step 1: Collect Materials

Picture of Collect Materials

Parts

  • shoe box and smaller box for head (or suitable, stable containers)
  • Arduino UNO or similar 'duino
  • analog micro servo (TowerPro SGR92R, SG90 or similar)
  • breadboard
  • 22ga solid core wire - various colors help or male - male jumper wires
  • battery power adapter*
  • photoresistor - I have no idea what spec mine is*
  • 10K trim potentiometer (board mount type)
  • 10K resistor
  • tactile switch
  • electrician's tape or heat shrink tubing (for photoresistor leads - in a pinch painter's tape would work)
  • small cardboard to hold components or purchased project board for Arduino and breadboard

Tools

  • hot glue gun
  • painter's tape or other low tack tape
  • scissors and / or craft knife
  • paint, stickers, markers, etc for decoration
  • wire stripper / cutter
  • solder iron / solder (For photoresistor leads only. Option - Just twist and tape)
  • Computer with the Arduino IDE installed
  • USB cable to upload sketches

* 9V batteries are not the most economical choice but I had free cases of them. You can run the Arduino and a small servo attached to your computer's USB port or a 6X AA battery holder.

* I tried a few different fixed resistors in series with my photoresistor until I settled one where voltage between them was above 1V even in bright light.

We'll start building PuppyDuino on a project board and only install the 'guts' into our robodog after everything is working to satisfaction. Of course, if you are working with children you might work on the box simultaneously with the intent of finishing both about the same time. A little craft time is a great break from the electronics while still keeping on task.

Step 2: Let's Wag Some Tail - Servo Motor Control

Picture of Let's Wag Some Tail - Servo Motor Control

What's a servo?

The standard hobby servo motor does not go round and round. Instead it goes back and forth which is perfect for steering radio controlled model airplanes and wagging robotic dog tails. The business end of a servo is more like a small electric arm that can be positioned quickly and with some precision through about 180 degrees. You may need to check the specification of your servo either on the package or a datasheet from the manufacturer to determine how far yours rotates.

Thanks to the Servo library in the Arduino IDE we don't have to understand how this works internally, we simply need to tell the servo how many degrees to rotate and it obeys. Tell your servo to go to 0 and it will position the arm as far clockwise as it can rotate. If we tell it 180 the arm moves 180 degrees counterclockwise from zero. If we tell it 135 it positions the arm 135 degrees counterclockwise from zero. All measurements are counterclockwise from zero.

OK - Let's experiment!

Tape your servo motor to your work surface with the splined gear pointing up. Slide one of the little arms over the gear. Connect it to the Arduino as shown in the diagram. Red to 5V, Black (or Brown) to ground and the remaining wire (usually White or Orange), to pin 9.

Upload the code to your Arduino and watch it go. Try changing the numbers in the program to see what happens. DO NOT EXCEED THE MAXIMUM ROTATION OF YOUR SERVO - 0 to 180 is usually safe.

tailTest1.ino

/*tailTest1.ino
your servo needs to connect to 
5V to red wire, 
ground black wire 
pin 9 to control wire (white, yellow or orange)
*/

#include  <Servo.h> // this imports the Servo library
Servo servo; //create Servo

void setup()
{
 servo.attach(9); //control wire attaches to pin 9
}

void loop()
{
  // just some random moves to show servo working
  servo.write(0);
  delay(1000); 
  servo.write(180);
  delay(1000);
  servo.write(135);
  delay(1000); 
  servo.write(180);
  delay(1000);
  servo.write(135);
  delay(1000); 
  servo.write(180);
  delay(1000);
  servo.write(135);
  delay(1000); 
  servo.write(45);
  delay(1000); 
  servo.write(0);
  delay(1000); 
  
}

Smooth move

You should have seen the servo arm move back and forth a few times then return to the zero position (over and over again). Cool, but kind of a jerky wag even for a robot dog. Let's smooth that wag out a bit by turning 1 degree at a time with a little 10 millisecond pause between moves.

tailTest2.ino

/*tailTest2.ino
 your servo needs to connect to 
 5V to red wire, 
 ground black wire 
 pin 9 to control wire (or PWM pin of your choice)
 */

#include  <Servo.h>  //this imports the Servo library
Servo servo;         //create a Servo
int i;               //counting variable
int right = 135;     //right extent of wag
int left = 180;      //left extent of wag

void setup()
{
  servo.attach(9);
}

void loop()
{

 // sweep right to left one degree at at time
  for(i = right; i<=left; i++)
  {
    servo.write(i); 
    delay(10);
  }
  // sweep left to right one degree at at time
  for(i = left; i >= right; i--)
  {
    servo.write(i); 
    delay(10);
  }

}

BINGO! We now have a smooth wag that says happy dog.

Obedience School

OK, now that PuppyDuino knows how to wag her tail let's train her to wag on command. We'll add the optional button circuit shown in the diagram and upload the sketch below. The tail should wag when the button is pressed and be still when it is not pressed. (If we can make her wag in response to a button press we're a hop, skip and a short jump away from making her wag in response to a petting sensor.)

tailTest3.ino

/*tailTest3.ino
 your servo needs to connect to 
 5V to red wire, 
 ground black wire 
 pin 9 to control wire 
 servo tail wags only when button pressed
 */

#include <Servo.h>   //this imports the Servo library
Servo servo;         //create a Servo
int i;               //counting variable
int right = 135;     //right extent of wag
int left = 180;      //left extent of wag
int button = 8;      //button input on pin 8

void setup()
{
  servo.attach(9);
  pinMode(button,INPUT_PULLUP); //HIGH unless grounded
}

void loop()
{
  // check if button pressed (if pin goes LOW)
  if(digitalRead(button) == LOW)
  {
    // sweep right to left one degree at at time
    for(i = right; i <= left;  i++)
    {
      servo.write(i); 
      delay(10);
    }
    // sweep left to right one degree at at time
    for(i = left; i >= right; i--)
    {
      servo.write(i); 
      delay(10);
    }
  }
  delay(300);

}

OK - let's remove that button circuit. We're done with it.

Step 3: Pet Me! Making a Petting Sensor

Picture of Pet Me! Making a Petting Sensor

Seeing the light

Now we need a way to detect when PuppyDuino is getting pets. We'll be making a light sensor (or dark sensor depending on your perspective) to detect the shadow of a passing hand.

Ingredient X of our sensor is a photoresistor which becomes less resistant in brighter light. We'll wire this in series with a plain ol' fixed resistor and have the Arduino measure the voltage at the point in between the two. As the resistance changes in the photoresistor so will the voltage at that midpoint. That change is how we know a hand (shadow) passed over PuppyDuino's head.

The Arduino will be testing this voltage on an analog pin. Analog pins on the Arduino interpret 0V to 5V as a number between 0 and 1023. Our sensor will return some number in full light and some other number in shadow depending on the components used and the lighting conditions in our workspace. We also need to see those numbers so we'll use the Serial Monitor in the Arduino IDE to peek at what PuppyDuino is sensing.

Let's upload the lightSensor1 sketch and click the rightmost icon on the Arduino IDE. That will open the Serial Monitor. We'll be sending values from our light sensor back from the Arduino to the serial monitor with the statement Serial.println(lightSensor).

lightSensor1.ino

/*lightSensor1.ino
Let's peek at the values from our light sensor
 */

int lightPin = 1; //analog pin light sensor  
int lightSensor = 0;

void setup() 
{
  Serial.begin(9600); //start serial communication (match value serial monitor)
}

void loop() 
{
  lightSensor = analogRead(lightPin); //get value light sensor
  Serial.println(lightSensor); //print sensor value to monitor
  delay(300);
}

At the time I wrote this mine read about 215 in light and shot up to 500+ in shadow. You will need these values from your serial monitor in a minute so write them down. I'll padded mine a bit and used 400 for the dark value.

Light sensor value in light 215

Light sensor value in shadow 400

Getting a reaction

Ultimately we want PuppyDiuno to wag her tail but for now let's just blink the onboard LED connected to pin 13. Load up lightSensor2 sketch and watch the LED blink when you hand passes over the light sensor.

Our programming logic will go something like this

repeat this forever

  • check light sensor value
  • if light sensor value > known shadow value, then blink LED
  • if not, LED off

lightSensor2.ino

/*lightSensor2.ino
Let's peek at the values from our light sensor
 then blink an LED when it detects a shadow
 */

int lightPin = 1; //analog pin light sensor  
int lightSensor = 0; //initialize sensor value to zero
int led = 13; //led pin
int shadowValue = 400;  //a little less than my lowest observed shadow value
                        //change this to match your conditions

void setup() 
{
  Serial.begin(9600); //start serial communication
  pinMode(led,OUTPUT); //set our pin led to output mode
}

void loop() 
{
  lightSensor = analogRead(lightPin); //read value from sensor
  Serial.println(lightSensor); //send sensor value to monitor

  if(lightSensor > shadowValue) //if shadow detected then blink
  {
    digitalWrite(led, HIGH);
    delay(300);
    digitalWrite(led, LOW);
    delay(300);
  }
  else  //otherwise don't blink
  {
   digitalWrite(led,LOW); 
  }

}

OK, not exactly a tail wag but we are getting a response. Be patient, in the next step we'll marry our tail wag code to our light sensor code.

Step 4: Tail Waggin' Bliss - PuppyDuino 0.3

Picture of  Tail Waggin' Bliss - PuppyDuino 0.3

Adding it all up

PuppyDuino already knows how to wag the servo tail when a button is pressed (responding to an event).

PuppyDuino already knows how to sense a petting hand from a change in light sensor value (sensing an event).

Now let's make PuppyDuino wag her tail in response to a shadow at the light sensor.

We're just going to replace blinking in the previous sketch with tail wagging. I noticed back in the previous step that petting my dog resulted in a sensor reading of about 500+. I'll pad that a bit and use 400 as my threshold so that any reading over 400 will result in a wag. (Your values may vary from mine and vary with changing ambient light conditions. Check with the serial monitor before you commit to values. We'll make this number adjustable later.)


Our programming logic will go something like this

repeat this forever

  • check light sensor value
  • if light sensor value > known shadow value, then wag servo tail
  • if not, put tail down

Deja vu - this sounds so familiar. Let's get both the servo and the light sensor circuits on the breadboard as shown in diagram and then upload our next sketch.

puppyduino0_3.ino

/*puppyduino0_3.ino
puppy wags tail when someone pets her
servo tail wags when light sensor in shadow
*/

#include  <Servo.h>  //this imports the Servo library
Servo servo;         //create a Servo

int right = 135;     //right extent of wag
int left = 180;      //left extent of wag
int lightPin = 1;    //analog pin light sensor  
int lightSensor = 0; //initialize sensor value to zero
int servoPin = 9;    //servo control pin
int i = left;        //initialize i to left

int shadowValue = 400; //put YOUR value here
 
void setup() 
{
  servo.attach(servoPin);
}
 
void loop() 
{
  lightSensor = analogRead(lightPin); //read light sensor
  
  if(lightSensor > shadowValue)
  {
    //wag 3 times
    for(int j = 0; j<=3; j++)  
    {
      // sweep right to left one degree at at time
      for(i = right; i<=left; i++)
      {
        servo.write(i); 
        delay(10);
      }
      // sweep left to right one degree at at time
      for(i = left; i >= right; i--)
      {
        servo.write(i); 
        delay(10);
      }
    }
  }
  else
  {
   servo.write(0); //tail in down position
  }
 
}

If all went well your PuppyDuino wags happily when you pet her head. If not, do some troubleshooting. Is everything wired correctly? Are your circuit connections snug? Did the lighting change significantly since you determined your threshold value? Maybe try adding some Serial.println statements so you can see your actual sensor readings.

Step 5: Sensitivity Training - PuppyDuino 0.31

Picture of Sensitivity Training - PuppyDuino 0.31

Going to Pot

OK, we now have a puppy that wags her tail when a sensor reading exceeds a preset hard-coded threshold we determined by trial and error. That's cool! But if the ambient light conditions change very much we will probably have to change that threshold in the code and recompile again. That's not so cool.

We'll fix that in just a minute by adding an adjustment knob so we can change that threshold on the fly to match the conditions. For this we'll be using a trim potentiometer, or trim pot, to generate varied values that we can use as our wag threshold. Telling you that a trim pot is just a variable resistor is oversimplification but that definition works well enough for what we are doing here. As we turn the knob we change the resistance of the pot and change the voltage at the middle 'wiper' pin.

We need to add the last of the components to our breadboard as shown in the above diagram and load up this little demo sketch. Once you have the serial monitor open you should see values just like we saw from our light sensor in a previous step.

Turn the knob through its full extent and you should see numbers 0 to 1023. How about that? We just happen to need a value adjustable from 0 and 1023.

trimPot.ino

/*
trimPot.ino
Observe varying values at wiper pin on trim potentiometer
 */

int potPin = 0;
int potValue;

void setup()
{
  Serial.begin(9600);   //start serial communication
}

void loop()
{
  potValue = analogRead(potPin);   //read value at wiper
  Serial.println(potValue);   //send value to monitor
  delay(300);
}

Are we there yet?

The answer would be yes. Our circuit is complete and this is our last sketch to load kids. We'll just do the switcheroo with our hard-coded threshold value for our pot value. I added some statements that print to the serial monitor to aid in debugging and testing. These can be commented out by placing // at the beginning of the line if you don't need them.

</*puppyduino0_31.ino
puppy wags tail when someone pets her
servo tail wags when light sensor in shadow
wag threshold determined by value on potentiometer
*/

#include  <Servo.h>  //this imports the Servo library
Servo servo;         //create a Servo

int right = 135;     //right extent of wag
int left = 180;      //left extent of wag
int lightPin = 1;    //analog pin light sensor  
int lightSensor = 0; //initialize sensor value to zero
int servoPin = 9;    //servo control pin
int i = left;        //initialize i to left

int potPin = 0;      //analog pin read pot value
int potValue = 0;    //value of pot init to zero
 
void setup() 
{
  servo.attach(servoPin); //servo control pin
  Serial.begin(9600); //for testing
}
 
void loop() 
{
  lightSensor = analogRead(lightPin); //read light sensor
  potValue = analogRead(potPin);   
  
  // serial output for testing and debugging
  Serial.print("Pot: ");
  Serial.println(potValue);
  Serial.print("Sensor: ");
  Serial.println(lightSensor);
  
  if(lightSensor > potValue)
  {
    Serial.println("Wagging!"); //test statement
    //wag 3 times
    for(int j = 0; j<=3; j++)  
    {
      // sweep right to left one degree at at time
      for(i = right; i<=left; i++)
      {
        servo.write(i); 
        delay(10);
      }
      // sweep left to right one degree at at time
      for(i = left; i >= right; i--)
      {
        servo.write(i); 
        delay(10);
      }
    }
  }
  else
  {
   servo.write(0); //tail in down position
  }
 
}

Step 6: Boxing Day

Picture of Boxing Day

With the electronics good to go it would be time to make our puppy proper. Drop that project board into your shoebox and reposition the servo arm so that it points up when wagging. The only rule that applies here is there are no rules except keeping your options open for future upgrades so I'll leave the crafting to you.

Step 7: Resources

If you are already familiar with Arduino then this project should be a slam dunk. If you're a total noob you could just follow the instructions and make PuppyDuino but to really get the most from this you need to understand the why, not just the how. Concepts in this project are covered fairly well in the Arduino lessons on the Adafruit Learning System website. I recommend this site for beginners as it gets your hands on an Arduino from the start. I suggest completing all the lesson projects separately then bundle a few together into your own PuppyDuino.

Unless you have electronic components galore on hand already I would suggest purchasing an Arduino starter kit. Here are some kits that should have all or most of what you need to learn the basics of Arduino and complete a PuppyDuino.

http://www.adafruit.com/products/170

http://www.adafruit.com/products/68 (no servomotor)

https://www.sparkfun.com/products/13154

http://arduino.cc/en/Main/ArduinoStarterKit

If you are purchasing for a group then it may be worth your while to price individual components, negotiate volume discounts or purchase cheap knock-offs from China.

All sketches are included in embedded zip file.

Comments

iam_maker_leo (author)2014-11-18

Sooooo cute...!!!

nice to meet your project.

alhazen (author)iam_maker_leo2014-11-18

Thank you. The cute factor seems to be a hit with the kids. I think I have found my gateway platform.

I may be checking out your instructable with the ultrasonic sensor. The next version will include either a PIR or US.

MsSweetSatisfaction (author)2014-11-18

Daww it's so cute, and a great beginner project!

Thank you. I hope someone finds it useful.

About This Instructable

2,601views

22favorites

License:

More by alhazen:Kid-friendly PuppyDuino 0.31Kid stuff (Big kids too)Spin Art Table from a Window Fan
Add instructable to: