Make a servo move once by reed relay

Hi all,

I would like a servo to push a button (so not the other way round, push a button and make a servo move). The trigger will be a reed relay. After pushing the button, the servo needs to move back to neutral position. My code partially works.

// Include the servo library
#include <Servo.h>
// Declare the servo pin
int servoPin = 5;
// Create a servo object
Servo Servo1;
byte reedPin = 12;
const int pinLed = 9; //Pin LED


void setup() 

{
pinMode(pinLed, OUTPUT); 
pinMode(reedPin, INPUT);


   // We need to attach the servo to the used pin number
   Servo1.attach(servoPin);
   pinMode(reedPin,INPUT_PULLUP);

   Servo1.write(90);   
   delay(1000);
}


void loop()
{
if (digitalRead(reedPin) == HIGH)
{
 digitalWrite(pinLed, LOW);

Servo1.write(180);
delay(1000);
Servo1.write(90);

} 


{
if (digitalRead(reedPin) == LOW)

 digitalWrite(pinLed, HIGH);
 Servo1.write(90);



} 
}

So the servo starts in neutral position, LED on.
(I’m using the LED as an indicator for the status of the relay)
Move the magnet to the reed relay, LED goes off, servo moves to position, but does not move back to neutral.
Remove magnet, LED goes off, servo moves to neutral position.

So why is the servo not moving back to neutral?
Also, if it would, I think it would move back and forth indefinitely, as the code loops.
So how could I move it just once?

I based my code onthe code in this post:
https://forum.arduino.cc/index.php?topic=378956.0Reed switch controlling a servo

I tried the doServoStuff function and the while(1); , but it makes no difference.

Does anybody have an idea how to make the servo move back and forth and do that only once, as long as the reedPin is high?

The classis confution between a button which IS pressed vs a button that BECOMES pressed. The micro is very fast, if the read-relay is still high after the 1000ms the if will just fire again thus setting the angle to 180 degree again. Have a look at the “State change”-example.

Some free tips:

  • Press Ctrl+T in the IDE to clean up the formatting.

  • Next, clean it up a bit more :wink:

  • Not everything is an int

  • Are you planning to use more servo’s? If so, use an array. If not, drop the ‘1’

  • Are you planning to do more with the Arduino (for example, multiple servo’s)? If so, stop using delay. Have a look at the “Blink without delay”-example.

  • A blank line can help

  • to many blank lines is annoying

  • In your text you defined servo positions. You can do the same in code with a good variable name. Makes the code even easier to read.

Example after changes (but not fixing the problem):

// Include the servo library
#include <Servo.h>

// Declare the pins
const byte servoPin = 5;
const byte reedPin = 12;
const byte ledPin = 9; //Pin LED

//Servo states
const byte servoNeutralPosition = 90;
const byte servoTriggerPosition = 180;

//servo activation time
const servoActivationTime = 1000; //[ms]

// Create a servo object
Servo Servo;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(reedPin, INPUT_PULLUP);

  // We need to attach the servo to the used pin number
  Servo.attach(servoPin);

  Servo1.write(90);
  delay(1000);
}


void loop()
{
  if (digitalRead(reedPin) == HIGH)
  {
    digitalWrite(ledPin, LOW);

    Servo1.write(180);
    delay(1000);
    Servo1.write(90);
  }
  
  if (digitalRead(reedPin) == LOW)
    digitalWrite(ledPin, HIGH);
  Servo1.write(90);
}

If you're using input_pullup, you should wire your switch so that it pulls the input low when pressed. And you'll need to change the logic in the code accordingly.

Thanks for the helpful pointers.
I did not know about the CTRL+T, I see it is under Tools, where I was looking for it under edit.

I tried to combine my code with the example here:
StateChangeDetection

I came up with this:

// Include the servo library
#include <Servo.h>
// Declare the servo pin
const byte servoPin = 5;
// Declare the Reed switch
const byte reedPin = 12;
// Declare the LED pin
const byte pinLed = 9;
// Create a servo object
Servo Servo;

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

//Servo states
const byte servoNeutralPosition = 90;
const byte servoTriggerPosition = 180;

//servo activation time
const byte servoActivationTime = 1000; //[ms]

void setup()

{
  pinMode(pinLed, OUTPUT);
  pinMode(reedPin, INPUT);

  // We need to attach the servo to the used pin number
  Servo.attach(servoPin);
  pinMode(reedPin, INPUT);
  digitalWrite(pinLed, HIGH);
  Servo.write(servoNeutralPosition);
  delay(1000);
}

void loop() {

  buttonState = digitalRead(reedPin);
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
    } else {
      // if the current state is LOW then the button went from on to off:

    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  {
    if (buttonPushCounter % 1 == 0)
    {
      digitalWrite(pinLed, LOW);
      Servo.write(servoTriggerPosition);
      delay(1000);
      Servo.write(servoNeutralPosition);
    } else {

      digitalWrite(pinLed, HIGH);
      Servo.write(servoNeutralPosition);
    }
  }
}

I did not use the modulo 4 as in the example, just one state change is enough.
Now if I start the program, the LED goes on, the servo moves back and forth and the LED goes off.
If I put the magnet on the switch, it moves just a little bit, LED stays off. Remove the magnet and it twitches a bit again.

EDIT:

By the way, what is the servoActivationTime supposed to be used for?
As an alternative to delay?