2560 Behaving strangely. What am I doing wrong?

I have 6 linear actuators connected to 3 CanaKit H bridges attached to a 2560. Each dual h bridge has two sets of IN1, IN2, and EN. I raise the either one of the IN* pins to set motor direction and then send a PWM on EN to control motor speed. The IN* pins are connected to arduino pins 40-52. The PWM pins are connected to 8-13. The H Bridges have a 12v3a power supply that also drives their logic. The arduino is getting 5v from the USB.

The following code works and the motors go either way:

  for(i=0;i<6;++i) {
    // ReadActuatorPos() reads the potentiometer on the actuator.  Analog pins 0...6
    while(ReadActuatorPos(PWM1+i)>0.5) SetActuatorSpeed(PWM1+i,-1);  // retract
    while(ReadActuatorPos(PWM1+i)<0.5) SetActuatorSpeed(PWM1+i,1);  // extend
    SetActuatorSpeed(PWM1+i,0);
  }

However: in the following code the motors will only extend if they're too close. They refuse to retract when they're too far.

  do {
    j=0;
    for(i=0;i<6;++i) {
      f=ReadActuatorPos(PWM1+i);
      if(f>0.51) SetActuatorSpeed(PWM1+i,-1);  // this is being called, so why isn't it working?
      else if(f<0.49) SetActuatorSpeed(PWM1+i,1);
      else {
        SetActuatorSpeed(PWM1+i,0);
        ++j;
      }
    }
  } while(j<6);

Since the motors are all able to extend at the same time I don't think it's some kind of voltage drop. The H bridges have LEDs indicating which way the motors are moving. When the system is working the appropriate lights are on. When I run the non-working code the wrong lights are lit - it looks as if both INs are raised, leading me to think the arduino is somehow sending the wrong signals.

Maybe it's something else I don't see, so here's SetActuatorSpeed.

void SetActuatorSpeed(int pwm,float newspeed) {
  int pin1, pin2, mode1, mode2;  

  // these are according to the CanaKit instruction manual that came with the boards.
  if( newspeed > 0 ) {
    mode1=HIGH;
    mode2=LOW;
  } else if( newspeed < 0 ) {
    mode1=LOW;
    mode2=HIGH;
    newspeed=-newspeed;  // because we can't supply a negative value to analogWrite()
  } else {
    // mode1=HIGH, mode2=HIGH is the same as mode1=LOW, mode2=LOW
    mode1=HIGH;
    mode2=HIGH;
  }

  // PWM1 is pin 8.  The rest are sequential.
  // IN1 is pin 40.  The rest are sequential.
  switch(pwm) {
  case PWM1:    pin1=IN1;    pin2=IN2;    break;
  case PWM2:    pin1=IN3;    pin2=IN4;    break;
  case PWM3:    pin1=IN5;    pin2=IN6;    break;
  case PWM4:    pin1=IN7;    pin2=IN8;    break;
  case PWM5:    pin1=IN9;    pin2=IN10;   break;
  case PWM6:    pin1=IN11;   pin2=IN12;   break;
  default: return;
  }

  // set direction 
  digitalWrite(pin1,mode1);
  digitalWrite(pin2,mode2);
  // set speed
  analogWrite(pwm,newspeed*SERVO_SCALE);  // SERVO_SCALE is 255.newspeed is always 0.0 .... 1.0
}

I've been fighting this thing for two days with a lot of Serial.print() to diagnose and so far I've found nothing.
What am I doing wrong?

Here is a test case.

http://pastebin.com/HSp6b0xR

note that in loop() there are two pieces of code with //* piece_a // piece_b /// around them. each is one of the cases. piece_a does not work. piece_b does work.

The only thing I can spot is that in the non-working code, the loop is assymetric regarding j.

Also I sense a potential problem if, after one iteration you have left the actuators for one set of pins on, and you move to another set (that is, ++i) but the original ones are still on. So for example you might have IN1=HIGH and IN2=LOW, and then move on and set IN3/IN4 while still leaving IN1 on.

"the loop is assymetric regarding j."

Your english is assymetric with my understanding.

IN1 and IN2 don't affect IN3 and IN4. Each pair is for a separate motor.

I've found that the non-working loop functions slowly if I only try to modify 5 motors at once, and functions fine if I modify 4 at once. Which is really wierd, since it doesn't have trouble extending all 6 actuators at once. Given that the actuators are pointing straight up, it actually takes MORE work to push them up then bring them down. That means the current draw is LOWER when retracting the actuators.

aggrav8d:
Your english is assymetric with my understanding.

You only add 1 to j if f is around 0.5. Is that intentional?

Right. Well I think it is electrical. The working loop looks like this if I hard-code in 0.6 as the input:

R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN1  pin2=IN2  1=0/1

In other words, it is only activating one motor.

The non-working loop looks like this:

R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN3  pin2=IN4  2=0/1	
R pin1=IN5  pin2=IN6  3=0/1	
R pin1=IN7  pin2=IN8  4=0/1	
R pin1=IN9  pin2=IN10 5=0/1	
R pin1=IN11 pin2=IN12 6=0/1	
R pin1=IN1  pin2=IN2  1=0/1	
R pin1=IN3  pin2=IN4  2=0/1	
R pin1=IN5  pin2=IN6  3=0/1	
R pin1=IN7  pin2=IN8  4=0/1	
R pin1=IN9  pin2=IN10 5=0/1	
R pin1=IN11 pin2=IN12 6=0/1

So the output looks OK, but you have 6 motors running at once.

That means the current draw is LOWER when retracting the actuators.

I would be measuring currents and voltages and seeing if they are within spec.

Yes, it's intentional. When each motor gets near 0.5, j increases by one. When all 6 are within range, the loop exits. Since the loop makes each motor go back and forth (eg stay in range) the loop must eventually exit. a 0.1 margin of error was added because it was found that 0.5 exact match almost never happens.

Disconnect the motor to rule out electrical problems. Then put LEDs on the outputs (or a logic analyzer or something) and test to see if some illogical sequence of LEDs is lit up.

There are built in LEDs on the h bridges. It looks fine when the actuators are extending - the greens are all lit, the reds are off.
When I run it the other direction, they're all on but they're dim. Not as dim as when I'm flashing new code to the Arduino.

I won't have a chance to run it through a logic analyzer until tomorrow morning.

Turns out using the motor power supply to also supply the h driver (via the onboard j1 pin) was a bad idea.
Now that I'm supplying it from the arduino everything is working great.
Hooray!

Thanks for the help.