Using Multiple Servos Issue

I found code that works for what I need, but it is only for one servo motor. I would like to be able to get it to work for three or more servos, but I have little to no experiance in coding. I tried for hours looking at different code to figure out how to tweek it to get it to work but I get a bunch of errors. What I am trying to do is have 3 servos or so each with its own button. When the botton A is pressed, servo A turns 90 degrees. When button A is press again, the servo truns back to its initial state. This part works with the follow code, but I cant for the life of me figure out how to get servo B/button B etc. to work.

Any Help would be very appreciated!!

Here is the code I found that works for one servo and the circuit diagram I am using (I will add a powersupply when I build it):



#include <Servo.h>

// constants won't change
const int BUTTON_PIN = 7; // Arduino pin connected to button's pin
const int SERVO_PIN  = 9; // Arduino pin connected to servo motor's pin

Servo servo; // create servo object to control a servo

// variables will change:
int angle = 0;          // the current angle of servo motor
int lastButtonState;    // the previous state of button
int currentButtonState; // the current state of button

void setup() {
  Serial.begin(9600);                // initialize serial
  pinMode(BUTTON_PIN, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo.attach(SERVO_PIN);           // attaches the servo on pin 9 to the servo object

  servo.write(angle);
  currentButtonState = digitalRead(BUTTON_PIN);
}

void loop() {
  lastButtonState    = currentButtonState;      // save the last state
  currentButtonState = digitalRead(BUTTON_PIN); // read new state

  if(lastButtonState == HIGH && currentButtonState == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angle == 0)
      angle = 90;
    else
    if(angle == 90)
      angle = 0;

    // control servo motor arccoding to the angle
    servo.write(angle);
  }
}

Have look at Multi-tasking in Arduino and make each servo its own task.
multitaskingDiagramSmall

Im not sure if I did that correctly, when I put the code in TinkerCad simulator it uploads alright but when I click each button the motor moves a few degrees and returns (not the full 90 degrees) here is how I wrote it:

#include <Servo.h>

// constants won't change
const int BUTTON_PIN_A = 7; 
const int BUTTON_PIN_B = 8;
const int BUTTON_PIN_C = 12;
const int SERVO_PIN_A = 9;
const int SERVO_PIN_B = 10; 
const int SERVO_PIN_C = 11;

Servo servo_A; // create servo object to control a servo
Servo servo_B;
Servo servo_C;

// variables will change:
int angle = 0;          // the current angle of servo motor
int lastButtonState;    // the previous state of button
int currentButtonState; // the current state of button

void setup() {
  Serial.begin(9600);                // initialize serial
  pinMode(BUTTON_PIN_A, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo_A.attach(SERVO_PIN_A);           // attaches the servo on pin 9 to the servo object

  servo_A.write(angle);
  currentButtonState = digitalRead(BUTTON_PIN_A);

  pinMode(BUTTON_PIN_B, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo_B.attach(SERVO_PIN_B);           // attaches the servo on pin 9 to the servo object

  servo_B.write(angle);
  currentButtonState = digitalRead(BUTTON_PIN_B);

  pinMode(BUTTON_PIN_C, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo_C.attach(SERVO_PIN_C);           // attaches the servo on pin 9 to the servo object

  servo_C.write(angle);
  currentButtonState = digitalRead(BUTTON_PIN_C);

}

void loop() {

  void Task_A();

  lastButtonState    = currentButtonState;      // save the last state
  currentButtonState = digitalRead(BUTTON_PIN_A); // read new state


  if(lastButtonState == HIGH && currentButtonState == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angle == 0)
      angle = 90;
    else
    if(angle == 90)
      angle = 0;

    // control servo motor arccoding to the angle
    servo_A.write(angle);


  }

    void Task_B();

  lastButtonState    = currentButtonState;      // save the last state
  currentButtonState = digitalRead(BUTTON_PIN_B); // read new state


  if(lastButtonState == HIGH && currentButtonState == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angle == 0)
      angle = 90;
    else
    if(angle == 90)
      angle = 0;

    // control servo motor arccoding to the angle
    servo_B.write(angle);
}

    void Task_C();

  lastButtonState    = currentButtonState;      // save the last state
  currentButtonState = digitalRead(BUTTON_PIN_C); // read new state


  if(lastButtonState == HIGH && currentButtonState == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angle == 0)
      angle = 90;
    else
    if(angle == 90)
      angle = 0;

    // control servo motor arccoding to the angle
    servo_C.write(angle);

  }
}

