4 Servo Sweep Control

I need this code so when I press the left button, the servo starts a sweep motion and when I press the right button, it stops the sweep motion (for 4 servos).
I am new to Arduino, so if you can leave and explanation, that would be nice. Thanks! I got this code from an instructable if you are curious (http://www.instructables.com/id/How-to-Control-3-Servo-Motors-using-Push-Button-Sw/step8/Programming-the-Arduino-The-Main-Loop-explained/)

Here is the code below (I also attached it to the post if you would prefer)

#include <Servo.h>

Servo myservo; // create servo object to control a servo
Servo myservo2;
Servo myservo3;
Servo myservo4;

int pos1 = 85; // variable to store the servo's starting position
int pos2 = 85;
int pos3 = 85;
int pos4 = 85;

const int maxDeg = 175; // limits the maximum range of the servo's movement to 175
const int minDeg = 5; // limits the minimum range of the servo's movement to 5

const int movement = 2; // distance to move servo

// This basically means the servo will sweep from 5 to 175 (not 0 to 180 as expected), you can adjust this to suit your own servo motors specs

const int leftPin = 2; // tells the Arduino the location of the signal cable from the switch
const int rightPin = 3;

const int leftPin2 = 4;
const int rightPin2 = 5;

const int leftPin3 = 6;
const int rightPin3 = 7;

const int leftPin4 = 12;
const int rightPin4 = 13;

const int outputPin = 8; // tells the Arduino the location of the signal cable to the servo
const int outputPin2 = 9;
const int outputPin3 = 10;
const int outputPin4 = 11;

int leftPressed = 0; // variables we will use to keep information about the switch states
int rightPressed = 0;

int leftPressed2 = 0;
int rightPressed2 = 0;

int leftPressed3 = 0;
int rightPressed3 = 0;

int leftPressed4 = 0;
int rightPressed4 = 0;

void setup()
{
myservo.attach(outputPin); // attaches the servo motor's signal cable location, stored in the variable outputPin, to the servo object
myservo2.attach(outputPin2);
myservo3.attach(outputPin3);
myservo4.attach(outputPin4);

pinMode(leftPin, INPUT); // sets the state of the pins to input mode
pinMode(rightPin, INPUT);

pinMode(leftPin2, INPUT);
pinMode(rightPin2, INPUT);

pinMode(leftPin3, INPUT);
pinMode(rightPin3, INPUT);

pinMode(leftPin4, INPUT);
pinMode(rightPin4, INPUT);
}

void loop()
{
leftPressed = digitalRead(leftPin); //gives a value to the variables as the state of the switch
rightPressed = digitalRead(rightPin);

leftPressed2 = digitalRead(leftPin2);
rightPressed2 = digitalRead(rightPin2);

leftPressed3 = digitalRead(leftPin3);
rightPressed3 = digitalRead(rightPin3);

leftPressed4 = digitalRead(leftPin4);
rightPressed4 = digitalRead(rightPin4);

// The following routine handles what happens if the first set of push buttons are pressed

if(leftPressed){
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0; // variable to store the servo position

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop() {
for (pos = 0; pos <= 180; pos += 1) {
// in steps of 1 degree
myservo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 1) {
myservo.write(pos);
delay(15);
}
}

if(rightPressed){
if(pos > minDeg)
pos -= movement;
myservo.write(pos); // tells the servo to go to the position stored in the variable ‘pos’
}

// The following routine handles what happens if the second pair of push buttons are pressed

if(leftPressed2){
if(pos2 < maxDeg)
pos2 += movement;
myservo2.write(pos2);
}

if(rightPressed2){
if(pos2 > minDeg)
pos2 -= movement;
myservo2.write(pos2);
}

// The following routine handles what happens if the third pair of push buttons are pressed

if(leftPressed3){
if(pos3 < maxDeg)
pos3 += movement;
myservo3.write(pos3);
}

if(rightPressed3){
if(pos3 > minDeg)
pos3 -= movement;
myservo3.write(pos3);
}

// The following routine handles what happens if the fourth pair of push buttons are pressed

if(leftPressed4){
if(pos4 < maxDeg)
pos4 += movement;
myservo4.write(pos4);
}

if(rightPressed4){
if(pos4 > minDeg)
pos4 -= movement;
myservo4.write(pos4);
}

}

//if(rightPressed3){
// ctrl_servo(myservo3, pos3, -1);

//void ctrl_servo(servo, poss, dir){
// if(poss > minDeg)
// poss += movement*dir;
// servo.write(poss);
// }
// else;
// delay(15);
// }

_4_Servo_Button_Switch_Odyssey.ino (4.45 KB)

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Your servos will have to be powered of their own power supply.

If you look in the Arduino IDE Examples there are servo example code for you to try and see how the servo library is used.

Can you tell us your electronics, programming, Arduino, hardware experience?

What you propose is possible, what model Arduino are you using?

Thanks.. Tom.. :slight_smile:

Hi,
I'm his partner on the project.

First of all, I am working on a diagram of the circuit now.
We have been using an Arduino Uno R3.

We are aware that our servos have to be powered of their own power supply.

Thanks for the help :slight_smile:

The problem with the sweep sketch is that you can't break into the sweeping to stop it once it's started; that's the nature of the "for" which does the sweeping.

I'm posting a sketch here which sweeps 2 servos independently of each other, but (alas for you right now :wink: ) does not have any buttons. To understand this sketch, you will need to first digest the BlinkWithOutDelay approach; look in the IDE at File > Examples > Digital.

Each time through loop() it checks to see if each servo is due for a move, using the 2x functions moveX() and moveY(). The use of functions like that will make your button idea feasible: you could make the calls to moveX() and moveY() (and ultimately for you, 2 more) conditional on the state* of your buttons.

  • Have a look at the StateChangeDetection sketch, also at File > Examples > Digital.

Here's my code. Variables include those to set each servo's start and end degree points, as well as the number of degrees per update, and the time between updates.

//idea is for two servos to go up and down ala sweep
//   BUT to interleave their motion, checking to see if either servo is due for a move
//   each time thru loop()

// in this one the servos can have diff ranges and speeds
// both of which hardcoded (for now, any way)

//basically blink without delay thinking: each servo updates only when due,
// and other stuff can happen in the sketch since the servo stuff doesn't block

#include <Servo.h>

Servo servoX;
Servo servoY;

byte posX;
byte posY;

byte posXmin = 10;
byte posXmax = 170;

byte posYmin = 50;
byte posYmax = 100;

int stepX = -1; //degrees per move.. gets *-1 immed for +1 first time
int stepY = -1;

unsigned long currentMillis = 0;
unsigned long previousMillisX = 0; // the time when the servo was last moved
unsigned long previousMillisY = 0;
int speedX = 25; //millisec per update, larger is slower
int speedY = 100;

//  (un)-comment the following
//#define DEBUG //serial prints
#define DEBUG1 //led13 off because it's so annoying
//#define LCD_PRESENT_BUT_NOT_USED

void setup()
{
  posX = posXmin;
  posY = posYmin;

  servoX.write(posX);  //initialise
  servoY.write(posY);

  servoX.attach(2);  //2, 3, 11, 12, 13 vacant on dfr0009 lcd
  servoY.attach(3);

#ifdef DEBUG
  Serial.begin(9600);
  Serial.println("setup " + String(posX) + " " + String(posY));
  delay(1000);
#endif

#ifdef DEBUG1
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
#endif

#ifdef LCD_PRESENT_BUT_NOT_USED
  pinMode(10, OUTPUT); //turn backlight off
#endif
}


void loop()
{
  currentMillis = millis();
  moveX();
  moveY();

#ifdef DEBUG
  delay(100);
#endif
}//loop

void moveX()
{
  if (currentMillis - previousMillisX >= speedX) //move if X time elapsed else nothing
  {
    previousMillisX = currentMillis;

    if ((posX == posXmin) || (posX == posXmax))
    {
      stepX = -1 * stepX;
    }

    servoX.write(posX);
    //delay(15);
    posX = posX + stepX;

#ifdef DEBUG
    Serial.print("moveX " + String(posX) + " " + String(stepX));
#endif
  }//millis if
} //moveX

void moveY()
{
  if (currentMillis - previousMillisY >= speedY) //move if Y time elapsed else nothing
  {
    previousMillisY = currentMillis;

    if ((posY == posYmin) || (posY == posYmax))
    {
      stepY = -1 * stepY;
    }

    servoY.write(posY);
    //delay(15);
    posY = posY + stepY;

#ifdef DEBUG
    Serial.println("  moveY " + String(posY) + " " + String(stepY));
#endif
  }//timing
}//moveY

Hi,

WHY does your code have TWO void setup() and TWO void loop() ?

Might I suggest you code for ONE SERVO only and get it working, leave the coding for the other three to later.
Your code will be SOOO much more easier to read and edit.

Thanks.... Tom.. :slight_smile:

TomGeorge:
WHY does your code have TWO void setup() and TWO void loop() ?

Probably indicates the OP and partner are at the cobbling any stuff together stage of their learning.

edit: by which I mean no disrespect, just pointing out that it works better if you go from first principles with (say) the examples in the IDE at File > Examples.

TomGeorge:
Might I suggest you code for ONE SERVO only and get it working, leave the coding for the other three to later.

I second that: using functions like I showed in my example lends itself to that. (Can even put the calls in to the other 3, and have those functions empty just to keep the compiler happy, as placeholders to help get the program structure clear. )

But one thing's for sure: if you don't use a BlinkWithOutDelay approach, even with only one servo, you will not be able to read a button during a sweep.

This is a diagram of our breadboard. I apologize for it not being very neat.

Here's the pic inline to save others having to download it.

Thanks for the support!

Hi,
Can you answer post #4 please.

Thanks.. Tom.... :slight_smile:

So basically this only controls 2 servos and isn't coded to work with buttons.

My partner and I are only fifth graders and are very new to the concept.
All the help possible is much appreciated

Thanks to TomGeorge for the help.
This is the code again

#include  <Servo.h>

Servo myservo;  // create servo object to control a servo 
Servo myservo2; 
Servo myservo3;
Servo myservo4;

int pos1 = 85;    // variable to store the servo's starting position
int pos2 = 85; 
int pos3 = 85;
int pos4 = 85;

const int maxDeg = 175; // limits the maximum range of the servo's movement to 175
const int minDeg = 5;   // limits the minimum range of the servo's movement to 5

const int movement = 2; // distance to move servo

// This basically means the servo will sweep from 5 to 175 (not 0 to 180 as expected), you can adjust this to suit your own servo motors specs



const int leftPin = 2; // tells the Arduino the location of  the signal cable from the switch 
const int rightPin = 3;

const int leftPin2 = 4;
const int rightPin2 = 5;

const int leftPin3 = 6;
const int rightPin3 = 7;

const int leftPin4 = 12;
const int rightPin4 = 13;

const int outputPin = 8; // tells the Arduino the location of the signal cable to the servo 
const int outputPin2 = 9; 
const int outputPin3 = 10;
const int outputPin4 = 11;

int leftPressed = 0; // variables we will use to keep information about the switch states
int rightPressed = 0;

int leftPressed2 = 0;
int rightPressed2 = 0;

int leftPressed3 = 0;
int rightPressed3 = 0;

int leftPressed4 = 0;
int rightPressed4 = 0;


void setup() 
{ 
myservo.attach(outputPin);  // attaches the servo motor's signal cable location, stored in the variable outputPin, to the servo object 
myservo2.attach(outputPin2);
myservo3.attach(outputPin3);
myservo4.attach(outputPin4);

pinMode(leftPin, INPUT); // sets the state of the pins to input mode
pinMode(rightPin, INPUT);

pinMode(leftPin2, INPUT);
pinMode(rightPin2, INPUT);

pinMode(leftPin3, INPUT);
pinMode(rightPin3, INPUT);

pinMode(leftPin4, INPUT);
pinMode(rightPin4, INPUT);
} 

void loop() 
{ 
leftPressed = digitalRead(leftPin); //gives a value to the variables as the state of the switch
rightPressed = digitalRead(rightPin);

leftPressed2 = digitalRead(leftPin2);
rightPressed2 = digitalRead(rightPin2);

leftPressed3 = digitalRead(leftPin3);
rightPressed3 = digitalRead(rightPin3);

leftPressed4 = digitalRead(leftPin4);
rightPressed4 = digitalRead(rightPin4);

// The following routine handles what happens if the first set of push buttons are pressed

 if(leftPressed){  
Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { 
    // in steps of 1 degree
    myservo.write(pos);              
    delay(15);                       
  }
  for (pos = 180; pos >= 0; pos -= 1) { 
    myservo.write(pos);              
    delay(15);                       
   }                       
}
      
 if(rightPressed){
   if(pos > minDeg) 
      pos -= movement;
      myservo.write(pos);             // tells the servo to go to the position stored in the variable 'pos'            
     }                      

// The following routine handles what happens if the second pair of push buttons are pressed

 if(leftPressed2){
   if(pos2 < maxDeg) 
      pos2 += movement;
      myservo2.write(pos2);          
   }                      

 if(rightPressed2){
   if(pos2 > minDeg) 
      pos2 -= movement;
      myservo2.write(pos2);              
      }                     

// The following routine handles what happens if the third pair of push buttons are pressed

 if(leftPressed3){
   if(pos3 < maxDeg) 
      pos3 += movement;
      myservo3.write(pos3);              
      }                     

 if(rightPressed3){
   if(pos3 > minDeg) 
      pos3 -= movement;
      myservo3.write(pos3);               
      }

// The following routine handles what happens if the fourth pair of push buttons are pressed

 if(leftPressed4){
   if(pos4 < maxDeg) 
      pos4 += movement;
      myservo4.write(pos4);              
      }                     

 if(rightPressed4){
   if(pos4 > minDeg) 
      pos4 -= movement;
      myservo4.write(pos4);               
      }


}

 //if(rightPressed3){
 //  ctrl_servo(myservo3, pos3, -1);  

 //void ctrl_servo(servo, poss, dir){
 //  if(poss > minDeg) 
 //     poss += movement*dir;
 //     servo.write(poss);               
 //     }
 //  else;
 //    delay(15); 
 //  }

Hi,
Your code does not compile, why have you got two void setup() and two void loop() functions?

You should only have one of each.
Any setup and code that needs to run once when the code is booted, goes in the void setup() function.
Any code that is your main program and needs to be looped over and over goes in the void loop() function.

Tom.. :slight_smile:

MrAlexMan:
My partner and I .... are very new to the concept.

Which means you need to back up a little. The fact that you have twice posted code with 2x setup() and 2x loop() functions means you've not got your minds round the required structure of an Arduino sketch. I surmise you took two sketches off the web and just pasted one behind the other.

My advice would be to work through the examples in the IDE (File > Examples), which are also available here.

I pointed out in my first reply, that you can't readily stop a sweep with a button once it's started; that's the nature of the "for" as used in sweep. To make that possible you need to use the technique I used, where each time through loop() I looked to see if either servo was due for a move. That same opportunity could be used to see if the pause button has been pressed. That's reasonably sophisticated coding, and I'm reluctant to post a mod to my existing code for you since that is unlikely to help you learn.

Kudos to 5th graders taking on a project like this, and you'll get loads of help here, but I think you started in the wrong place: back up a bit is my advice.

I attempted to create the code but it didn't work.
As soon as it uploaded, the servos glitched out and I couldn't open the Arduino app. >:(
So, in the end, I had to delete the code to open the app. Could you please post a mod/code because (as you can see) I attempted and it didn't work. Also, the deadline is coming up and this is a major part of the project. My partner and I would really appreciate it :slight_smile: