Animatronics

Enter Your Electronics & Design Project for a chance to win an $200 Shopping cart of product!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll

 

Man's best friend, the humble dog.

Creepy clown's best friend, the $8 skeleton dog from dollar general.

https://www.dollargeneral.com/skeleton-dog-halloween-decor-1-count.html#

 

 

 

Let's see what we can do to make this pup a bit more scary for halloween.........

I'll be using an Arduino Micro for this project to control head movement and eye color.

A motion sensor will detect a visitor, and animate the scary puppy.

First cut it's head off and add a RC servo.

 

Then epoxy the servo horn into the neck of the beast.

Then we'll add some programmable RGB LEDS for eyes.

These are cut from a strip of 48 with LPD8806 control ICs.

Here's the schematic:  The power is from a 5VDC wall supply.

Then hot-glue some ping-pong ball half spheres to cover up the RGB LEDS

There's a RGB control library for this IC on the Adafruit Github site:

https://github.com/adafruit/LPD8806

 

 

//Skelly the animatronics dog
//October 2019 R. Scott Coppersmith


#include "LPD8806.h"
#include "SPI.h" 
#ifdef __AVR_ATtiny85__
 #include <avr/power.h>
#endif


// Based on Adafruit Example to control LPD8806-based RGB LED Modules in a strip
/*****************************************************************************/
// Number of RGB LEDs in strand:
int nLEDs = 4;
// Choose pins for output:
int dataPin  = 2;
int clockPin = 3;
const int MotionPin = 4; // Motion detect circuit 
const int ServoPin = 5;  // PWM servo pin
int MotionState = 1;     // Motion detect active low


#include <Servo.h>


Servo myservo;  // create servo object to control a servo
int pos = 0;    // variable to store the servo position


// First parameter is the number of LEDs in the strand.  The LED strips
// are 32 LEDs per meter but you can extend or cut the strip.  Next two
// parameters are SPI data and clock pins:
LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);


void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
  clock_prescale_set(clock_div_1); // Enable 16 MHz on Trinket
#endif
pinMode(MotionPin, INPUT);
myservo.attach(5);  // attaches the servo on pin 5 to the servo object
  // Start up the LED strip
  strip.begin();
  // Update the strip, to start they are all 'off'
  strip.show();
}




void loop() {
   colorWipe(strip.Color(0,   0,   0), 50);  // off
  // read the input pin:
  // print out the state of the button:
  Serial.println("Waiting for Motion Trigger");
  while (MotionState == 1){
  MotionState = digitalRead(MotionPin);
  }
  // print out the state of the button:
  Serial.println("Motion Detected");
  MotionState = 1;
  theaterChase(strip.Color(127,   0, 127), 50); // Violet
  // Fill the entire strip with...
  colorWipe(strip.Color(127,   0,   0), 50);  // Red
  colorWipe(strip.Color(  0, 127,   0), 50);  // Green
  colorWipe(strip.Color(  0,   0, 127), 50);  // Blue
  rainbow(10);
  // Move the dogs head back and forth using the servo
    for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  rainbowCycle(0);  // make it go through the cycle fairly fast
}


void rainbow(uint8_t wait) {
  int i, j;
   
  for (j=0; j < 384; j++) {     // 3 cycles of all 384 colors in the wheel
    for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel( (i + j) % 384));
    }  
    strip.show();   // write all the pixels out
    delay(wait);
  }
}


// Slightly different, this one makes the rainbow wheel equally distributed 
// along the chain
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;
  
  for (j=0; j < 384 * 5; j++) {     // 5 cycles of all 384 colors in the wheel
    for (i=0; i < strip.numPixels(); i++) {
      // tricky math! we use each pixel as a fraction of the full 384-color wheel
      // (thats the i / strip.numPixels() part)
      // Then add in j which makes the colors go around per pixel
      // the % 384 is to make the wheel cycle around
      strip.setPixelColor(i, Wheel( ((i * 384 / strip.numPixels()) + j) % 384) );
    }  
    strip.show();   // write all the pixels out
    delay(wait);
  }
}


// Fill the dots progressively along the strip.
void colorWipe(uint32_t c, uint8_t wait) {
  int i;


  for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}


// Chase one dot down the full strip.
void colorChase(uint32_t c, uint8_t wait) {
  int i;


  // Start by turning all pixels off:
  for(i=0; i<strip.numPixels(); i++) strip.setPixelColor(i, 0);


  // Then display one pixel at a time:
  for(i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c); // Set new pixel 'on'
    strip.show();              // Refresh LED states
    strip.setPixelColor(i, 0); // Erase pixel, but don't refresh!
    delay(wait);
  }


  strip.show(); // Refresh to turn off last pixel
}


//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();
     
      delay(wait);
     
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}


//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 384; j++) {     // cycle all 384 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < strip.numPixels(); i=i+3) {
          strip.setPixelColor(i+q, Wheel( (i+j) % 384));    //turn every third pixel on
        }
        strip.show();
       
        delay(wait);
       
        for (int i=0; i < strip.numPixels(); i=i+3) {
          strip.setPixelColor(i+q, 0);        //turn every third pixel off
        }
    }
  }
}
/* Helper functions */


//Input a value 0 to 384 to get a color value.
//The colours are a transition r - g -b - back to r


uint32_t Wheel(uint16_t WheelPos)
{
  byte r, g, b;
  switch(WheelPos / 128)
  {
    case 0:
      r = 127 - WheelPos % 128;   //Red down
      g = WheelPos % 128;      // Green up
      b = 0;                  //blue off
      break; 
    case 1:
      g = 127 - WheelPos % 128;  //green down
      b = WheelPos % 128;      //blue up
      r = 0;                  //red off
      break; 
    case 2:
      b = 127 - WheelPos % 128;  //blue down 
      r = WheelPos % 128;      //red up
      g = 0;                  //green off
      break; 
  }
  return(strip.Color(r,g,b));
}