Blue Robotics - PWM - Two Button Control Help?

Good Morning All,

I am putting this post together to get some help / insight to my beginner brain to Arduino, a little explanation of what I am aiming to do and what I have managed to do.

So let me begin with what I have, I have a Blue Robotics Newton Subsea Gripper and with this I am aiming to use two buttons to control the gripper with the functions to be while holding open the gripper opens and when released it stops dead in its tracks and then the same function with the close button.

This is the code that I have so far, and what it does is allows for me to close the gripper but its on a constant open which isnt what I am after I want to have complete control over the gripper.

Any help and guidance would be great,

Thanks Again.

also please find attached a picture of the quick set up.

#include "Servo.h"

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin
#define LEFT 12 // PIN 2 IS CONNECTED TO LEFT BUTTON       
#define RIGHT 2 // PIN 2 IS CONNECTED TO RIGHT BUTTON         

#define OPEN_PWM_US       1100  // Gripper open PWM output (us)
#define CLOSE_PWM_US      1900  // Gripper close PWM output (us)

const int buttonPin = 2;
const int ledPin = 9;


int buttonState = 0;
int buttonState2 = 0;

Servo gripper;

void setup() {

  pinMode(ledPin, OUTPUT);  
  // Attach gripper to proper pin
  gripper.attach(GRIPPER_PWM_PIN);
  pinMode(LEFT,INPUT_PULLUP); // assign pin 12 ass input for Left button
  pinMode(RIGHT,INPUT_PULLUP);// assing pin 2 as input for right button
}

void loop() {
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper
  if (buttonState == LOW) {
    // turn LED on:
    gripper.writeMicroseconds(OPEN_PWM_US);
  } else if (buttonState == HIGH) {
    // turn LED off:
    gripper.writeMicroseconds(CLOSE_PWM_US);
    
  }
     


}
[/c]

According to the way I read this, what it's doing at the moment is opening when one of the buttons is pressed, (buttonState == LOW), and it closes when that button is released (buttonState == HIGH)?

// Open the gripper
  if (buttonState == LOW) {
    // turn LED on:
    gripper.writeMicroseconds(OPEN_PWM_US);
  } else if (buttonState == HIGH) {
    // turn LED off:
    gripper.writeMicroseconds(CLOSE_PWM_US);
   
  }

So if you lose the "if" in there, when that button is released nothing will happen; it will stay where it is.

Then do the same for the other button' state, but make it close.

In other news:

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin

... you can use any pin for a servo, not just the PWM~ pins.

Do you want it to "slam" closed (all or nothing?) rather than "step" closed so you don't crush whatever it is you're trying to pick up?

sayHovis:
Do you want it to "slam" closed (all or nothing?) rather than "step" closed so you don't crush whatever it is you're trying to pick up?

With this we want to close as its going to be used on debris so full close will be fine.

sayHovis:
According to the way I read this, what it's doing at the moment is opening when one of the buttons is pressed, (buttonState == LOW), and it closes when that button is released (buttonState == HIGH)?

// Open the gripper

if (buttonState == LOW) {
    // turn LED on:
    gripper.writeMicroseconds(OPEN_PWM_US);
  } else if (buttonState == HIGH) {
    // turn LED off:
    gripper.writeMicroseconds(CLOSE_PWM_US);
 
  }




So if you lose the "if" in there, when that button is released nothing will happen; it will stay where it is.

Then do the same for the other button' state, but make it close.

In other news:



#define GRIPPER_PWM_PIN  9    // Gripper PWM output pin




... you can use any pin for a servo, not just the PWM~ pins.

Thank you for that when applying this to the code:

void loop() {
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper
  (buttonState == LOW);{
    // turn LED on:
    gripper.writeMicroseconds(OPEN_PWM_US);
  }(buttonState == HIGH); {
    // turn LED off:
    gripper.writeMicroseconds(CLOSE_PWM_US);
    
  }
}

the servo motor gets very twitchy and doesn't give me any control over the buttons, however reverting back to the original code if allows me to do this:

