Servo isn't following my code, keeps jittering

this is my code

#include <Servo.h>



int servopin=9;
int servopos=90;
int sensPin = 8;
int servoRes = 0;
Servo myServo;





void setup() {
  // put your setup code here, to run once:
  pinMode(sensPin, INPUT);
Serial.begin(9600);
myServo.attach(servopin);

}

void loop() {
  myServo.write(servoRes);
  
  int val = digitalRead(sensPin);
  

  if(val==HIGH){
    myServo.write(servopos);
    delay(21500);
    
    
  }
  

}

3 questions:

  1. How are you powering the servo?
  2. What kind of input is sensPin? (button, sensor, etc)
  3. Why do you have a 21.5 second delay?

What sort of servo? How is the Arduino powered? DO you have a pull-down resistor on on the input?

Only very small servos have any chance of working when powered from the Arduino 5V pin and even then it's a bad idea. Try powering the servo from a separate supply like 4 x AA batteries.

Steve

Sorry the 21.5 second delay was just to test some things
The servo is powered by the 5V power supply on the arduino, it works with other programs perfectly, just not with this one.
sensPin is a button

It is generally a bad idea to power a servo from the Arduino. Try using another power source for the servo and make sure to connect the grounds. Does your button have a pull down resistor?

In your loop function you are setting the servo position to 0. If sensPin is HIGH then you are immediately setting it to 90. If the servo is not already at 0 then it will not have time to return to 0 before being commanded to go to 90. This will definitely cause jitter after the first time through loop.

If you intend for the servo to move when you press the button then you will have to be holding the button through the delay in the if statement completes in order for it to be read the next time loop() is called. delay() calls and button reading are usually a problem because during the delay the button cannot be read.

so the idea behind the delay() is to give the servo time to turn before reverting to 0, the plan is to replace the button with a motion sensor, so it cannot be held for a long time, only when I go past it. The entire goal of the project is to turn a servo motor, flicking off a light switch, then resetting the servo, so it can be repeated. Would it work setting the angle of the servo to 0 on setup and then in the if statement turn to 90 and then have a delay then set it back to 0. All within the if statement?

It doesn't really matter. All I'm saying is that if sensPin is still HIGH after loop() is called again then it won't have time to go back to 0 before going to 90 again. If the switch or sensor goes LOW during the delay then you are probably OK. If it stays HIGH you will get jitter every time through loop.

Inside the if statement you could go to 90, delay, go to 0, then delay again. I also think you would be better checking when the sensor BECOMES high and not when it IS high.

1 Like

How is your button wired? You need a pull-down resistor.

Although this may work for a while, in the long run you are likely to destroy the Arduino.

Why would I need a pull-down resistor here? Could you please explain, I'm relatively knew to Arduino.

Thanks a lot.

what would you recommend I do instead?

Use a 4xAA battery pack or 5V phone charger capable of greater than 1 Ampere to power the servo. Don't forget to connect the grounds.

This is the aprobiate way of supplying a servo

the function delay() is often seen in the Arduino-examples.

This guides newcomers in the wrong direction. As soon as you want to have something with more complexity that an single LED switch On/Off function delay() is just delaying finishing your project.

The much better suited alternativ to function delay is non-blocking timing

Non-blocking timing enables to do multiple things in "parallel".
But this is a different programming-paradigma.

You have to think very different than with using the function delay()

The basics are:

  1. all looping is done by function void loop() itself

  2. it requires to code all functions to

  • quickly jump in do a small step
    then
  • jump out because -- while----: void loop is really looping fast the next "jump in" will be done just 0,05 seconds in the future
void loop()
jump in myfuntion1 (quickly jump out)
jump in myfuntion2 (quickly jump out)
jump in myfuntion3 (quickly jump out)
...

So all defined functions are executed in sequence but it seems to be executed in parallel because each function proceeds just a small step and then jumps out
well "knowing" executing my next step will occur 0,15 seconds in the future.

Executing a certain sequence of steps is done by using a coding-technique called state-machine.

You can think of a state-machine like a machine that has different operation-modes.
as an example I use a laser-printer

if you switch on the laser-printer he will run through different operation-modes:

Operationmode 1: selftest
Operationmode 2: heating up
Operationmode 3: awaiting print-jobs
Operationmode 4: executing a print-job

In each mode the laserprinter does just this one thing
selftest or heating up or awaiting print-jobs or executing a print-job

Well some printers will be able to "receive" a second print-job while the first is not yet finished. (Doing things in parallel just we plan to do)

But I think you get the principle.

which operation-mode is "active" is controlled by using a state-variable.
After power-on the state is set to selftest

if selftest has finished set operation-mode to heating up

if heating up has finished set operation-mode to await printing-jobs

if a printing-job is received set operation-mode to print-this printing-job
if printing-job has finished set operation-mode to await printing-jobs

In your case the operation-modes are:

mode 1: wait for PIR-signal "active" if signal is detected set mode to 2

mode 2: set new servo-position "switch flipped" immidiately set mode 3

mode 3: wait for servo having reached this servo-position
check servo-position (with a read-command)
if servo has reached new position set mode 4

mode 4: set servo-position to start-position immidiately set mode 5

mode 5: wait for servo to reach start-position
check servo-position through a read-command
if servo has reached start-position set mode 1

one cycle has ran through

This is the concept. I'm sure you have a big question-mark inside your head
"sounds good but how do I code that?????

It is important to have an overview about the concept and then diving into the coding...

Quite some stuff to learn
here is a demo-code and explanation about non-blocking timing

and here is a demo-code how a state-machine is coded in principle. You have to adapt the switch-case-break-statement to your needs

Be the change you want to see in the world
best regards Stefan

1 Like

Stefan, I love you man, thank you so much! I'll get right to reading these posts.
I'm so very grateful for your reply.

I have previously posted about this but I have edited my code and it still refuses to work.
Here is my code:

#include <Every.h>

#include <Servo.h>



int servopin=9;
int servopos=90;
int sensPin = 8;
int servoRes = 0;
Servo myServo;





void setup() {
  
 
  pinMode(sensPin, INPUT);
myServo.attach(servopin);
myServo.write(servoRes);
}

void loop() {

 
  
  int val = digitalRead(sensPin);
  
  if(val==HIGH){
    
    myServo.write(servopos);
    static Timer t1(8000);
    if ( t1() ) { 
      myServo.write(servoRes);
      static Timer t2(8000);
    }
  }
 

}

Please tell me what I am doing wrong,
Sunny

You are cross-posting, which is against forum rules.

  • it looks like your senspin may be a button switch. they are normally connected to ground, the pin configured as INPUT_PULLUP and the pin is active LOW
  • don't know what Timer is. but the if (t1()) is inside the condition for the sensPin so will only execute if the sensPin remains active after the servo is moved
  • why is the a Timer t2? if these are simple delays, why not use delay()?
  • your code suggests that you want the servo to return to its original position after s delay

don't know the link to the original post