Here is the "Final" Code that works - Im sure someone could clean it up, I am a newbie.

#include <Servo.h>

// constants won't change
const int BUTTON_PIN_A = 7; 
const int BUTTON_PIN_B = 8;
const int BUTTON_PIN_C = 12;
const int SERVO_PIN_A = 9;
const int SERVO_PIN_B = 10; 
const int SERVO_PIN_C = 11;

Servo servo_A; // create servo object to control a servo
Servo servo_B;
Servo servo_C;

// variables will change:
int angleA = 0;          // the current angle of servo motor
int angleB = 0;
int angleC = 0;
int lastButtonStateA;    // the previous state of button
int lastButtonStateB;
int lastButtonStateC;
int currentButtonStateA; // the current state of button
int currentButtonStateB;
int currentButtonStateC;


void setup() {
  Serial.begin(9600);                // initialize serial
  pinMode(BUTTON_PIN_A, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo_A.attach(SERVO_PIN_A);           // attaches the servo on pin 9 to the servo object

  servo_A.write(angleA);
  currentButtonStateA = digitalRead(BUTTON_PIN_A);

  pinMode(BUTTON_PIN_B, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo_B.attach(SERVO_PIN_B);           // attaches the servo on pin 9 to the servo object

  servo_B.write(angleB);
  currentButtonStateB = digitalRead(BUTTON_PIN_B);

  pinMode(BUTTON_PIN_C, INPUT_PULLUP); // set arduino pin to input pull-up mode
  servo_C.attach(SERVO_PIN_C);           // attaches the servo on pin 9 to the servo object

  servo_C.write(angleC);
  currentButtonStateC = digitalRead(BUTTON_PIN_C);

}

void loop() {

  void Task_A();

  lastButtonStateA    = currentButtonStateA;      // save the last state
  currentButtonStateA = digitalRead(BUTTON_PIN_A); // read new state


  if(lastButtonStateA == HIGH && currentButtonStateA == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angleA == 0)
      angleA = 90;
    else
    if(angleA == 90)
      angleA = 0;

    // control servo motor arccoding to the angle
    servo_A.write(angleA);


  }

    void Task_B();

  lastButtonStateB    = currentButtonStateB;      // save the last state
  currentButtonStateB = digitalRead(BUTTON_PIN_B); // read new state


  if(lastButtonStateB == HIGH && currentButtonStateB == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angleB == 0)
      angleB = 90;
    else
    if(angleB == 90)
      angleB = 0;

    // control servo motor arccoding to the angle
    servo_B.write(angleB);
}

    void Task_C();

  lastButtonStateC    = currentButtonStateC;      // save the last state
  currentButtonStateC = digitalRead(BUTTON_PIN_C); // read new state


  if(lastButtonStateC == HIGH && currentButtonStateC == LOW) {
    Serial.println("The button is pressed");

    // change angle of servo motor
    if(angleC == 0)
      angleC = 90;
    else
    if(angleC == 90)
      angleC = 0;

    // control servo motor arccoding to the angle
    servo_C.write(angleC);

  }
}

@griffjams Could you edit all your posts and put the sketch between lines with three backslash-single-quotes ?

```
Your sketch
```

You can also use the </> button for that.

There is an other way. By updating all the servo motors every 10ms or 20ms, you can program the speed and use them all together.
Start by reading the Blink Without Delay page.
Then try this Wokwi simulation:

In middle-upper of the screen is the start button. No need to log in, just click the start button.

In my opinion, Tinkercad is very good and useful, but now I'm totally a fan of Wokwi. I made a comparison of the two.

done.. thanks for the pointer. I was wondering why it looked strange when I posted it.

One good way to expand from single to multiple is with arrays and loops:

#include <Servo.h>
const byte ButtonCount = 3;

// constants won't change
const int BUTTON_PINS[ButtonCount] = {7, 8, 12}; // Arduino pin connected to button's pin
const int SERVO_PINS[ButtonCount]  = {9, 10, 11}; // Arduino pin connected to servo motor's pin

Servo servos[ButtonCount]; // create servo object to control a servo

// variables will change:
int angles[ButtonCount] = {0, 0, 0};          // the current angle of servo motor
int lastButtonStates[ButtonCount] = {HIGH, HIGH, HIGH};    // the previous state of button