Link to Youtuve Video

So from this When i release the button i just want it to stop and not return to an open state.

Sorry, I didn't mean lose the word "if", I actually meant take out the else half, so you have just this:

if (buttonState == LOW) 
{
    // turn LED on:
    gripper.writeMicroseconds(OPEN_PWM_US);
}

Since it doesn't have an "else if" any more, it's not going to do anything when buttonState goes high.

Then have a similar one checking buttonState2, doing the close.

Try this:

// forum 648969
// 19 nov 2019


#include "Servo.h"

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin
#define LEFT 12 // PIN 2 IS CONNECTED TO LEFT BUTTON       
#define RIGHT 2 // PIN 2 IS CONNECTED TO RIGHT BUTTON         

#define OPEN_PWM_US       1100  // Gripper open PWM output (us)
#define CLOSE_PWM_US      1900  // Gripper close PWM output (us)

const int buttonPin = 2;
const int ledPin = 9;


int buttonState = 0;
int buttonState2 = 0;

Servo gripper;

void setup()
{
  pinMode(ledPin, OUTPUT);
  // Attach gripper to proper pin
  gripper.attach(GRIPPER_PWM_PIN);
  pinMode(LEFT, INPUT_PULLUP); // assign pin 12 ass input for Left button
  pinMode(RIGHT, INPUT_PULLUP); // assing pin 2 as input for right button
}

void loop()
{
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper
  if (buttonState == LOW)
  {
    // turn LED on:
    gripper.writeMicroseconds(OPEN_PWM_US);
  }//open

  //close
  if (buttonState2 == LOW)
  {
    // turn LED off:
    gripper.writeMicroseconds(CLOSE_PWM_US);
  }//close

}//loop

Works for me on a small hobby servo:

  • One button pushed sends it one way, it stays there when released.
  • The other button pushed returns it, stays there when released.

sayHovis:
Sorry, I didn't mean lose the word "if", I actually meant take out the else half, so you have just this:

if (buttonState == LOW) 

{
   // turn LED on:
   gripper.writeMicroseconds(OPEN_PWM_US);
}




Since it doesn't have an "else if" any more, it's not going to do anything when buttonState goes high.

Then have a similar one checking buttonState2, doing the close.

Ah i see what you mean now, so with me apply this to the code the motor still keeps going (Video V2)

Updated Code:

#include "Servo.h"

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin
#define LEFT 12 // PIN 2 IS CONNECTED TO LEFT BUTTON       
#define RIGHT 2 // PIN 2 IS CONNECTED TO RIGHT BUTTON         

#define OPEN_PWM_US       1100  // Gripper open PWM output (us)
#define CLOSE_PWM_US      1900  // Gripper close PWM output (us)

const int buttonPin = 2;
const int ledPin = 9;


int buttonState = 0;
int buttonState2 = 0;

Servo gripper;

void setup() {

  pinMode(ledPin, OUTPUT); 
  // Attach gripper to proper pin
  gripper.attach(GRIPPER_PWM_PIN);
  pinMode(LEFT,INPUT_PULLUP); // assign pin 12 ass input for Left button
  pinMode(RIGHT,INPUT_PULLUP);// assing pin 2 as input for right button
}

void loop() {
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper
if (buttonState == LOW){
    // open gripper:
    gripper.writeMicroseconds(OPEN_PWM_US);
}
     
if (buttonState2 == LOW){
    // close gripper:
    gripper.writeMicroseconds(CLOSE_PWM_US);
}

}

Oh wait we're at cross purposes here, and /or I didn't read the opening post properly.

To get it to stop when you let go of the button, you can't just send it to a position with one command.

You need a variable for the position, and while the button is pressed, as it loops, it increments or decrements the variable each time. Then each time through loop() you write to the new position, which is one step more open or more closed than last time.

So when you release the button, it doesn't increment and step any more, so it stops.

Sorry to sound a bit thick, would you be able to simplify this for me please, as i wouldnt know where to start on adding this to the code.

