Nerf Turret Part 1

I have always been impressed with the cool tech in Sci-fi movies. With all the recent buzz in the gamer community about the game Portal –which has a smart turret as it’s main character– I thought it would be cool to try and build my own autonomous security turret, even if it didn’t look as cool as the one in the game.

Turrets

I have a few Arduino microcontrollers laying around so I thought it would be cool to try with a Nerf gun and some servos. I set out to create a system that can autonomously track and engage targets. A portable, desktop, security turret that is simple to use. I would start with thinking through a few ideas of how I would track targets as that would be the core system everything else would be built around.

Before you can shoot, you need to see your target

PIR

The first way to find a target that came to mind was using a PIR sensor (Pyroelectric InfraRed). They are great for seeing movement and are widely used in home spotlights and commercial automatic doors. I found a few problems right away. It is not instant on and off as they require a short warm up period to heat up the imaging element. This said, I found they are extremely sensitive after they do.The plastic window covering has multiple facets molded into it to consolidate and focus the scattered infrared energy onto the sensor.

Image from BHLENS
Each individual facet is a Fresnel lens. They are famously used in lighthouses to direct and amplify light out. The Fresnel lens here is designed to amplify the scattered infrared energy by capturing and redirecting a larger area of energy than the actual sensor could read by itself.

The PIR sensor does not return distance to target, instead they compare two infrared images. Any difference between the heat signatures in both images will constitute movement and the sensor sends a high signal.

When a warm body passes by the first half of the sensor it causes a positive differential change between the two halves. When the warm body leaves the sensing area, the reverse happens and the sensor generates a negative differential change. These change pulses are what is detected.


Image from Adafruit.com

There is no doubt the PIR sensor is excellent for seeing initial movement but not tracking where the target is. I can’t use them to know how far or in which specific location the target is, just a wide general area. I think we will revisit the PIR later, for now we need a core system to track targets with a finer resolution than the PIR can provide. There are other types of Infared sensors on the market that do return a distance value, but sadly they are for very short distances under 100 centimeters.

This led me to the other option, sonar which is also cheap and easy to set up and they do return a distance value over a longer range we can work with.

PING

A Bat’s eye

The Parallax PING))) Ultrasonic range finder is powered by 5V and will provide precise, non-contact distance measurements from about 2 cm (0.8 inches) to 3 meters (3.3 yards). The PING))) sensor has a sender (speaker) and a receiver (mic) and works by transmitting an above human hearing ultrasonic burst that will propagate out to hopefully bounce off an object where the echo is then received by the microphone.

After the return burst is recorded, the sensor provides an output pulse that corresponds to the time required for the burst echo to return to the sensor. The distance to target can be calculated by using the return echo pulse width measurement and correct unit conversion formula, which the Arduino Ping object can do for you.

PING

Here is a simple example of how to use the Ping Arduino library.

// serial output of PING sensor in various unit conversions
#include <Ping.h>

// sensor pin
int pingPin = 7;

// sensor object
Ping ping = Ping(pingPin,74,29);

void setup(){
   Serial.begin(9600);
}

void loop(){
  ping.fire();
  Serial.print("Microseconds: ");
  Serial.print(ping.microseconds());
  Serial.print(" | Inches ");
  Serial.print(ping.inches());
  Serial.print(" | Centimeters: ");
  Serial.print(ping.centimeters());
  Serial.println();
}

After creating an instance of the Ping object set to pin 7, the sensor is fired and the result returned. The Ping object can have the return time converted into inches or centimeter units for you. You can also use the this object to retrieve the actual microseconds of each return pulse to do your own calculations using the speed of sound and conversion formulas yourself.

We can take a closer look at what is really going on behind the neat fire method and unit conversions.

  long duration, inches, cm;

  // start fresh by going LOW 
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);

  // Now send a clean burst to measure
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

First we have to establish variables for duration of the ping, and the distance result in inches and centimeters. The burst process begins with placing the sensor LOW to ensure a clean burst, this is a reset so we are starting from scratch. Now we can send a new clean HIGH pulse for an exact amount of time as the pulse to track (2-5 microseconds). As a note, I found sometimes it is better to send a pulse closer to 5 microseconds in length for better accuracy over longer ranges, there is simply more of a burst to make it back. But this comes at a cost, you want to scan as fast as possible and the longer the burst, the longer it takes to complete a scan. I wouldn’t go below 3ms or above 5ms on the burst because of these reasons. You have to dial it in and see what works best given the range you want to support.

  
  pinMode(pingPin, INPUT);

After the clean HIGH burst was sent, the same pin is put in receiving mode to listen for the returning echo.

  
  duration = pulseIn(pingPin, HIGH);

The pulseIn function is used to return the echo value. It is important to note this return HIGH pulse is not just a simple digital ON, but instead is actually the full duration (in microseconds) from the sending of the ping to the reception of its echo off an object. So the return HIGH length is equal to the whole trip, there and back.

To convert microseconds to centimeters, simply divide by the number of microseconds sound travels per centimeter (29). Using this we know the burst travels out and back, so to find the distance of the object we divide that value by 2 to take half of the distance traveled, exactly from the sensor to the target alone.

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

There are 73.746 microseconds per inch (speed of sound is 1130fps). Like before divide by 2 to get the distance of the target and by the number of microseconds sound travels per inch (74).

long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

So in the end it is quite easy to work with the PING))) range finder which is pretty reliable up to 10 feet. There are limitations of course, the ping can bounce off of walls and multiply into ghost readings, as well the echo can be deflected or absorbed by the target giving less than accurate results. Now that we can measure how far things are we have to figure out how use this to find targets.

Target detection is more than reading a distance


Now that I have a reliable way to get distance measurements, my goal was to write a driver for object detection. I had to test different physical mounting configurations of the range finder, as well as design a working algorithm to find targets. I went through about a half dozen configurations until I found using two range finders makes it easier to track targets. Below is a test function I use with two sensors.

void pinger(int pos) {
  PingLeft.fire();
  PingRight.fire();
  left = PingLeft.centimeters();
  right = PingRight.centimeters();
  DISTANCE = left + right / 2;
   Serial.print(pos);
   Serial.print(" --");
   Serial.print("LEFT:");
   Serial.print(left);
   Serial.print(" RIGHT:");
   Serial.print(right); 
   Serial.print(" Avg:");
   Serial.println(DISTANCE);
}

One clear requirement I had was independent articulation of the sensors from the turret. I wanted the ability to shoot and keep tracking at the same time. Once I had target detection working I would add the gun & turret.  I sure had my work cut out for me, below is a consolidated video of some of that effort and success. It didn’t take long getting this working and was very exciting having it track me with just a few lines of code. I still had some bugs but it was working! Could it be this easy?

I made the mistake of holding my phone in the wrong orientation. Let this be a lesson to everyone, hold your phone sideways when recording video!

Continue to Part 2

Resources

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s