Sweeping 16 Servos Alternately

Hi,
Using an Arduino Uno and a PCA9685 16 channel driver I'm trying to sweep all the servos from 0 to 15 at the same time but in an alternate manner. i.e. odd number servos sweep from left to right and even numbered ones sweep in the opposite direction. The following code sweeps all the servos together but in the same direction :

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <math.h>
#include "SoftwareSerial.h"
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define Lft  150 // left
#define Rt  250   // right
#define Ct  200  // center

int pulselen;
int myservo;

void setup() {

  Serial.begin(9600);
  pwm.begin();

  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(50);  
  delay(10);
}
void loop() {
for (uint16_t pulselen = Lft; pulselen < Rt; pulselen += 1) {
      for (myservo = 0; myservo < 15; myservo++) {
      pwm.setPWM(myservo, 0, pulselen);
      }
      }

      for (uint16_t pulselen = Rt; pulselen > Lft; pulselen -=1 ) {

      for (myservo = 0; myservo < 15; myservo++){
      pwm.setPWM(myservo, 0, pulselen);   
      }
      }
}

How could I throw in an IF myservo is odd go from left to right and vice versa and have all the servos sweep at the same time ?
Thanks.

value & 1

if true (non-zero), means value is odd.

  uint16_t pulse;
  
  for (uint16_t pulselen = Lft; pulselen < Rt; pulselen += 1) {
    for (myservo = 0; myservo < 15; myservo++) {
      if ( myservo % 1 ) {
        pulse = pulselen;
      }
      else {
        pulse = Rt - pulselen;
      }
      pwm.setPWM(myservo, 0, pulse);
    }
  }

You can also remove the outer for() loop and just let loop() do what it does. Each time through loop() you calculate the pulsewidth, set it, and increment, When you reach the limit, switch direction. repeat for all eternity.

1 Like

Did you mean "% 2"?

Or " & 1" ?

means bitwise AND
decimal 1 binary 00000001
decimal 2 binary 00000010
decimal 3 binary 00000011
decimal 4 binary 00000100
decimal 5 binary 00000101

best regards Stefan

1 Like

Thanks all.

@blh64 Your code moves only the odd ones, sweeping in one direction but then jumps (not sweep) in the other direction.

I read it's better to do the IF test in binary so I changed to

 if ( (myservo & 0x01) == 0){

now I get all the even ones. But again they sweep only in one direction and jump to (no sweep) as they go back.

My rookie brain can't figure out how to have all the servos sweep together in both directions without jumping.

The processor doesn't care about the base you express the constant in.

Because any value modulo 1 is always zero, aka false.
Which is why you should try modulo 2

Post the code you have now, and tell us what it does.

1 Like

And you'll probably do better if you change
pulse = Rt - pulselen;
to
pulse = (Ct * 2) - pulselen;

That should keep pulse within the correct Lft to Rt range.

Steve

1 Like

@slipstick Thanks Steve, nice suggestion.
Thanks all, now I got it, it works fine.

void Sweep_Alternate(){
uint16_t pulse;
  for (uint16_t pulselen = Lft; pulselen < Rt; pulselen += 1) {
    for (myservo = 0; myservo < 15; myservo++) {
    if ( (myservo & 0x01) == 0){
        pulse = pulselen;
      }
      else {
        pulse = (Ct * 2) - pulselen;
      }
      pwm.setPWM(myservo, 0, pulse);
      
    }
  }

for (uint16_t pulselen = Rt; pulselen > Lft; pulselen -= 1) {
    for (myservo = 0; myservo < 15; myservo++) {
    if ( (myservo & 0x01) == 0){
        pulse = pulselen;
      }
      else {
        pulse = (Ct * 2) - pulselen;
      }
      pwm.setPWM(myservo, 0, pulse);
      
    }
  }
  
}

Either would be better than my mistake :slight_smile: