Close

Pan Tilt Servo Control

A project log for DIY Thermal Camera

A $50 thermal camera using a non-contact thermometer, 2 servos, and an Arduino

Michael ShaubMichael Shaub 03/26/2017 at 16:080 Comments

The gimbal was pretty quick to assemble, though the order of connections was critical and I found I had to take it apart and reassemble a couple times before finishing.

Connecting the servos to an Arduino requires some changes to the wiring. The critical thing is to power the servos with an external source, if you don't the Arduino will brown out when trying to move both simultaneously. I used a 6V external power supply so the servos wouldn't be powered through the USB port.

The pan and tilt motion resulted in a way wider angle than I needed. This could be useful when the thermometer needs to be placed close to the target, but lots more math would be required to account for the angle of motion. From a distance the angular motion can be translated linearly without much distortion.

I considered modifying the servos in some way, probably not gearing but maybe the resistance values of the potentiometers inside so the feedback loop would limit the rotation to a more narrow range. I needed higher torque on another project and used these external servo gearboxes from servo city, those could work but would make the gimbal much larger and more complex.

But, luckily I discovered that servos can be controlled from an Arduino with Microseconds instead of angular measurements. Even at the small angles I wanted the servos to move, microsecond signals allow for 500+ steps of movement. This is possible in the standard library, but I ultimately elected to use the alternate VarSpeed library so I could set acceleration speeds when needed.

This is the code I used to test drawing a frame around the area to be scanned, as a preview before beginning the scan.

// Michael Shaub 1/18/2017
// Based on Sweep by BARRAGAN  

#include <Servo.h> 
 
Servo myservoTilt;  // create servo object to control a servo 
Servo myservoPan;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
 
int posTilt = 1500;    // variable to store the servo position 
int posPan = 1500;    // variable to store the servo position

int tiltLimitUpper = 1350; //2000;
int tiltLimitLower = 950; //500;
int panLimitUpper = 1750; //2300;
int panLimitLower = 1350; //700;

boolean countDown = true;

int frameCase = 0; //state of the frame sequence
//0=Upper Left Corner, 1=Upper Right Corner
//2=Lower Right Corner, 3=Lower Left Corner
 
void setup() 
{ 
  myservoTilt.attach(9, tiltLimitLower, tiltLimitUpper);  // attaches the servo on pin 9 to the servo object 
  myservoPan.attach(10, panLimitLower, panLimitUpper);  // attaches the servo on pin 9 to the servo object 
} 
 
 
void loop() 
{ 
  frame();
  delayMicroseconds(500);
} 

void frame(){
  switch(frameCase){
  case 1: //Upper Right Corner
    if(posTilt<=tiltLimitLower){
      frameCase=2;
      delay(5);
    }else{
      posTilt--; 
      myservoTilt.writeMicroseconds(posTilt);  // tell servo to go to position in variable 'posTilt'
    }
    break;
  case 2: //Lower Right Corner
    if(posPan<=panLimitLower){
      frameCase=3;
      delay(5);
    }else{
      posPan--;
      myservoPan.writeMicroseconds(posPan);  // tell servo to go to position in variable 'posPan'
    }
    break;
  case 3: //Lower Left Corner
    if(posTilt>=tiltLimitUpper){
      frameCase=0;
      delay(5);
    }else{
      posTilt++;
      myservoTilt.writeMicroseconds(posTilt);  // tell servo to go to position in variable 'posTilt'
    }
    break;
  default: //Upper Left Corner
    if(posPan>=panLimitUpper){
      frameCase=1;
      delay(5);
    }else{
      posPan++;
      myservoPan.writeMicroseconds(posPan);  // tell servo to go to position in variable 'posPan'
    }
    break;
  }
}

Discussions