Servo keeps shaking

Hi!

I've been trying to add a servo to a arduino game I found online. This is the link to the original post of the before mentioned game: https://create.arduino.cc/projecthub/unexpectedmaker/pixel-chaser-game-5929cf. I want to add a servo to it to open a compartment when the player reaches a certain score. For testing, I tried to let the servo move when the score hits 4. The problem I found whit this is (also when the only thing I do is attach the servo to a pin in the code) that the servo keeps shaking. I can't figure out why and hoped someone could help me look at this and maybe help me solve it :). I will put my code beneath here. The original code can be found in the before mentioned link.

Thanks in advance!

(sorry that some things in the code are in Dutch and that I had to cut out a part of the author/license section. The forums wouldn't let me post more than two links in a question. For the author/license information, please visit the above shared link. I am NOT the creator of this code)
code:
/*

Pixel Chaser Game - v1.0.0 - 24/03/2019.

AUTHOR/LICENSE:
Created by Seon Rozenblum
Copyright 2016 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html

DISCLAIMER:
This software is furnished "as is", without technical support, and with no
warranty, express or implied, as to its usefulness for any purpose.

PURPOSE:
This controller is the software that runs on the Reflow Master toaster oven controller made by Unexpected Maker

HISTORY:
24/03/2019 v1.0.0 - Initial release.

NOTE: This is a work in progress...

*/

// We need these libraries installed from library manager

#include <Adafruit_NeoPixel.h>
#include "OneButton.h"
#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
                // twelve servo objects can be created on most boards
 
int pos = 0;    // variable to store the servo position 
 

// What GPIO is the strip connected to
#define PIXELPIN       6

// How many NeoPixels in the strip
#define NUMPIXELS      24

// What GPIO is the button connected to?
#define BUTTON_TAP     3

// Initialise the button, with a default low
OneButton buttonTAP(BUTTON_TAP, false);

// Initialise the pixel strip
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELPIN, NEO_GRB + NEO_KHZ800);

// A bunch of variables
int playerIndex = -1;
int playerIndexTrail = -1;
int playerDirection = 1;
float nextMove = 0;
float currentPlayerSpeed = 150;
unsigned long countdown  = 0;
int enemyIndex = -1;
int coinIndex = -1;
int score = 0;
int bestScore = 0;
int lastScore = 0;
bool gameOver = false;

void setup()
{
  // make the button pin an input
  pinMode( BUTTON_TAP, INPUT );
  pinMode( 9, OUTPUT);
  pinMode( 10, OUTPUT);
  pinMode( 11, OUTPUT);
  
  // Attatch click functions to the button
  buttonTAP.attachClick(singleClick);
  buttonTAP.attachLongPressStart(longClick);

  myservo.attach(5);
 

  // Initialise the strip and set it's brightness to 20%
  pixels.begin();
  pixels.setBrightness(20);

  score = 0;

  // set a 2 second countdown before the player appears and starts moving
  countdown = millis() + 2000;
}

void loop()
{

  // Every cycle we need to tick the button state
  buttonTAP.tick();

  // If the game is in game over state, exit loop early
  if ( gameOver )
    return;

  // Set the pixel display state of the level
  // This sets the enemy position and the coin position
  SetLevel();

  // wait for a second for the player to get ready
  if ( countdown > millis() )
  {
    pixels.show();
    return;
  }

  // All the player display, movement and game logic is in here
  DisplayPlayer();
  LichtLevels();

   // This sends the updated pixel color to the hardware.
  pixels.show();
}

// Clear the level, setting all pixels to black
void ClearLevel()
{
  for(int i=0;i<NUMPIXELS;i++)
      pixels.setPixelColor(i, pixels.Color(0,0,0)); // Moderately bright green color.

  pixels.show();
}

