Simple Button Control for Robotic Arm

Im playing around with a robotic arm. It has 2 servos (one moves the arm and the other open/closes the claw). It works but it jitters a bit on both servos because of noise. What I mean is both servos jitter or move around or wiggle a bit if i just let it sit there. How do I work around that?

This is my sketch:

/*
 Controlling a servo position using a potentiometer (variable resistor)
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

Servo myservo1;  // create servo object to control a servo gyro
Servo myservo2;  // create servo object to control a servo claw

int potpin1 = 0;  // analog pin used to connect the pot1
int val1;    // variable to read the value from the analog pin 0
int button = 0;    // variable to read the value from the analog pin 2

const int buttonPin = 2;     // the number of the pushbutton pin

int buttonState;             // the current reading from the input pin
int buttonFlag = 0;          // button never been pressed

void setup() {
  myservo1.attach(9);  // attaches the servo1 on pin 9 to the servo object
  myservo2.attach(10);  // attaches the servo2 on pin 10 to the servo object
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  myservo2.write(10); // open claw
  buttonState = 1; // state = open
}

void loop() {
  val1 = analogRead(potpin1);            // reads the value of the potentiometer (value between 0 and 1023)
  Serial.println(val1);
  val1 = map(val1, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo1.write(val1);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there

  button = digitalRead(buttonPin);
  Serial.println(button);
  
  if (button == 1) {
    Serial.println("Button Clicked");
    buttonFlag = 1;
    toggleClaw();
  }
}

void toggleClaw() {
  if (buttonState == 1) { //claw is open
    closeClaw();
  } else  {//if (buttonState == 0)
    openClaw();
  }
}

void openClaw() {
  buttonState = 1;    //record that buttonState is now open-1
  myservo2.write(10);                 // sets the servo position according to the scaled value
}

void closeClaw() {
  buttonState = 0;    //state now closed
  myservo2.write(170);
}

Most servo issues relate back to inadequate servo power supply, or possibly over loading the servo.

I thought servo jitter was normal, when they are under load. Am I wrong?

Why is the variable that toggles the claw state called buttonState? Wouldn’t fred be a better name? Why not?

Why are you toggling the claw when the switch IS pressed? That seems like something that should be done when the switch BECOMES pressed.

How ARE the servos powered?

I'm powering from the board. I'll use the battery pack.

How would I toggle when the button BECOMES pressed?

How would I toggle when the button BECOMES pressed?

By now, you should be quite familiar with all the example code that comes with the IDE. If you are not, either put the Arduino away OR become familiar with the examples. There IS one that covers that question.

Thanks Paul, I was being lazy!

I was trying to remember how I solved similar issues in iOS game programming when a bullet struck a target the first time and not having to fire it again with every subsequent collision after that as the bullet “traversed” the target polygon. I remembered we use flags to note when a collision had first occurred and after that was set to true, detection ceased for a while. I just wasnt able to work out the details.

I found the Debounce example, thanks. I have a small doubt. In this bit of code:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }

after we detect the recently read state ‘reading’ ISNOT equal to the current ‘buttonState’, it must mean the button was touched. We then update the ‘buttonState’ with the new ‘reading’ state.

Since the ledState starts out LOW, if the new value is HIGH, then we toggle the LED…but what does:

ledState = !ledState;

do, exactly? Im not sure what we are doing here. Is it saying to set ledState to the opposite of whatever it is? Does that work in this case because its a value that can only be LOW or HIGH? Btw, how does that work since we defined it as an int (which can take any + whole numerical value) instead of opposing LOW-HIGH values?

Fixed it like so:

/*
 Controlling a servo position using a potentiometer (variable resistor)
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

Servo myservo1;  // create servo object to control a servo gyro
Servo myservo2;  // create servo object to control a servo claw

int potpin1 = 0;  // analog pin used to connect the pot1
int val1;    // variable to read the value from the analog pin 0
const int buttonPin = 2;     // the number of the pushbutton pin

int clawState = HIGH;             // the claw start out open
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  myservo1.attach(9);  // attaches the servo1 on pin 9 to the servo object
  myservo2.attach(10);  // attaches the servo2 on pin 10 to the servo object
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  openClaw();
}

void loop() {
  //Start by sweeping servo1
  sweepServo();
  
  //Read state of buttonPin
  int reading = digitalRead(buttonPin);
  Serial.println(reading);

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

    if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        clawState = !clawState;
        //should i just call openClaw() here???????????
      }
    }
  }

  //set claw to latest logically defined state
  toggleClaw();
  
  //save most recent state
  lastButtonState = reading;
}

void sweepServo() {
  val1 = analogRead(potpin1);            // reads the value of the potentiometer (value between 0 and 1023)
  Serial.println(val1);
  val1 = map(val1, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo1.write(val1);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}

void toggleClaw() {
  if (clawState == 1) { //claw is open
    closeClaw();
  } else  {
    openClaw();
  }
}

void openClaw() {
  //clawState = 1;    //record that buttonState is now open-1
  myservo2.write(10);                 // sets the servo position according to the scaled value
}

void closeClaw() {
  //clawState = 0;    //state now closed
  myservo2.write(170);
}

I found the Debounce example

The state change detection example was the one I was referring to.

  if (reading != lastButtonState) {

Wouldn't comparing variables with similar names, like currSwitchState and prevSwitchState, make more sense?