servo moving with hand motion

Hi,
I have a MaxSonar EZ1 Ultrasonic Range Finder hooked up to my arduino with a 360 degree servo. I’m trying to make it so that how I move my hand the servo will move. So if i’m moving my hand toward the range finder, the servo will move clockwise, when I pull away it will move counterclockwise…or visa versa I don’t care. Right now it sort of does that but I feel like it could work a lot more solid.
I feel like there’s a better algorithm than what I have now. Sometimes it doesn’t move counterclockwise when it should and sometimes the servo is very choppy. It works best when my hand is moving back in forth in the middle…but up close and far away it’s much more choppy and erratic. I’m getting very good reads in my serial monitor, though, so I know it’s not the sensor…just my terrible programming. :slight_smile: thanks for any help!

#include <Servo.h> 
Servo myservo;  
int inchesOLD, clockwise;

const int pwPin = 7;

long pulse, inches, cm;
void setup() {

  myservo.attach(9); 
  Serial.begin(9600);

}

void loop() {

  pinMode(pwPin, INPUT);
  pulse = pulseIn(pwPin, HIGH);
  inches = pulse/147;
 
  if (inches>=inchesOLD){ //if inches are increasing i.e. you're pulling away, it should spin clockwise
    clockwise=0;
  }
  else if (inches<inchesOLD){
    clockwise=1;       //or else it should go counter clockwise when you're
  }
  Serial.print(inches);
  Serial.print("in");
  Serial.println();
  delay(50);

  if (inches>30) {   
    myservo.write(90);    
  }
  if ((inches<=29)&&(inches>=28)) {
    if (clockwise==1){
      myservo.write(80);
    } 
    else {
      myservo.write(110);
    }
  }

  if ((inches<=27)&&(inches>=24)) {
    if (clockwise==1){
      myservo.write(70);
    } 
    else { 
      myservo.write(130);
    }
  }

  if ((inches<=23)&&(inches>=20)) {
    if (clockwise==1) {
      myservo.write(50);
    }
    else{
      myservo.write(150);
    }
  }

  if ((inches<=19)&&(inches>=16)) {
    if (clockwise==1){
      myservo.write(5);
    }
    else{
      myservo.write(160);
    }
  }

  if ((inches<=15)&&(inches>=11)) {
    if(clockwise==1){
      myservo.write(50);
    }
    else {
      myservo.write(175);
    }
  }

  if ((inches<=10)&&(inches>=9)){
    if(clockwise==1){
      myservo.write(80);
    }
    else { 
      myservo.write(170);
    }
  }
  if ((inches<=8)&&(inches>=7)){
    if(clockwise==1){
      myservo.write(85);
    }
    else{
      myservo.write(95);
    }
  }
  if (inches==5){
    myservo.write(90);

  }
  inchesOLD=inches;

}

Does the servo have a separate power supply, or are you powering from the Arduino? From experience erratic servo's can mean erratic/inadequate power supply. If you're getting good serial output then your programming might be OK...

Cheers,

i’m powering it from the arduino…how do you power a servo without an arduino anyway? well…i know how to do it from a battery…but do you know how to do it from an adapter?
i still am pretty sure my code is a little out of whack. i’m trying to say when the variable before is greater than then new one, do this, when it’s smaller, do that. I feel like i’ve read about this algorithm before…but I can’t find it anywhere.
thanks for any help!

  if (inches>=inchesOLD){ //if inches are increasing i.e. you're pulling away, it should spin clockwise
    clockwise=0;
  }
  else if (inches<inchesOLD){
    clockwise=1;       //or else it should go counter clockwise when you're
  }

There are only two possibilities. Either the new value is less than the old value, or it isn’t. If the first if is true, the else block will be skipped. If the first if is false, the else clause will be visited. The if test there, then, MUST be true, so it isn’t needed.

  if (inches>=inchesOLD)
  { //if inches are increasing i.e. you're pulling away, it should spin clockwise
    clockwise=0;
  }
  else
  {
    clockwise=1;       //or else it should go counter clockwise when you're
  }

Even this could be shortened.

  clockwise = 0;
  if(inches < inchesOld)
     clockwise = 1;

With the rest of the code, some else statements would be useful:

int off = 0;
if(inches > 30)
   off = 0;
else if(inches > 27)
   off = 10;
else if(inches > 24)
   off = 20;
// a few more else if clauses go here

int pos = 90 + off;
if(clockwise)
   pos = 90 - off;
myservo.write(pos);

Thank you so much for your help! You’ve really helped me with my programming…
Here is the new code. It works pretty good. Just the sensor is a little jittery with its readings…but I bought the cheapest one I could find :slight_smile:

#include <Servo.h> 
Servo myservo;  
int inchesOLD, clockwise;

const int pwPin = 7;

long pulse, inches, cm;
void setup() {

  myservo.attach(9); 
  Serial.begin(9600);

}

void loop() {

  pinMode(pwPin, INPUT);
  pulse = pulseIn(pwPin, HIGH);
  inches = pulse/147;

  clockwise=0;

  if(inches < inchesOLD)
    clockwise=1;

  if (inches == inchesOLD)
    clockwise=2;

  Serial.print(inches);
  Serial.print("in");
  Serial.println();
  delay(50);

  int off = 0;

  if (inches>30)
    off=0;
  else if (inches >27)
    off = 10;
  else if (inches >24)
    off = 20;
  else if (inches > 21)
    off = 30;
  else if (inches > 18)
    off = 40;
  else if (inches > 15)
    off = 50;
  else if (inches > 10)
    off = 60;
  else if (inches > 5)
    off = 70;

  int pos = 90 + off;

  if(clockwise)
    pos = 90 - off;
  
  if (clockwise==2) //if nothing changes, keep servo still
    pos = 90;
     
  myservo.write(pos);

  inchesOLD=inches;

}