Servo + LiquidCrystal = Not Working!

This is the sketch Im using:

#include <Servo.h> 
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
Servo myservo;

void setup() 
{ 
  lcd.begin(2,16);
  lcd.clear();
  lcd.print("start");
  myservo.attach(3);
  myservo.write(0);
} 

void loop() 
{
}

The LCD displays "start" but the servo only steps about 10 degrees and stops. If I take the LCD stuff out it goes the entire rotation that I want it to. Is there an incompatibility between the LCD library and the Stepper library?

Try a small delay between the two.

after lcd.print and before the servo initialization. 10 ms ish should be fine.

I'm not sure if it will work, but the small delays solved my problems when I was using my small servos.

Also, does it work if you move the servo write down into the Loop? I know the servo needs a constant signal to stay in it's position, not sure if the Setup would have an effect or not. (Since it's only called once, obviously :D)

Youre right, I put in a small delay and it worked. I wonder why this is!

#include <Servo.h> 
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
Servo myservo;

void setup() 
{ 
  lcd.begin(2,16);
  lcd.clear();
  lcd.print("start");
  delay(10);
  myservo.attach(3);
  myservo.write(0);
} 

void loop() 
{
}

Ive done some more work on the code and come up with this. Everything works as I want it to, except the motor goes back and forth really quickly when there is no input, and the backlight blinks to it. When you enter commands, the motor pauses, and it performs the 90° turns fine. Its only when its idle that it goes back and forth.

#include <Servo.h> 
#include <Keypad.h>
#include <LiquidCrystal.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

bool state = true;
bool doorOpen;

int currentLength = 0;
int i = 0;

char password[4] = {
  0,0,0,0};
char entered[4];
char keys[ROWS][COLS] = 
{
  {
    '1','2','3'                                                }
  , 
  {
    '4','5','6'                                                }
  ,
  {
    '7','8','9'                                                }
  ,
  {
    '*','0','#'                                                }
};
byte rowPins[ROWS] = { 
  3, 2, 1, 0 };
byte colPins[COLS] = { 
  7, 6, 5 }; 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
Servo servo;  // create servo object to control a servo 

void setup() 
{
  servo.attach(4);  // attaches the servo on pin 0 to the servo object 
  servo.write(0);
  lcd.begin(2, 16);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Pick a password:");
  while (currentLength < 4)
  {
    lcd.setCursor(currentLength + 6, 1);
    lcd.cursor();
    char key = keypad.getKey();
    if (key != NO_KEY)
    {
      lcd.print(key);
      password[currentLength] = key;
      currentLength++;
      delay(200);
    }
  }
  if (currentLength == 4)
  {
    lcd.noCursor();
    lcd.clear();
    lcd.home();
    lcd.print("The password is");
    lcd.setCursor(6,1);
    lcd.print(password[0]);
    lcd.print(password[1]);
    lcd.print(password[2]);
    lcd.print(password[3]);
    delay(3000);
    currentLength = 0;
  }
} 

void loop()
{
  if (!doorOpen)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Enter password:");
    while (currentLength < 4)
    {
      lcd.setCursor(currentLength + 6, 1);
      lcd.cursor();
      char key = keypad.getKey();

      if (key != NO_KEY)
      {
        lcd.print(key);
        entered[currentLength] = key;
        currentLength++;
        delay(200);
        lcd.noCursor();
        lcd.setCursor(currentLength + 5, 1);
        lcd.print("*");
        lcd.setCursor(currentLength + 6, 1);
        lcd.cursor();
      }
    }
    if (currentLength == 4)
    {
      if (entered[0] == password[0] && entered[1] == password[1] && entered[2] == password[2] && entered[3] == password[3])
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Accepted! --");
        servo.write(90);
        delay(1500);
        lcd.clear();
        lcd.home();
        lcd.print("----- Door -----"); 
        lcd.setCursor(0,1);
        lcd.print("---- opened ----");
        delay(1500);
        currentLength = 0;
        doorOpen = true;
      }
      else
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Incorrect! --"); 
        delay(1500);
        currentLength = 0;
      }
    }
  }
  else
  {
    lcd.clear();
    lcd.home();
    lcd.print("--- Press # ----"); 
    lcd.setCursor(0,1);
    lcd.print("--- to lock. ---");

    while (doorOpen)
    {
      char key = keypad.getKey();

      if (key != NO_KEY && key == '#')
      {
        lcd.clear();
        lcd.home();
        lcd.print("----- Door -----"); 
        lcd.setCursor(0,1);
        lcd.print("---- locked ----");
        servo.write(0);
        delay(1500);
        doorOpen = false;
      }
    }
  }
}

I dont understand what you mean by "Its only when its idle that it goes back and forth" but perhaps you don't have enough power to drive everything. You can test this by temporarily disconnecting the backlight and see if the sketch functions as expected. If it does then you will need an external power supply.

I mean; when the program is waiting for an input from the user (no keys are being pressed) the gear on the servo goes CW then CCW a few times per second, in what seems like 1° rotations.