void setup()
{
  Serial.begin(9600);                // initialize serial

  for (int i = 0; i < ButtonCount; i++)
  {
    pinMode(BUTTON_PINS[i], INPUT_PULLUP); // set arduino pin to input pull-up mode
    servos[i].attach(SERVO_PINS[i]);           // attaches the servo on pin 9 to the servo object
    servos[i].write(angles[i]);
  }
}

void loop()
{
  for (int i = 0; i < ButtonCount; i++)
  {
    int currentButtonState = digitalRead(BUTTON_PINS[i]); // read new state

    if (lastButtonStates[i] == HIGH && currentButtonState == LOW)
    {
      Serial.println("The button is pressed");

      // change angle of servo motor
      if (angles[i] == 0)
        angles[i] = 90;
      else if (angles[i] == 90)
        angles[i] = 0;

      // control servo motor arccoding to the angle
      servos[i].write(angles[i]);
    }
    lastButtonStates[i] = currentButtonState;
  } // end of for (ButtonCount)
}

Thanks John! I got a chance to try your code and it works too and is much shorter. If I were to add additional servos would I just add to the button count and add the appropriate pins? Or do I also need to add more ++ wherever that is in the code?

The project I am working on is a box that raises and lowers sharpies onto clear 3d printer filament to change the colors. Once I get A prototype working with manual controls I want to add a function to raise and lower the servos in certain intervals as well as a random function(with long times because the filament moves slow and you need 30 or so centimeters to get a band of color on a small print.

Is it possible to add these (I have found sketches that will probably work) to either iterations of code above using adding a extra buttons for the proposed functions? Or would the code need to be rewritten in a different style?

Thanks again for any input!

One example of the code for intervals I found was this….looks like you wrote it lol


//QUADSweep
//edited from the original code by BARRAGAN

#include "Servo.h"

Servo myservo;  // create servo object to control a servo, a maximum of eight servo objects can be created
Servo mysecondservo;              // servo 2
Servo mythirdservo;              // servo3
Servo myfourthservo;              // servo4

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

void setup()
{
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object
 mysecondservo.attach(10); // attaches the servo on pin 10 to the servo object
 mythirdservo.attach(8); // attaches the servo on pin 8 to the servo object
 myfourthservo.attach(11); // attaches the servo on pin 11 to the servo object
}


void loop()
{
unsigned long start = millis();
int sweepsNotFinished;

do
    {
    unsigned long now = millis() - start;
    sweepsNotFinished = 0;
    sweepsNotFinished += sweep(now, 500, 1500, 90, 0, myservo); // 1/2 second delay then 1 second sweep from 90 to 0
    sweepsNotFinished += sweep(now, 0, 2000, 180, 75, mysecondservo); // no delay and 2 second sweep from 180 to 75
    sweepsNotFinished += sweep(now, 250, 10000, 30, 100, mythirdservo);  // 1/4 second delay, then 9.75 second sweep from 30 to 100
   } while (sweepsNotFinished > 0);
}

int  sweep(unsigned long currentTime, unsigned long startTime, unsigned long endTime, int startPosition, int endPosition, Servo &servo)
{
if (currentTime < startTime)
    return 1;
if (currentTime > endTime)
    return 0;
servo.write( startPosition + (endPosition-startPosition) * (currentTime-startTime) / (endTime-startTime));
  return 1;
}

Yes. Change the value of ButtonCount and list that number of BUTTON_PINS and SERVO_PINS. Everything else just works. That's one of the joys of using arrays when you want more than one of something. :slight_smile:

Using servos to color filament for a 3D print is a great idea. With some tuning and Cyan/Magenta/Yellow/Black Sharpies you could do many-color prints. With the servos you could even press the Sharpie with varying intensity to get more shades.

The trick with coloring filament is that there is a fair distance between the top of the extruder where you can apply the color and the nozzle. Fortunately the extruder motion in the gcode is typically absolute: you know what fraction of a millimeter of filament is going to be used for each X/Y motion. You could pre-process the gcode to move the color change instructions to, say '523 mm' before the corresponding X/Y motion. Add code to the printer firmware (Marlin?) to control the servos based on the color selection.

That would be very neat, if I get the hardware/design working optimally I might try that, got to get used to coding first, I would hate to brick my printer lol