AaronClark_1989:
Sorry to sound a bit thick, would you be able to simplify this for me please, as i wouldnt know where to start on adding this to the code.

Busy with it even as we speak....

Ok try this... it moves one way as you hold one button, stops where it is on release. Ditto the other button but opposite direction.

You can tune the speed by changing these lines:

byte servoIncrement = 50; //just above setup()
delay(100); //last line of loop()

Using delay() is a bit of a quick-n-dirty way of timing things, but should might be ok here. (Unless the program needs to do anything else where timing is critical.)

#include "Servo.h"

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin
#define LEFT 12 // PIN 2 IS CONNECTED TO LEFT BUTTON      
#define RIGHT 2 // PIN 2 IS CONNECTED TO RIGHT BUTTON        

#define OPEN_PWM_US       1100  // Gripper open PWM output (us)
#define CLOSE_PWM_US      1900  // Gripper close PWM output (us)

int servoPos = 1500; //starts in the middle
byte servoIncrement = 50; // how much to change each time thru loop, may need to be more or less

//const int buttonPin = 2; //this is redundant
//const int ledPin = 9; //this is redundant

int buttonState = 0;
int buttonState2 = 0;

Servo gripper;

void setup() {

  //pinMode(ledPin, OUTPUT); //this is redundant
  // Attach gripper to proper pin
  gripper.attach(GRIPPER_PWM_PIN);
  pinMode(LEFT, INPUT_PULLUP); // assign pin 12 ass input for Left button
  pinMode(RIGHT, INPUT_PULLUP); // assing pin 2 as input for right button
}

void loop()
{
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper 
  if (buttonState == LOW)
  {
    // open gripper:
    servoPos = servoPos - servoIncrement;
    if (servoPos <= OPEN_PWM_US) servoPos = OPEN_PWM_US; //it's already open
    gripper.writeMicroseconds(servoPos);
  }

  if (buttonState2 == LOW)
  {
    // close gripper:
    servoPos = servoPos + servoIncrement;
    if (servoPos >= CLOSE_PWM_US) servoPos = CLOSE_PWM_US; //it's already open
    gripper.writeMicroseconds(servoPos);
  }
  delay(100); //make longer or shorter or remove it
}//loop

Thank you for that it is really appreciated, however it still doesn't want to stop...

I can see that you've added in the 1500 for a neutral signal so that it stops.

The start position when you attach, defaults to 1500 anyway. So I just put that in a variable, so that when we do the first add or subtract of the increment, it knows where it is to start with.

As to why it doesn't stop for you, I can't say. I just copied the code I posted back to me again from the forum in case I uploaded the wrong version, compiled it and it runs correctly for me. Servo only moves while either button is pressed, each causes a different direction, and when either button is released the servo stops right there.

Can we just confirm your buttons are wired from their respective pins direct to ground?

Not a problem please find the pictures below I believe I have them wired up correctly but its always worse a second pair of eyes.


Image 1


Image 2

It does look right....

Run this version with the serial monitor open at 9600 or change the begin. It should print that it's opening or closing, or print nothing while neither button is pressed.

opening
opening
opening
  closing
  closing
  closing
  closing
  closing
  closing
opening
opening
  closing
  closing
  closing
  closing
opening
#include "Servo.h"

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin
#define LEFT 12 // PIN 2 IS CONNECTED TO LEFT BUTTON      
#define RIGHT 2 // PIN 2 IS CONNECTED TO RIGHT BUTTON        

#define OPEN_PWM_US       1100  // Gripper open PWM output (us)
#define CLOSE_PWM_US      1900  // Gripper close PWM output (us)

int servoPos = 1500; //starts in the middle
byte servoIncrement = 50; // how much to change each time thru loop, may need to be more or less

//const int buttonPin = 2; //this is redundant
//const int ledPin = 9; //this is redundant

int buttonState = 0;
int buttonState2 = 0;

Servo gripper;