It looks like the program is always waiting for some kind of input. Are you saying the servo is always moving except when you press a key?

Did you try disconnecting the backlight?

Yes, I want it to wait for input. It first asks the user for a password, then has them enter it on a keypad. When the correct key is entered, it turns the servo, opening a lock. When the pound key is pressed, it re-locks and awaits a password.

With the backlight disconnected the servo still wiggles. But keep in mind its not moving very far, maybe a degree at the most. If a video would help I can take one.

So does it wiggle when no button is pressed in either the 0 degree or 90 degree position?

Can you try the sketch with a delay(20) at the bottom of loop?

A video may help particularly if you can show how everything is wired up, but first try adding the delay.

Not sure adding a delay will make any difference, I think you either have a problem with the way the system is wired and powered or there is a problem with the servo.

I ran the following sketch (using serial input instead of keypad) and the servo (powered using an external power supply) does not wiggle while waiting for a key.

#include <Servo.h>
//#include <Keypad.h>
#include <LiquidCrystal.h>
#define NO_KEY -1 // added for testing with serial input

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

bool state = true;
bool doorOpen;

int currentLength = 0;
int i = 0;

char password[4] = {'1','2','3','4'};


char entered[4];
char keys[ROWS][COLS] =
{
  {   '1','2','3'                                                }
  ,
  {
    '4','5','6'                                                }
  ,
  {
    '7','8','9'                                                }
  ,
  {
    '*','0','#'                                                }
};
byte rowPins[ROWS] = {
  3, 2, 1, 0 };
byte colPins[COLS] = {
  7, 6, 5 };

//Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
Servo servo;  // create servo object to control a servo

void setup()
{
  Serial.begin(9600);
  servo.attach(4);  // attaches the servo on pin 4 to the servo object
  servo.write(0);
  lcd.begin(2, 16);
  lcd.clear();
 
}

void loop()
{
  if (!doorOpen)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    Serial.println(" Enter password:");
    lcd.print(" Enter password:");
    while (currentLength < 4)
    {
      lcd.setCursor(currentLength + 6, 1);
      lcd.cursor();
      char key = Serial.read();

      if (key != NO_KEY)
      {
        lcd.print(key);
        entered[currentLength] = key;
        currentLength++;
        delay(200);
        lcd.noCursor();
        lcd.setCursor(currentLength + 5, 1);
        lcd.print("*");
        lcd.setCursor(currentLength + 6, 1);
        lcd.cursor();
      }
    }
    if (currentLength == 4)
    {
      if (entered[0] == password[0] && entered[1] == password[1] && entered[2] == password[2] && entered[3] == password[3])
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
          Serial.println("--- Password ---- Accepted! --");
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Accepted! --");
        servo.write(90);
        delay(1500);
        lcd.clear();
        lcd.home();
        lcd.print("----- Door -----");
        lcd.setCursor(0,1);
        lcd.print("---- opened ----");
        delay(1500);
        currentLength = 0;
        doorOpen = true;
      }
      else
      {
          Serial.println("--- Password --- Incorrect! --");
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Incorrect! --");
        delay(1500);
        currentLength = 0;
      }
    }
  }
  else
  {
    lcd.clear();
    lcd.home();
    lcd.print("--- Press # ----");
    lcd.setCursor(0,1);
    lcd.print("--- to lock. ---");
    Serial.println("--- Press # ----- to lock. ---");

    while (doorOpen)
    {
      char key = Serial.read();

      if (key != NO_KEY && key == '#')
      {
        lcd.clear();
        lcd.home();
        lcd.print("----- Door -----");
        lcd.setCursor(0,1);
        lcd.print("---- locked ----");
        Serial.println("----- Door ----- locked ----");
        servo.write(0);
        delay(1500);
        doorOpen = false;
      }
    }
  }
}

I cant add serial because Im using pins 0-13 to connect to the servo, the LCD, and the keypad, and that uses up pins 0 and 1. Unless there's a way to switch the analog inputs to outputs...

The servo is brand new, and the sweep example works fine. Also, rotating 90 degrees works just fine too. It just 'ticks' when its sitting idle.

The video is uploading now. I accidentally filmed it upside down so if photobucket cant rotate it, youll have to tilt your head a bit :wink:

EDIT Nope, wont let me rotate. Ohwell. You can hear the ticking atleast.

Also, I confirmed that there is a pulse on the servo output with my scope when I hear the ticking.

From your description, you are driving the servo beyond its limits when writing 0, Try writing 10 and see if that fixes it.

The sweep example is not a good test for this because it does not remain at 0 for long enough to notice the problem. the 'knob' example is a better test for this

I tried writing 10's instead of 0's, but it ticks faster now, and with short bursts every second or two.

if you have a pot, try the knob example.

If not you can modify it with this code in loop - it will step 10 degrees waiting 2 seconds at each step. See if it makes noise at the 0 degree position