// Show the best score in yellow and if the last score was less than the best, show that on top in red
void BestScore()
{
  // Best score in yellow
  for(int i=0;i<NUMPIXELS;i++)
  {
    if ( i < bestScore )
      pixels.setPixelColor(i, pixels.Color(255,155,0)); // Moderately bright green color.
    else
      pixels.setPixelColor(i, pixels.Color(0,0,0)); 
  }

  // last score is less than best is in red
  if ( lastScore < bestScore )
  {
    for(int i=0;i<lastScore;i++)
      pixels.setPixelColor(i, pixels.Color(255,0,0)); // Moderately bright green color.
  }
  pixels.show();
}

// Game over animation
void GameOver()
{
  // First pass we animate the strip going red from the enemy position
  int a = enemyIndex;
  int b = enemyIndex;
  
  for(int i=0;i<NUMPIXELS/2;i++)
  {
      pixels.setPixelColor(a, pixels.Color(255,0,0)); // Moderately bright green color.
      pixels.setPixelColor(b, pixels.Color(255,0,0)); // Moderately bright green color.

      a = ( a + 1) % NUMPIXELS;
      b--;
      if ( b == -1 )
        b = NUMPIXELS;

      pixels.show();
      delay(20);
  }

  delay(100);

  // Second pass we animate the strip going back from the enemy position
  a = enemyIndex;
  b = enemyIndex;
  
  for(int i=0;i<NUMPIXELS/2;i++)
  {
      pixels.setPixelColor(a, pixels.Color(0,0,0)); // Black
      pixels.setPixelColor(b, pixels.Color(0,0,0)); // Black

      a = ( a + 1) % NUMPIXELS;
      b--;
      if ( b == -1 )
        b = NUMPIXELS;

        pixels.show();
        delay(20);
  }

  // Now we show the best score
  delay(100);
  BestScore();
}

// Setup the level including the postiion of the enemy and the coin
void SetLevel()
{
  // If the enemy position is -1 (has been reset)
  // Find a new position for the enemy
  if ( enemyIndex < 0 )
  {
    // I fthe player not playing, always start the enemy at the half strip position
    if ( playerIndex < 0 )
    {
      enemyIndex = NUMPIXELS / 2;
    }
    // The player is in the game, so make sure not to place the enemy on or too close to the player
    else
    {
      enemyIndex = random(0, NUMPIXELS);

      while ( abs(enemyIndex - playerIndex ) < ( NUMPIXELS / 4 ) )
        enemyIndex = random(0, NUMPIXELS);
    }
  }
  // If the coin position is -1 (has been reset)
  // Find a new position for the coin
  if ( coinIndex < 0 )
  {
      coinIndex = random(0, NUMPIXELS);

      // pick a coin position somewhere between the player and enemy
      while ( abs(coinIndex - playerIndex ) < 7 || ( abs(coinIndex - enemyIndex ) < 7 ) )
        coinIndex = random(0, NUMPIXELS);
  }

  pixels.setPixelColor(enemyIndex, pixels.Color(255,0,0));
  pixels.setPixelColor(coinIndex, pixels.Color(255,255,0));
}

// This is where all the magic happens
// Player movement happens here as well as game logic for collecting coins or hitting the enemy
void DisplayPlayer()
{
  
  if ( nextMove < millis() )
  {
    nextMove = millis() + currentPlayerSpeed;

    // The player has a visual trail, so these next 2 if statements shows or clears the trail
    if ( playerIndexTrail >= 0 )
        pixels.setPixelColor(playerIndexTrail,  pixels.Color(0, 0, 0));

    if ( playerIndex >= 0)
    {
      pixels.setPixelColor(playerIndex, pixels.Color(0, 100, 0));
      playerIndexTrail = playerIndex;
    }

    // Move the player in their current direction
    playerIndex += playerDirection;

    // Wrap the player at the strip edges
    if ( playerIndex < 0 )
      playerIndex = NUMPIXELS - 1;
    else if ( playerIndex == NUMPIXELS )
      playerIndex = 0;
    
    pixels.setPixelColor(playerIndex, pixels.Color(0, 255, 0));

    // Did the player hit the coin?
    // If so, increase the score, reset coin and enemy positions and clear the level
    // Next loop the SetLevel() will reset the enemy and coin
    // Player speed is also increased for every coin hit
    if ( playerIndex == coinIndex )
    {
      enemyIndex = -1;
      coinIndex = -1;
      score++;
      currentPlayerSpeed = constrain( currentPlayerSpeed - 10, 50, 150 );
      ClearLevel();
      pixels.setPixelColor(playerIndex, pixels.Color(0, 255, 0));
    }
    // Did the player hit the enemy?
    // Set the last/best score and call game over
    else if ( playerIndex == enemyIndex )
    {
      lastScore = score;
      if ( score >= bestScore )
        bestScore = score;
        
      GameOver();
      
      gameOver = true;
      enemyIndex = -1;
      coinIndex = -1;
      playerIndex = -1;
    }
  }
}

