[SOLVED] Servo jitter with random angle millis() code

The below code generates a pseudo-random angle every three seconds and then the servo rotates to it. At most angles, large and small, the servo jitters noticeably around its target angle, instead of coming to a standstill. Are there errors in my code that cause this problem?

When I set target angles via serial, no jitter occurs, and also not with other people's random angle servo codes, such as this one. I also made a short 45MB 720p video of the issue.

What am I doing wrong?

#include <Servo.h>

const int timeServoInterval = 7;
const int timeSimUserInterval = 3000;
unsigned long timeNowServo = 0;
unsigned long timeNowUser = 0;

int angleCurrent;
int angleTarget;

Servo ovres;

void setup() {
  //Serial.begin(115200);
  randomSeed(analogRead(0));
  ovres.attach(3);
  ovres.write(0);
  angleCurrent = ovres.read(); // Seed with initial value to start
  angleTarget = random(10, 140); // Seed with initial value to start
}

void loop() {
  simulateUserInput();
  rotateServo();
}

void rotateServo()
{
  if (millis() - timeNowServo >= timeServoInterval)
  {
    timeNowServo = millis();

    if (angleCurrent <= angleTarget)
    {
      angleCurrent ++;
      ovres.write(angleCurrent);
    }
    else
    {
      if (angleCurrent >= angleTarget)
      {
        angleCurrent --;
        ovres.write(angleCurrent);
      }
    }
  }
}

void simulateUserInput() // Set angle programmatically (later by user input)
{
  if (millis() - timeNowUser > timeSimUserInterval)
  {
    timeNowUser = millis();
    angleTarget = random(10, 170);
  }
}

You never seem to recognise that the servo is on target and stop writing to it. You keep adding or subtracting one and writing a new value. Why not a simple "If it's on target do nothing"?

Steve

Thanks, Steve, you were right of course; it jitters because it's looping on, changing "angleCurrent" when the target is already reached before three seconds are over. I added an if statement and now it works as intended. Random angle and two millis() functions running nicely independently.

#include <Servo.h>

const byte timeServoInterval = 6;
int timeSimUserInterval; // Set "do something" interval programmatically
unsigned long timeNowServo = 0;
unsigned long timeNowUser = 0;

int angleCurrent;
int angleTarget;

Servo ovres;

void setup()
{
  randomSeed(analogRead(0));
  ovres.attach(3);
  ovres.write(0);
  angleCurrent = ovres.read(); // Seed with initial value to start
  angleTarget = random(0, 180); // Seed with initial value to start
}

void loop()
{
  simulateUserInput(); // Values (°) randomly generated within a range
  rotateServo();
}

void rotateServo()
{
  if (millis() - timeNowServo >= timeServoInterval) // Check if it is time to rotate
  {
    timeNowServo = millis(); // Record the current time
    if (angleCurrent != angleTarget) // Don't write to servo if target angle is reached
    {
      if (angleCurrent <= angleTarget)
      {
        angleCurrent ++;
        ovres.write(angleCurrent);
      }
      else
      {
        if (angleCurrent >= angleTarget)
        {
          angleCurrent --;
          ovres.write(angleCurrent);
        }
      }
    }
  }
}

void simulateUserInput() // Set target angle programmatically (later through user input)
{
  if (millis() - timeNowUser > timeSimUserInterval)
  {
    timeNowUser = millis();
    timeSimUserInterval = random(1000, 8000);
    angleTarget = random(0, 180);
  }
}