Sunday, August 12, 2018

"Spooky Old Tree" - The Mouse and The Spider

Despite their vastly different appearances, the Mouse and the Spider are basically the same prop.  They use exactly the same electronic components and the difference in their code is a single digit, so I'm going to cover them together.


Build (Mouse)

The mouse is my favorite of the three props.  The image was taken directly from the book and he has nice bounce when he comes up. His eyes and mouth are coated with glow-in-the-dark paint, so when you activate him with a ultraviolet flashlight, he has a neat look.

We started with a small tagboard box that originally held trash bags.  We painted the interior black and covered it with wood-grain contact paper.  The light sensor is in the middle of the knothole, but to make a more obvious aiming point, we glued on a plastic spider.

To make the mouse, I took a picture of the book page where he appears and loaded it up into a pico-projector.  We pointed that straight down and adjusted the height so that he was blown up to the proper size and my wife traced over him.  After coloring, we mounted him on a light piece of cardboard.

Originally, I thought I would mount him using an L-shaped bracket made from a couple of craft sticks, but we first needed to determine the exact angle and length.  So, for testing purposes I just hooked a piece of wire to a servo horn, figuring we could bend and adjust it until we got the right size and then build the final mount based on that.  However, when we started testing we both loved the way he popped up and wiggled from the wire's flexing, so we just ended up using that.  He's just stuck on with some pieces of Blue-Tack.

Here's a view from the rear.

As you can see, it's a bit of a hot mess.  These are temporary props designed for light duty cycles, so we didn't try to clean things up too much.  The servo is mounted on a block of wood glued to the side and bottom of the box.  I added some wire wrapped around the servo to make sure it didn't move, since the clearance to get the mouse up and out of the hole is a bit tight.  The servo horn is attached so that the zero position is actually pointed down toward the bottom of the box.  When activated, it jumps up to 60 degrees, taking the mouse with it.  Like the Owl, the controller is an Arduino Nano powered by a cellphone USB power bank. 

Build (Spider)

The Spider is the most complicated physical build since it has several different graphic elements.  We wanted something that would fit neatly into the hallway opening, but we didn't have a big enough piece of cardboard span the distance, so we also cut our a pair of cardboard "wings" and attached one to each side vertically  with hot glue to make a nice arch that filled the space.  It's hung using a pair of grommets that slip over some finishing nails I put on the back of the hallway support beam.  It can be hung or removed in a matter of seconds.  Like the Mouse, the cardboard is covered in wood-grain contact paper.

The spiderweb is black yarn that my wife wove through holes she punched in the cardboard and then glued down.  The light sensor is in the middle of the web and a plastic spider with a jeweled back was glued on to give a bit more visual interest. 

To help fill up the space, my wife drew and cut out three bats.  Their eyes are coated with luminous paint to give an eerie look under ultraviolet light.

Here's the rear view.
The controller (another Nano) and its power bank are mounted with Blue-Tack on a shelf made from a piece of molding hot-glued to the cardboard.  A smaller shelf holds the servo, which is wired in place.

The servo horn has been extended with a five-inch piece of craft stick and positioned so that zero is straight up.  When activated, the servo rotates 90 degrees (to the right in this picture) and ends up pointing at the large white circle.  The Spider is attached to a piece of black yarn fastened to the stick that goes over a push pin behind the white circle (six inches out from the servo center), and drops down a couple of inches below the cardboard arch.

Circuitry

Here's the schematic for both the Mouse and the Spider.
As before, it consists of an Input side and an Output side.

The input uses exactly the same components as described for the Owl; an LDR and a resistor that form a voltage divider.  Refer to the post about building the Owl if you want a more detailed explanation of how it works.

The output side is even simpler.  It's just a single servo tied to power and ground, with its control wire attached to an output pin of the Nano.  There's really not much else to say about it.

Here's the breadboard diagram in case you want to mock it up.

Code

The code for the Mouse and the Spider is even simpler than that for the Owl.  The only real changes are the simplification caused by the prop only being able to do one thing, and the code required to run the servo.  This program also includes the Calibrate() routine to make sure the system has an appropriate triggerpoint at all times.  See the Owl post for more details. 

#include<Servo.h>
Servo myServo;
float triggerpoint;
long unsigned caltime;

void Calibrate(){
  triggerpoint=analogRead(A1)+60;
  caltime=millis()+10000;
}

void setup(){
  myServo.attach(9);
  myServo.write(0);
  Calibrate();
}

void loop(){
  if(analogRead(A1)>triggerpoint){
    myServo.write(60); //use 90 for the Spider
    delay(1000);
    myServo.write(0);
  }
  if(millis()>caltime){
    Calibrate();
  }
}

The grandkids love these props and they were a lot of fun to make.  If you build something like them, please let me know.

Tuesday, August 07, 2018

"Spooky Old Tree" - The Owl

Of the three props we created, the Owl, having no moving parts, was the simplest build.

Build

I used my printer's copy function to make a 1:1 scale reproduction of one of our Halloween decorations, which we then spray-glued down to a piece of cardboard.  My wife cut out around it and went over the edges with a black marker.  Once that was done, we used a pushpin to make a couple of holes in each eye for the LED leads, and another set between the feet for the photo-resistor "target".

That completed the graphics work, so all we had to do was wire it up.
The breadboards I'm using come with double-sided tape, so i just peeled of the protective coating and stuck it directly to the cardboard.  Power for the system comes from a USB battery pack.  The system draws very little power, so the pack will run it for hours.  It's just held in place with a couple of pieces of Blue-Tack.