void setup() {
  Serial.begin(9600);
  //pinMode(ledPin, OUTPUT); //this is redundant
  // Attach gripper to proper pin
  gripper.attach(GRIPPER_PWM_PIN);
  pinMode(LEFT, INPUT_PULLUP); // assign pin 12 ass input for Left button
  pinMode(RIGHT, INPUT_PULLUP); // assing pin 2 as input for right button
}

void loop()
{
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper
  if (buttonState == LOW)
  {
    // open gripper:
    Serial.println("opening");
    servoPos = servoPos - servoIncrement;
    if (servoPos <= OPEN_PWM_US) servoPos = OPEN_PWM_US; //it's already open
    gripper.writeMicroseconds(servoPos);
  }

  if (buttonState2 == LOW)
  {
    // close gripper:
    Serial.println("  closing");
    servoPos = servoPos + servoIncrement;
    if (servoPos >= CLOSE_PWM_US) servoPos = CLOSE_PWM_US; //it's already open
    gripper.writeMicroseconds(servoPos);
  }
  delay(100); //make longer or shorter or remove it
}//loop

When running the serial monitor, I can see it opening and closing when each button is pressed, but nothing seems to happen on the release i.e. nothing to show that its going to 1500, would it be possible to show this in the serial monitor to aim to debug it?

Looking more into it here:

Comms log

This looks alot longer than yours.

but nothing seems to happen on the release i.e. nothing to show that its going to 1500, would it be possible to show this in the serial monitor to aim to debug it?

It doesn't go to 1500 when you release a button: it stops where it is.

1500 is where it starts at power up or reset.

If you want it to go to 1500 when neither button is pressed, I added this:

if (buttonState == HIGH && buttonState2 == HIGH)
  {
    servoPos = 1500;
    gripper.writeMicroseconds(servoPos);
    Serial.println("     centred");
  }

Thus:

#include "Servo.h"

#define GRIPPER_PWM_PIN   9    // Gripper PWM output pin
#define LEFT 12 // PIN 2 IS CONNECTED TO LEFT BUTTON      
#define RIGHT 2 // PIN 2 IS CONNECTED TO RIGHT BUTTON        

#define OPEN_PWM_US       1100  // Gripper open PWM output (us)
#define CLOSE_PWM_US      1900  // Gripper close PWM output (us)

int servoPos = 1500; //starts in the middle
byte servoIncrement = 50; // how much to change each time thru loop, may need to be more or less

//const int buttonPin = 2; //this is redundant
//const int ledPin = 9; //this is redundant

int buttonState = 0;
int buttonState2 = 0;

Servo gripper;

void setup() {
  Serial.begin(9600);
  //pinMode(ledPin, OUTPUT); //this is redundant
  // Attach gripper to proper pin
  gripper.attach(GRIPPER_PWM_PIN);
  pinMode(LEFT, INPUT_PULLUP); // assign pin 12 ass input for Left button
  pinMode(RIGHT, INPUT_PULLUP); // assing pin 2 as input for right button
  Serial.println("setup() complete");
}

void loop()
{
  buttonState = digitalRead(RIGHT);
  buttonState2 = digitalRead(LEFT);

  // Open the gripper
  if (buttonState == LOW)
  {
    // open gripper:
    Serial.println("opening");
    servoPos = servoPos - servoIncrement;
    if (servoPos <= OPEN_PWM_US) servoPos = OPEN_PWM_US; //it's already open
    gripper.writeMicroseconds(servoPos);
  }

  if (buttonState2 == LOW)
  {
    // close gripper:
    Serial.println("  closing");
    servoPos = servoPos + servoIncrement;
    if (servoPos >= CLOSE_PWM_US) servoPos = CLOSE_PWM_US; //it's already open
    gripper.writeMicroseconds(servoPos);
  }

  if (buttonState == HIGH && buttonState2 == HIGH)
  {
    servoPos = 1500;
    gripper.writeMicroseconds(servoPos);
    Serial.println("     centred");
  }
  
  delay(100); //make longer or shorter or remove it
}//loop

AaronClark_1989:
This looks alot longer than yours.

Well it goes through loop() every 100ms after the delay(100) so it does depend how long you hold the button down.