Model railroad crossing

Can someone please help me, Every time before the booms move they jerk and then go down smoothly the same before the come up. I am using an Arduino UNO. The servos are connected to a speperate 5v supply and the arduino is connected to a seperate 7v supply.

#include<Servo.h>;
int maxPos1 = 45;
int maxPos2 = 45;
int minPos1 = 3;
int minPos2 = 9;
int pos1 = 45;
int pos2 = 45;

byte upPin = 2;
Servo servo1;
Servo servo2;

void setup() {
  pinMode(2, INPUT);
  servo1.attach(11);
  servo2.attach(9);

}
void loop() {
  while (digitalRead(upPin) == LOW) {
    pos1++;
    if (pos1 >= maxPos1) {
      pos1 = maxPos1;
    }
    pos2++;
    if (pos2 >= maxPos2) {
      pos2 = maxPos2;
    }
    servo1.write(pos1);
    servo2.write(pos2);
    delay(40);
  }
  while (digitalRead(upPin) == HIGH) {
    pos1--;
    if (pos1 <= minPos1) {
      pos1 = minPos1;
    }
    pos2--;
    if (pos2 <= minPos2) {
      pos2 = minPos2;
    }
    servo1.write(pos1);
    servo2.write(pos2);
    delay(40);
  }
}

I can't immediately see anything wrong with your code.

Maybe try putting the lines

    servo1.write(pos1);
    servo2.write(pos2);

before you change the values of pos1 and pos2

Also, try a much longer delay (like 400ms) so you can see the individual moves.

If none of that helps please post a link to a short YouTube video that illustrates the problem.

...R

to avoid jitter, you may need to constant write to each servo.

void loop() {
    while (digitalRead(upPin) == LOW) {
        pos1++;
        if (pos1 >= maxPos1) {
            pos1 = maxPos1;
        }

        pos2++;
        if (pos2 >= maxPos2) {
            pos2 = maxPos2;
        }
    }

    while (digitalRead(upPin) == HIGH) {
        pos1--;
        if (pos1 <= minPos1) {
            pos1 = minPos1;
        }

        pos2--;
        if (pos2 <= minPos2) {
            pos2 = minPos2;
        }
    }

    servo1.write(pos1);
    servo2.write(pos2);
    delay(40);
}

may be (if you have cheap servos) those values are too low

int minPos1 = 3;
int minPos2 = 9;

and your servos have a tough time moving there. Have you tested this works smoothly to get to that position ?

How do I attach a video. Thanks.

Greatnorthern and gresleyman should collaborate, seeing as Sir Nigel of that ilk was their main engineer.

Greatnorthern:
How do I attach a video. Thanks.

post on youTube and put a link here

Greatnorthern:
How do I attach a video. Thanks.

Post the video on Youtube and then get the link for its address and post the link here

...R

What type of switch are you using on the input? 40ms should be enough delay to debounce most switches, but if not that could be your problem.

Greatnorthern:
Can someone please help me, Every time before the booms move they jerk and then go down smoothly the same before the come up. I am using an Arduino UNO. The servos are connected to a speperate 5v supply and the arduino is connected to a seperate 7v supply.

Maybe this will help.

http://www.bajdi.com/arduino-servo-sweep/

and then this as referred to.......

What is connected to pin 2? Is there a connection between the two power supply grounds and Arduino GND?

Thanks for all your suggestions. The input to the Arduino is from a PLC relay output. I disconnected the PLC and shorted out the input, problem solved. There is no bounce at the start of the cycle. How can I modify the code so that I do not get this bounce at the start of the boom cycle using the relay output from the PLC.

Greatnorthern:
How can I modify the code so that I do not get this bounce at the start of the boom cycle using the relay output from the PLC.

When you detect a low on the input, move the servos until they both reach their maximum values. Afterwards, when you detect a high on the input, move the servos until they both reach their minimum values. Have the while () loops check the values of pos1 and pos2, not the state of the input, the input is only used to select when to run the while() loop. Note that this is not a good way to do it if you ever want to have the arduino do any additional tasks, because it will block execution of the remaining code until the full servo movement is completed (your original code also has this problem).

so the poor's man way to remove bouncing is to just use a delay() [after you detect the condition] that is long enough for the bounces to go away. in your code above you had 40ms delay (due to your move of the servo) and with most buttons that's plenty but seems not the case for you. You could try to increase this a bit to 60 or 100 and see how it goes.

Another option is to start the movement only when the jitter is gone. you listen to change in the current HIGH or LOW value and when it's stable for a while (using millis()) you trigger your action. You could also still trigger on change but ignore opposite values if they come "soon" after that first trigger. To implement this a small state machine can help.

You could have a look at the OneButton Library, Matthias Hertel implemented a small finite state machine in there to handle bouncing.

(doc is here)

Another option is the hardware way, add a capacitor next to the "button". This will filter out high frequency bouncing and give you a clean signal.


(R is your pull-up resistor that you can also get using INPUT_PULLUP on the Arduino Pin)

david_2018:
Have the while () loops check the values of pos1 and pos2, not the state of the input, the input is only used to select when to run the while() loop.

There may be something in that idea.

In the OP’s code in the Original Post the servos move as long as the switch is (say) HIGH. But the more usual way to deal with switches is to check when they change from LOW to HIGH and use that change to start something. The code might be something like this

previousSwitchState = switchState;
switchState = digitalRead(switchPin);
if (switchState == HIGH and previousSwitchState == LOW) {
  servoMove = 'U';
}
if (switchState == LOW and previousSwitchState == HIGH) {
  servoMove = 'D';
}

if (servoMove == 'U') {
  pos1 ++;
  pos2 ++;
}
else {
  pos1 --;
  pos2 --;
}
if (pos1 > maxPos1) {
   pos1 = maxPos1;
   // etc etc
}
servo1.write(pos1);
servo2.write(pos2);
delay(40);

I don’t think there is any need for a WHILE as setting the max and min values will prevent the servo going too far.

…R

Robin2:
There may be something in that idea.

if (switchState == HIGH and previousSwitchState == LOW) {

servoMove = 'U';
}
if (switchState == LOW and previousSwitchState == HIGH) {
  servoMove = 'D';
}

you still do not debounce though... (if the delay 40 is not enough) so your state machine will jitter

Matthias Hertel implemented a small finite state machine

... and that's a really good example of a state diagram.

blomcrestlight:
... and that's a really good example of a state diagram.

Almost - missing the jitter debounce for the double click :slight_smile:

I don’t have time at the moment to code the no-delay version, but this should work ok:

void loop() {
  if (digitalRead(upPin) == LOW) {
    while ((pos1 < maxPos1) || (pos2 < maxPos2)) {
      pos1++;
      if (pos1 >= maxPos1) {
        pos1 = maxPos1;
      }
      pos2++;
      if (pos2 >= maxPos2) {
        pos2 = maxPos2;
      }
      servo1.write(pos1);
      servo2.write(pos2);
      delay(40);
    }
  } else { //input == HIGH
    while ((pos1 > minPos1) || (pos2 > minPos2)) {
      pos1--;
      if (pos1 <= minPos1) {
        pos1 = minPos1;
      }
      pos2--;
      if (pos2 <= minPos2) {
        pos2 = minPos2;
      }
      servo1.write(pos1);
      servo2.write(pos2);
      delay(40);
    }
  }
}

J-M-L:
you still do not debounce though… (if the delay 40 is not enough) so your state machine will jitter

Then make the delay() a bit longer

…R