// Single button click
void singleClick()
{
  // No input until player is visible
  if ( countdown > millis() )
    return;

  // switch the player direction
  playerDirection = -playerDirection;
}
  
// Long button click
void longClick()
{
    // Switch game over state
    // If it was game over, start the game, otherwise cancel a game in progress
    gameOver = !gameOver;
    if ( gameOver )
    {
      enemyIndex = -1;
      coinIndex = -1;
      playerIndex = -1;
      currentPlayerSpeed = 150;
      ClearLevel();
    }
    else
    {
      ClearLevel();
      score = 0;
      currentPlayerSpeed = 150;
      countdown = millis() + 2000;
    }
}
void LichtLevels()
{
  if(score == 1){
    digitalWrite( 9, HIGH);
  }
  if(score == 2){
    digitalWrite( 10, HIGH);
  }
  if(score == 3){
    digitalWrite( 11, HIGH);
    servoding();
  }
}
void servoding(){
  myservo.write(180);
}

Please follow the advice given in the link below when posting code , use code tags and post the code here to make it easier to read and copy for examination

Both the Adafruit NeoPixel and the FastLED libraries demand a lot from a basic Arduino board. The millis() function and many libraries might no longer be reliable.
The Arduino 5V board can not be used to power a servo motor. Which servo motor is it ? Most small servo motors might request a peak of 0.5A and stronger servo motors might request peaks of a few amps.

You can edit your post and put your sketch between lines with three backslash-single-quotes.

```
Your sketch
```

Please edit your post to add code tags.

Neopixels and servos don't tend to work together due to interrupt and timing issues.

Other servo problems are almost always due to an inadequate servo power supply. Use a separate servo power supply capable of providing 1 Ampere per small servo, or 3 Amperes per large servo. Don't forget to connect the grounds.

Hi UKHeliBob,

Thanks for showing me this! This is my first post, so there is a lot to learn. I think it is correct now!

Hi Koepel,

Thanks a lot for your reply! The servo i am using is a small 9 gram servo i have used before with arduino. Do you think there is a way to make these two libraries work together so i still can use anm servo together with this ledring game?

PS. I fixed the way tje sketch appears

Thanks again!

Hi jremington,

Thanks a lot for your reply! I tried to connect the power line if the small servo to abither arduino (the easiest power supply i could think of). Still the same happened. Do you think there is a way to make the led ring game work together with the servo in another way?

PS. I fixed the way the post shows the code!

Thanks again!

If you can find a more expensive servo motor with a sleep-mode, that might help.
The more expensive servo motors are often digital servo motors.
If it has a sleep mode, then the sleep-mode is entered if the servo signal is removed.
You would have to make changes to the sketch, to call myservo.write(180); just once.
Removing the servo signal is done with myservo.detach()

  myservo.write(180);
  delay( 1000);            // one second to reach 180 degrees
  myservo.detach();

When the score is 3, is that the end of the sketch ? Then you have to rewrite that and turn into a some kind of idle mode.

Even if your servo motor does not have a sleep mode, give it a try to remove the servo signal. See what happens.

An other option is to buy a hardware module that generates the servo signal.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.