void loop() 
{ 
  for(pos = 0; pos <= 90; pos += 10)  // goes from 0 degrees to 90 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(2000);                       // waits  for the servo to reach the position 
  } 
  for(pos = 90; pos>=0; pos-=10)     // goes from 90 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(2000);                       // waits  for the servo to reach the position 
  } 
}

I am off now till tomorrow so here are some troubleshooting suggestions.

If the servo does not tick when running modified knob code then try running the code I posted in reply #9, you will need to disconnect the keypad from pins 0 and 1 but keep the LCD connected. If this has still has problems, disconnect the LCD (but don't change the code).

Good luck!

Nope, no noise. Where should I try putting a delay in my loop?

See my previous post for some suggestions on what to try next.

I tried delays like this, and the problem is (almost) gone, but it does tick every couple seconds or so:

#include <Servo.h> 
#include <Keypad.h>
#include <LiquidCrystal.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

bool state = true;
bool doorOpen;

int currentLength = 0;
int i = 0;

char password[4] = {
  0,0,0,0};
char entered[4];
char keys[ROWS][COLS] = 
{
  {
    '1','2','3'                                                }
  , 
  {
    '4','5','6'                                                }
  ,
  {
    '7','8','9'                                                }
  ,
  {
    '*','0','#'                                                }
};
byte rowPins[ROWS] = { 
  3, 2, 1, 0 };
byte colPins[COLS] = { 
  7, 6, 5 }; 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
Servo servo;  // create servo object to control a servo 

void setup() 
{
  servo.attach(4);  // attaches the servo on pin 0 to the servo object 
  servo.write(0);
  lcd.begin(2, 16);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Pick a password:");
  while (currentLength < 4)
  {
    lcd.setCursor(currentLength + 6, 1);
    lcd.cursor();
    char key = keypad.getKey();
    if (key != NO_KEY)
    {
      lcd.print(key);
      password[currentLength] = key;
      currentLength++;
      delay(200);
    }
    delay(100);
  }
  if (currentLength == 4)
  {
    lcd.noCursor();
    lcd.clear();
    lcd.home();
    lcd.print("The password is");
    lcd.setCursor(6,1);
    lcd.print(password[0]);
    lcd.print(password[1]);
    lcd.print(password[2]);
    lcd.print(password[3]);
    delay(3000);
    currentLength = 0;
  }
} 

void loop()
{
  if (!doorOpen)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Enter password:");
    while (currentLength < 4)
    {
      lcd.setCursor(currentLength + 6, 1);
      lcd.cursor();
      char key = keypad.getKey();

      if (key != NO_KEY)
      {
        lcd.print(key);
        entered[currentLength] = key;
        currentLength++;
        delay(200);
        lcd.noCursor();
        lcd.setCursor(currentLength + 5, 1);
        lcd.print("*");
        lcd.setCursor(currentLength + 6, 1);
        lcd.cursor();
      }
      delay(100);
    }
    if (currentLength == 4)
    {
      if (entered[0] == password[0] && entered[1] == password[1] && entered[2] == password[2] && entered[3] == password[3])
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Accepted! --");
        servo.write(90);
        delay(1500);
        lcd.clear();
        lcd.home();
        lcd.print("----- Door -----"); 
        lcd.setCursor(0,1);
        lcd.print("---- opened ----");
        delay(1500);
        currentLength = 0;
        doorOpen = true;
      }
      else
      {
        lcd.noCursor();
        lcd.clear();
        lcd.home();
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Incorrect! --"); 
        delay(1500);
        currentLength = 0;
      }
    }
  }
  else
  {
    lcd.clear();
    lcd.home();
    lcd.print("--- Press # ----"); 
    lcd.setCursor(0,1);
    lcd.print("--- to lock. ---");

    while (doorOpen)
    {
      char key = keypad.getKey();

      if (key != NO_KEY && key == '#')
      {
        lcd.clear();
        lcd.home();
        lcd.print("----- Door -----"); 
        lcd.setCursor(0,1);
        lcd.print("---- locked ----");
        servo.write(0);
        delay(1500);
        doorOpen = false;
      }
      delay(100);
    }
  }
}

I will try your previous suggestions.

Results:

  • found a 10k pot, ran the knob example, and it worked just fine, no ticking
  • I ran your modified code and the stepper ticks very rapidly while waiting for a password to be chosen, and a password to be entered, but it doesnt tick at all when its waiting for the # key to be sent.

I think a good way forward is to understand why running the same code works ok for me but not in your environment.

Lets start by understanding the results of the tests I suggested in reply #14:

Did you run the code exactly as posted in reply#9 (keypad code removed and serial code added) and is this the test that had the following result:
“the stepper (servo) ticks very rapidly while waiting for a password to be chosen, and a password to be entered, but it doesnt tick at all when its waiting for the # key to be sent.”

Did you try the same test sketch with the LCD disconnected? If so, was there any difference in the servo noise? If not, try that test.

Is the ticking with the test sketch any different than you experienced running your original sketch?