As you can see, we didn't really make any effort at a neat, professional build.  All these projects are relatively temporary and everything is held together with tape, Blue-Tack and hot glue. All connections were simply twisted together and covered with electricians tape.

Circuitry

Here's the schematic for the Owl's circuitry.
There are two basic parts:  the output (the LED eyes) and the input (the photo-resistor).  We'll take a look at the input first, and since it's used for all the props, I'll cover it in some detail.

Input
The input is comprised of an  LDR (Light-Dependent Resistor) wired in series with a fixed 1K resistor to form a voltage divider.  One end of the LDR is connected to a 5V power pin on an Arduino Nano, and the other end is connected to the fixed resistor.  The other end of the fixed resistor goes to ground.  The center tap of the voltage divider is connected to one of the analog input pins on the Nano. (Refer to the schematic.)

Here's the way it works.  

In a simple divider like this, the voltage at the center tap will be the same as the ratio between each resistor and the total resistance in the circuit.  In other words, if we shine enough light on the LDR to lower its resistance to 1K, the total resistance in the circuit would be 2K, and the voltage at the tap would be 2.5V, since the LDR would be dropping half of the 5V source and fixed resistor will be dropping the other half.  If there is less light on the LDR (say, making it 2K) the total resistance would be 3K and the voltage at the tap would be about 1.67V, since the LDR will be dropping 2/3 of the voltage.

The analog input on the Nano converts the voltage to a proportionate value in the range of 0-1023.  So, when the voltage is 2.5V, the value would be about 512.  A 1.67 voltage would be converted to  341, and so on.

So, to make the LDR act as a trigger, we simply need to read the ambient light value and then add some value to create a triggerpoint that is a bit higher.  That way, when the LDR later receives a hit from the flashlight, it's resistance will go down, causing the input at the center tap to rise above the triggerpoint and set off the effect.  For my circuits I've been adding 60 to the ambient light value (i.e. an ambient light value of 40 would have triggerpoint of 100).

Output
The output side of things is even simpler.  Two digital output pins are used, each one connected to the anode of a standard red LED.  The cathode of the LED is connected to a 150 Ohm resistor, which is then connected to ground.  When the pins go high, current flows to the LED and lights it up.  When the pin goes low, the LEDs turn off.  There's not much else to say.


Finally, here's a breadboard diagram in case you want to build a prototype.

Code

Despite being the simplest physical build, the Owl has the most complex code of any of the props, since it can react to a light hit in one of three different ways.  Fortunately, however, the code is still pretty simple and straightforward.

Here it is:

float triggerpoint;
long unsigned caltime;

void Steady(){
  analogWrite(4,255);
  analogWrite(5,255);
  delay(1000);
  analogWrite(4,0);
  analogWrite(5,0);
} 

void Flash(){
  for(int x=0;x<5;x++){
    analogWrite(4,255);
    analogWrite(5,255);
    delay(205);
    analogWrite(4,0);
    analogWrite(5,0);
    delay(250);
  }
}

void Blink(){
  for(int x=0;x<5;x++){
    analogWrite(4,255);
    delay(250);
    analogWrite(4,0);
    analogWrite(5,255);
    delay(250);
    analogWrite(5,0);
  }
}

void Calibrate(){
  triggerpoint=analogRead(A1)+60;
  caltime=millis()+10000;
   
}
void setup(){
  Calibrate();
}

void loop(){
  if(analogRead(A1)>triggerpoint){
    int x=random(3);
    switch(x){
    case 0:
      Steady();
      break;
    case 1:
      Flash();
      break;
    case 2:
      Blink();
      break;
    }
  }

  if(millis()>caltime){
    Calibrate();
  }
}

There's nothing unusual or even very interesting about this code. It defines a couple variables, followed by four function definitions that the main program can call.  Then there's the standard setup function and the main loop, which reads the current light value and, if it is above the triggerpoint, gets a random number and uses the switch structure to determine which effect function to call..  The only thing that might require a bit of explanation is the Calibrate() function.

The hallway where these props are set up has a partially-curtained, west-facing window.  During the morning and late evening, it's rather dim, but during the afternoon, more light can come in.  Since the kids play this game at all hours of the day, there is no single triggerpoint that will work at all times.  To get around that, I created the Calibrate() function.

First, it reads the current ambient light level, adds 60 units to it, and sets that as the triggerpoint.  Then it read the Arduino's built-in millis() function.  This function returns the number of milliseconds since the board was powered on.  Once it has this, Calibrate() adds 10000 to it and saves it as the variable "caltime"  Essentially, caltime is set to 10 seconds into the future. 

Calibrate() is called in the setup() function to set an initial value.  Then, on each pass through the main loop the system checks to see if the real time returned by millis() has caught up with caltime.  If it has, Calibrate() is run again, re-evaluating and setting the triggerpoint and kicking the next update time another 10 seconds into the future.

This means that regardless of changing light conditions, the system will set an appropriate triggerpoint within 10 seconds.  Even if we turn on one of the hallway lights and trigger the effects, 10 seconds later they will go off and be reset to an appropriate working state.

There is an inherent minor flaw in this system, however.  Since the Calibrate() function runs independently of anything else, it will, inevitably, occasionally run when the target is being illuminated by the flashlight, giving a false ambient reading and setting the triggerpoint too high.  I thought of a few ways around this, but after watching the kids play the game, I decided it wasn't necessary.  They don't linger too long on any one effect and any error is corrected within 10 seconds, so they never even notice.