Introduction: Arduino Pan & Tilt With Ultra-Sonic Tracking

In an attempt to find a physical way to teach nested "for" loops, I derived a project for my students to program a pan and tilt module and add a (albeit slow) tracking function with an onboard ultrasonic sensor. The final representation of this idea, shown in the image above, consisted of the pan and tilt module constructed using Pitsco's "Tetrix" parts, along with two HiTec HS-322HB servo motors, and an HC-SR04 Ultrasonic sensor. All of this was mounted on a painted piece of 4x4 lumber to elevate the structure and give it some weight to prevent movement during operation. This was all controlled with an Arduino Mega and powered by an Elegoo breadboard power module. In the end, the goal was to have the system scan the area, and then have the module point to the closet target.

Step 1: Pan and Tilt - the Structure

As stated in the introduction, pan and tilt modules are a great way to teach nested for loops. Sometimes a physical representation of this helps students visualize one smaller function being repeated a certain number of times inside another larger function. As shown above, and stated in the introduction, we used Pitsco's "Tetrix" parts to construct the physical system and then powered the two servo motors using Elegoo's breadboard power module to ensure the two HS-322B's had sufficient current for stable operation. Obviously when connecting the two parts of the overall system, care has to be taken to ensure sufficient slack for the wiring on the tilt motor as the pan motor rotates.

Step 2: Pan and Tilt - the Code

As with most Arduino code, the pan and tilt code is broken into three sections: the "global" space, the setup and the main loop. In the global space shown below, the servo library is included; the main function of this library is to convert the angle parameters passed to the "write" method into the appropriate electronic control signals. The signals, shown in the pictures above, are pulsed waveforms with the "on" time varying in width depending on the angle. In addition to including the servo library, the global space also allows us the space to create the servo objects that will be necessary to call methods like "write" during the main part of the code.

#include <servo.h>Servo.h // Include the servo library which converts angles to control signals<br>
Servo panServo;  // create panServo object to control the pan servo motor
Servo tiltServo;  // create tiltServo object to control the tilt servo motor</servo.h>

The setup section in the abbreviated version of the code is brief and straight forward. In this section the "attach" method is used to create the logical connection between the servo objects and the physical pins their control signal wire is connected to on the processor board. One special note, servos should be connected to Arduino pins labeled "pwm" as shown in the simplified schematic above.

void setup() {<br>  panServo.attach(52);  // attaches panServo on pin 52 to the servo object
  tiltServo.attach(53);  // attaches tiltServo on pin 53 to the servo object
}

The main loop is the heart of the code and is where the "nested" for loops can be seen. The outer loop is controlling the position of the "pan" servo motor, while the inner loop is controlling the position of the "tilt" servo. In this structure, the inner loop repeats for every iteration of the outer loop and the counter variables are written to the "write" function of the appropriate motor. The delays (as the comments describe) are in place to allow sufficient time for motor movement.

void loop() {
  for (int p = 10; p <=170; p += 10){
    for (int t = 50; t <= 120; t += 10) {
      myservo1.write(p);  // writing current value of pan counter variable to that motor 
      myservo2.write(t);  // writing current value of pan counter variable to that motor 
      delay(100);         // delay to allow for tilt servo motion
      }
    delay(100);           // delay to allow for pan servo motion
  } 
}

Step 3: Adding the "Tracking" Hardware

The final hardware step was to add the ultrasonic sensor. We used the HC-SR04 primarily because we had several available from past projects and the fact that the Arduino code to enable them to make measurements is readily available online. The sensor requires power and ground, as well as an input (trig) and output (echo) connection. We used small pieces of breadboard to avoid having to print s mount for the sensor. One modification we had to make to the original design, was to add a transition point on the top of the post holding the pan and tilt module to convert from the solid core going to the breadboard to a flexible pre-made jumper wire.

Step 4: Adding the "Tracking" Software - Part One

As it's name implies, the ultra-sonic sensor measure distance by transmitting a sound wave and then measuring the time delay before it receives a reflection or echo. To enable the ultra-sonic sensor it is required to establish an output (trig) pin and an input (echo) pin, as well as establishing those two pins as an output and an input respectively. In addition, two variables must be declared to represent the time delay measured and the eventual calculated distance based on that measurement. All the code necessary for basic operation is shown below.

// defines pins numbers
const int trigPin1 = 3; const int echoPin1 = 4; // defines variables long duration1; int distance1;
void setup() {
pinMode(trigPin1, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin1, INPUT); // Sets the echoPin as an Input
void loop() {
// Clears trigPin1 digitalWrite(trigPin1, LOW); delayMicroseconds(2); // Sets trigPin1 on HIGH state for 10 micro seconds digitalWrite(trigPin1, HIGH); delayMicroseconds(10); digitalWrite(trigPin1, LOW); // Reads echoPin1, returns the sound wave travel time in microseconds duration1 = pulseIn(echoPin1, HIGH); // Calculating distance1 distance1 = duration1*0.034/2;

Step 5: Adding the "Tracking" Software - Part Two

The final step was to embed the main part of the code shown in the previous step inside the nested for loops so a measurement could be made directly following each small movement of the tilt servo. This measurement is then compared to the existing smallest distance calculated so far, and if it is smaller, that new value is stored and the corresponding pan and tilt angles are recorded. When the entire area scan is complete, the servos are then instructed to return to the angle they stored for the closet object. The code modifications to accomplish they have been purposefully omitted - if you have read this far, I am sure you want to figure this part out on your own!

Arduino Contest 2019

Participated in the
Arduino Contest 2019