Servo for loop issue

The below program sets servo's to predetermined positions: servoMin[] and ServoMax[].
The position change can be done either directly, or gradually in 3ms steps with delay() and a for loop.

When both increase angle and decrease angle are done in gradual steps there is an issue.
On startup, all servo's, one by one, are reverting back to the servoMin[] directly (not gradual), and then changing back to their servoMax[] positions gradually (for loop).

If the gradual angle-increase for loop (the increasing angle) is omitted and replaced by a direct angle-increase then there is no issue and the servo's remain stable in the servoMax[] position.

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <CMRI.h>
#include <Auto485.h>

#define CMRI_ADDR 1 // this also is the JMRI CMRI SMINI node address
// In JMRI this gives an address 1001 to the first servo on the PCA9685 address 0
// Configure a turnout as 1 bit and steady state
// Meaning: bit = 0 = (for example) thrown and bit = 1 = closed
#define DE_PIN 2
#define numServos 4 //The number of servos connected

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); //setup the board address 0
Auto485 bus(DE_PIN); // Arduino pin 2 -> MAX485 DE and RE pins
CMRI cmri(CMRI_ADDR, 24, 48, bus);

int Status[numServos]; //Create a table to hold the status of each turnout, signal, etc.
int Throw[numServos]; //Create a table to hold the throw value for each servo
int Close[numServos]; //Create a table to hold the close value for each servo
int i;
uint16_t pulselgt;
unsigned int servoMin[] = {300, 300, 200, 246, 246, 172, 246, 200, 200, 200}; //servo lower setting to suit individual servo
unsigned int servoMax[] = {450, 450, 500, 492, 492, 565, 492, 550, 550, 525}; //servo upper setting to suit individual servo

void setup() {
  Serial.begin(9600);
  bus.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(50);  // This is the maximum PWM frequency
}

void loop() {
  cmri.process();

  for (i = 0; i < numServos; i++) {
    Status[i] = (cmri.get_bit(i));
    if (Status[i] == 1) {  // decreasing angle
      for (pulselgt = servoMax[i]; pulselgt > servoMin[i]; pulselgt--) {
        pwm.setPWM(i, 0, pulselgt);
        //pwm.setPWM(i, 0, servoMin[i]);
        delay(3);
      }
    }
    if (Status[i] == 0) {  // increasing angle
      for (pulselgt = servoMin[i]; pulselgt < servoMax[i]; pulselgt++) {
        pwm.setPWM(i, 0, pulselgt);
        // pwm.setPWM(i, 0, servoMax[i]);
        delay(3);
      }
    }
    else {
    }
  }
}

With the last for loop changed to below, there is no issue:

if (Status[i] == 0) {  // increasing angle
      // for (pulselgt = servoMin[i]; pulselgt < servoMax[i]; pulselgt++) {
      //  pwm.setPWM(i, 0, pulselgt);
      pwm.setPWM(i, 0, servoMax[i]);
      delay(3);
      // }
    }

What is the reason?

Using the standard Servo library when a servo is connected in setup() it moves to its default position of 90 degrees. You can set the position that it should move to by writing to desired angle to the servo before attaching it

It sounds like the same sort of thing is happening when using the Adafruit library if the servos all initially move to the servoMin position.

It would also explain why there is a difference between a stepped move and a direct move because the servos will not have had time to get to their default start position before they are instantly commanded to move back to servoMax

I am not familiar with the library, but can you write the required start position to the servos before doing the equivalent of an attach() ?

It's doing what you asked in that for loop. Jump to servoMin then move gradually to servoMax. In your second version you just jump directly to servoMax. It's your choice what you prefer.

Steve

Could it be that the first for loop eternally iterates?
Because there seems to be nothing that prevents the first for loop from being executed all over again forever?
I added a secondary variable array previousServoPos[i] which retains the previous value for Status[i], and which is being set to its new value once thjs for loop is done.
I opened a serial monitor and the eternal looping has stopped.

If you feel there might be a better solution please advise me, thansks

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <CMRI.h>
#include <Auto485.h>

#define CMRI_ADDR 1 // this also is the JMRI CMRI SMINI node address
// In JMRI this gives an address 1001 to the first servo on the PCA9685 address 0
// Configure a turnout as 1 bit and steady state
// Meaning: bit = 0 = (for example) thrown and bit = 1 = closed
#define DE_PIN 2
#define numServos 1 //The number of servos connected

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); //setup the board address 0
Auto485 bus(DE_PIN); // Arduino pin 2 -> MAX485 DE and RE pins
CMRI cmri(CMRI_ADDR, 24, 48, bus);

int Status[numServos]; //Create a table to hold the status of each turnout, signal, etc.
int Throw[numServos]; //Create a table to hold the throw value for each servo
int Close[numServos]; //Create a table to hold the close value for each servo
int i;
uint16_t pulselgt;
unsigned int servoMin[] = {300, 300, 200, 246, 246, 172, 246, 200, 200, 200}; //servo lower setting to suit individual servo
unsigned int servoMax[] = {450, 450, 500, 492, 492, 565, 492, 550, 550, 525}; //servo upper setting to suit individual servo
int servoPos[numServos];
int oldServoPos[numServos];
int previousServoPos[numServos];

void setup() {
  Serial.begin(9600);
  bus.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(50);  // This is the maximum PWM frequency
  pulselgt = 307; // about middle pos
  for (i = 0; i < numServos; i++) {
    servoPos[i] = servoMin[i]; // Initial position
    oldServoPos[i] = servoMax[i]; // previous position
    previousServoPos[i] = 0; // update status to 1 = minimum angle
  }
  for (i = 0; i < numServos; i++) { // initiate servos to minimum angle
    pwm.setPWM(i, 0, servoPos[i]);
  }
}

void loop() {
  cmri.process();

  for (i = 0; i < numServos; i++) {
    Status[i] = (cmri.get_bit(i));
    if (Status[i] == 1 && previousServoPos[i] == 0) {  // decreasing angle
      for (pulselgt = servoMax[i]; pulselgt > servoMin[i]; pulselgt--) {
        pwm.setPWM(i, 0, pulselgt);
        delay(3);
        Serial.print("decr pulselgt  = ");
        Serial.println(pulselgt);
      }
      Serial.print("final pulselgt decrease = ");
      Serial.println(pulselgt);
      Serial.println();
      previousServoPos[i] = 1; // update last servoposition to current servoposition
    }
    if (Status[i] == 0 && previousServoPos[i] == 1) {  // increasing angle
      for (pulselgt = servoMin[i]; pulselgt < servoMax[i]; pulselgt++) {
        pwm.setPWM(i, 0, pulselgt);
        delay(3);
        Serial.print("incr pulselgt  = ");
        Serial.println(pulselgt);
        Serial.println();
        Serial.println();
      }
      Serial.print("final pulselgt increase = ");
      Serial.println(pulselgt);
      previousServoPos[i] = 0; // update last servoposition to current servoposition
    }
  }
}

Can you please explain what the code is supposed to do ?

Status[i] is read and determines the position of the servo.
If Status[i] = 1 then servo[i] must go to low angle, if not already set low. If Status[i] = 0 then servo[i] must go to high angle, if not already set high.

Preferably at slow servo position change rate.