Controling multiple Servos with an arduino Uno

Hello dear People!

I am currently working on a project where I need to control six servos with an arduino uno (well, actually 7 but I might come to that later).
The basic idea here is that each servo has its own designated push button and whenever it is pressed the servo should undergo a sweeping motion.

Now the problem is that I am currently on vaccation and my servos are far away at home so I can't really check if my code works. This is where I ask for your support. Maybe you could have a quick look and see if there are any major mistakes? I actually feel pretty safe about most of the code. The main loop, however, keeps bugging me. I feel like it's just too simple. But maybe that's just how it is?

So if any of you great coders can spare 5 minutes and have a quick look at my code I'd be tremendously graetful.

Thank you in advance

Jocobes

#include <Servo.h> 
 
Servo myServos[6];
int buttonPins[]={8,9,10,11,12,13};

 
int pos1 = 0;
int pos2 = 180;


 
void setup() 
{ 
 for(int i=0; i<6; i++){
  myServos[i].attach(i+2);
  pinMode(buttonPins[i],OUTPUT);
 }
} 
 


void loop() 
{ 
  for(int x=0;x<6;x++){
    if(digitalRead(buttonPins[x]==HIGH))resetTargets(x);
  }
 
}



void resetTargets(int j){
  myServos[j].write(pos2);
  delay(15);
  myServos[j].write(pos1);
}

I can't see anything obviously wrong, but

  1. you may wish to rename the function to be "resetTarget", because it only resets a single target per invocation
  2. You may want to call "resetTarget" when the switch becomes closed, instead of how you have it now, all the time it is closed.
  3. you may want to get rid of the call to "delay" and implement the code as a state machine.

Thank you for the suggestions. I'll change that asap.
How to you propse I only activate the function when the switch is closed as opposed to all the time? I don't really know how to do that.

Have a look at the state change example in the IDE.
It will require you to store the previous state of each switch.

These might work better if they're inputs:-pinMode(buttonPins[i],OUTPUT);

Aight thx for the OUTPUT INPUT correction. Kinda embarrassing though ^^

I did some changes know trying to remove any use of the delay function. Not sure if it works that way but it doesn't feel too bad.

#include <Servo.h> 
 
Servo myServos[6];
int buttonPins[]={8,9,10,11,12,13};

 
int pos1 = 0;
int pos2 = 180;

unsigned long previousMillis = 0;
const long interval = 15;  

int buttonState = 0;
int lastButtonState = 0;

 
void setup() 
{ 
 for(int i=0; i<6; i++){
  myServos[i].attach(i+2);
  pinMode(buttonPins[i],INPUT);
 }
} 
 


void loop() 
{ 
  for(int x=0;x<6;x++){
    buttonState = digitalRead(buttonPins[x]);
  
  if (buttonState != lastButtonState) {
    
    if (buttonState == HIGH) {
      
      
    }
      unsigned long currentMillis = millis();
 
        if(currentMillis - previousMillis >= interval) {
    
         previousMillis = currentMillis;   
  }
  
  lastButtonState = buttonState;
 
    }

}

}



void resetTarget(int j){
  myServos[j].write(pos2);
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    
      previousMillis = currentMillis;   
      myServos[j].write(pos1);
  }
  
}

No, you need a last state for each switch.

True! And yet again I am amazed by the simplicity of my mistakes. Thank you for that.

How about now?

#include <Servo.h> 
 
Servo myServos[6];
int buttonPins[]={8,9,10,11,12,13};

 
int pos1 = 0;
int pos2 = 180;

unsigned long previousMillis = 0;
const long interval = 15;  

int buttonState[] = {0,0,0,0,0,0};
int lastButtonState[] = {0,0,0,0,0,0};

 
void setup() 
{ 
 for(int i=0; i<6; i++){
  myServos[i].attach(i+2);
  pinMode(buttonPins[i],INPUT);
 }
} 
 


void loop() 
{ 
  for(int x=0;x<6;x++){
    buttonState[x] = digitalRead(buttonPins[x]);
  
  if (buttonState[x] != lastButtonState[x]) {
    
    if (buttonState[x] == HIGH) {
      
      
    }
      unsigned long currentMillis = millis();
 
        if(currentMillis - previousMillis >= interval) {
    
         previousMillis = currentMillis;   
  }
  
  lastButtonState[x] = buttonState[x];
 
    }

}

}



void resetTarget(int j){
  myServos[j].write(pos2);
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    
      previousMillis = currentMillis;   
      myServos[j].write(pos1);
  }
  
}

Whilst you need a last state for every switch, you don't need a current state for every switch :wink:

And you certainly don't need sixteen bits of storage to store one bit of information

Oh true. Is that because by the time the for loop is through i don't need the current state of the button anymore?

Where am I using 16 bits for 1?

Jocobes:
Oh true. Is that because by the time the for loop is through i don't need the current state of the button anymore?

Correct.

Where am I using 16 bits for 1?

int lastButtonState[] = {0,0,0,0,0,0};
Right there.

Aye thx!
How do you propose I express the same thing without using up 6 bits?
Something like that maybe: int lastButtonState[]=0;
?

Jocobes:
How do you propose I express the same thing without using up 6 bits?

This is 12 bytes, (96 bits), not 6 bits:-int lastButtonState[] = {0,0,0,0,0,0};
Using 'bool' or 'byte' would cut that in half, to 6 bytes:-bool lastButtonState[] = {0,0,0,0,0,0};
Or if you wanted to get really finicky, a bitfield would only use 1 byte:-

struct
{
    uint8_t b0: 1;
    uint8_t b1: 1;
    uint8_t b2: 1;
    uint8_t b3: 1;
    uint8_t b4: 1;
    uint8_t b5: 1;
}lastButtonState;

Used like this:-lastButtonState.b0=digitalRead(button0);or

if(lastButtonState.b0==LOW)
{
    // Do something.
}

So I finally came around to hooking up all my servos to an arduino did some testing uploaded the code aaaaaaaand it's not working. Surprise!
I spent all day trying to find mistakes, checking connections and getting really frustrated.
The servos just wiggle a bit but don't do what they should. I did check that everything works with the example sweep sketch.
As you can see I inserted an led check in the. beginning and end of the resetTarget function.
Whenever I press a button the led lights up and turns off again but the servo doesn't really do much. After about 3 button presses sometimes the led gets stuck and won't turn off agagain.
I do have all the servos hooked up to an external power supply with efficient juice.

If you guys have any idea what went wrong here I would appreciate that immensely!

Thx in advance!
Jocobes

#include <Servo.h> 
 
Servo myServos[6];
int buttonPins[]={8,9,10,11,12,13};

 
int pos1 = 0;
int pos2 = 180;

unsigned long previousMillis = 0;
const long interval = 15;  

int buttonState = 0;
int lastButtonState[] = {0,0,0,0,0,0};

 
void setup() 
{ 

pinMode(13,OUTPUT);

 for(int i=0; i<6; i++){
  myServos[i].attach(i+2);
  pinMode(buttonPins[i],INPUT);
 }
} 
 


void loop() 
{ 
  for(int x=0;x<6;x++){
    buttonState = digitalRead(buttonPins[x]);
  
  if (buttonState != lastButtonState[x]) {
    
    if (buttonState == HIGH) {
      
      
    }
      unsigned long currentMillis = millis();
 
        if(currentMillis - previousMillis >= interval) {
    
         previousMillis = currentMillis;   
  }
  
  lastButtonState[x] = buttonState;
 
    }

}

}



void resetTarget(int j){
  digitalWrite(13,HIGH);

  myServos[j].write(pos2);
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    
      previousMillis = currentMillis;   
      myServos[j].write(pos1);
      digitalWrite(13,LOW);
  }
  
}
  if (buttonState != lastButtonState[x]) {

You stored a value in an array called buttonState. Here you are using a scalar variable called buttonState. Since that is not possible, I can surmise that the code did not even compile.

Therefore, any talk of it working, or not, is meaningless.

Ya I pasted my old code sorry. I already removed the array from buttonState

So it's now to correct non working code ^^

    if (buttonState == HIGH) {
     
     
    }

If you are not going to do anything, why bother testing?

      unsigned long currentMillis = millis();
 
        if(currentMillis - previousMillis >= interval) {
   
         previousMillis = currentMillis;   
  }

What is the point of this? If it is to debounce switches, you need to record when each switch changed stated, not when the last switch changed state.

With excess blank lines removed, and curly braces properly (IMHO) positioned, your loop() function looks like:

void loop()
{
  for(int x=0;x<6;x++)
  {
    buttonState = digitalRead(buttonPins[x]);

    if (buttonState != lastButtonState[x])
    {
      unsigned long currentMillis = millis();

      if(currentMillis - previousMillis >= interval)
      {
        previousMillis = currentMillis;   
      }

      lastButtonState[x] = buttonState;
    }
  }
}

For the life of me, I can't see that it is accomplishing anything. There is nothing in there that moves any servos or calls any other functions.

I do have all the servos hooked up to an external power supply with efficient juice.

Do the Arduino and the external power supply have a common GND ?

Aight still seems to be old code. It's supposed to call the resetTarget function. And the other part is about having the servo stay in one position for a brief moment before returning to its initial state.
Sorry for that I'll update it as soon as I am home.

And yes they do share a common ground.