Measuring Servo Current

To accurately measure the current consumed by a servo you need to connect an oscilloscope across a low value resistor in series with the servo ground. 1 ohm is the lowest commonly available value but this may be too high and disrupt the operation of the servos, so 1/2 ohm or lower is recommended. You can make a 1/2 ohm resistor by connecting two 1 ohm resistors in parallel as shown in this diagram:

Use 1/2 watt resistors if you have them but two 1/4 watt resistors would be suitable for currents up to 1 amp

Connect the scope across the resistor. Each volt on the scope represents two amps

This post is a response to an enquiry in this thread : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1255495242

Server errors were making it impossible to reply in that thread

Heya, sorry about the really late reply, Ive been pretty busy. Anywho, I didnt have two one-ohm resistors but I did have two two-ohm resistors, so I parallel'd them for one ohm.

With the scope, I see pulses down to 300mV (the ticking) with the rest of the wave at 40mV, but with a DMM, I get a constant reading of 92mV. This relates to 300mA and 92mA, respectively, during the ticking.

Im still convinced that the problem is a confliction between the LCD code and servo code, so Im going to try with the shift register LCD library

EDIT Using the shift register LCD library, there is less ticking, but it still happens, just with a different pattern. So there is still a conflict. I can use either one with no problem. I think Im going to stick with the shift reg LCD library, just because it uses fewer lines. So far, the only finite solution has been to attach the servo, use it, then detach it.

I still think you have a power problem. If the servo is only drawing 300ma then why do you get a 2.4 volt drop in your power supply?

are you certain you are not using a x10 probe? :wink:

I double-checked the probe, as that was the first thing I thought too :wink: I will go grab an AT power supply, as Im certain it can provide the power. Uno momento.

EDIT Ticking still happens with a computer power supply. Definately not a power issue!

EDIT 2 Maybe the probe was stuck on 10x somehow... Either way, I went back to the normal LCD hookup, to get a constant ticking that I could see clearly on the scope, and even with the AT PSU hooked up I get a .2v drop during the ticking, with what looks like inductive spikes to .4v . The ticking pattern with the shift register lcd hookup goes 3-3-8-3-3-8

even with the AT PSU hooked up I get a .2v drop during the ticking, with what looks like inductive spikes to .4v

If you get a 2.4 volt drop with the old supply and .2 with the new one, you did have a power supply problem so that is one more variable out of the way .

Are you still getting the flashing on the LCD? Are you still running with the version that has the waitMicroseconds that does not disable interrupts?

p.s. its great to see this site so responsive for a change :slight_smile:

Im not sure why the other one dropped so much, but rest assured, its been thrown out to prevent that problem from reoccuring :slight_smile:

The LCD does not flash with the new supply. I modified the shift register LCD .cpp to use waitMicroseconds instead, and now it doesnt tick in a timed manner, rather, it moves sporatically. It just cant sit still. It looks like it tries to start turning, turns a few degrees, then realizes it should be at zero and moves back. I can make a video if youd like, its quite hard to describe.

And yes, I agree completely! Its so nice to have access to the forums for help again!

can you try it without the keypad code. One obvious difference between the test I tried and the one you are having trouble with is the keyapd code.

I tried it with Serial.read() instead of using the keypad and the ticking is gone entirely! However, I looked through the keypad code, and didnt see any delays being used. How can this one be solved?

One step closer to the solution :slight_smile: Thank you so much!

I just had a quick look at the source code for keypad 1.8 (is that the version you are using) and I also did not see anything obvious. I will have another look in the morning.

Yes, v1.8 is the version Im using. I have a feeling the ticking is coming from how it polls the lines, but I, like you, didnt notice anything. Thanks!

I don't see anything in that code that would upset interrupt handling. Perhaps you could try a test to make getKey return immediately instead of doing the scan.

Add the following line at the beginning of the getKey function:

char Keypad::getKey(){
return NO_KEY; // make this the first executable line to see if the clicking stops

Ill try that when I get home from school. I also had another thought; I read the servo code over and right at the top it mentions that it pulses it in the background. Could that just be disabled?

You can disable the pulsing by calling the detach method but then the servo won't work. If you are asking if its possible to control the servos explicitly in your sketch, then yes you can do this using the software servo library: Arduino Playground - Servo

But you then need to call the refresh method every 20ms or so.

I do call the detach method in my new sketch, thats how Ive got the servo to stop - Ive attached, used it, delayed, then detached. If its possible to just not pulse in the background (why does it need to anyway?) that would stop the ticking aswell.

If there is no force on the servo output shaft then you may be ok only having the servo attached when you need to move it. But when the servo is not pulsed it will not correct any physical movement in the output shaft and the only thing keeping it in place is the friction from the gears and motor.

If you do decide to detach the servos then you will need to ensure that they are attached for long enough when you need to move them to a new position. A typical servo can take half a second to move 180 degrees.

The servo is going to be used to rotate a lock, so it doesnt need to keep itself in the same place - it wont be moved unless I tell it to. Also, I have a detach delay that lets me control how long until they get detached. Here is the attach/detach code Ive been using to solve the problem:

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

bool state = true;
bool doorOpen;
bool flashState = true;

int currentLength = 0;
int i = 0;
int screenDelay = 1000;
int detachDelay = 500;
long interval = 500;
long flashInterval = 2000;
long previousMillis, previousFlashMillis;

char password[4] = {
  0,0,0,0};
char entered[4];
const byte ROWS = 4;
const byte COLS = 3;
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);
  delay(10);
  servo.write(0);
  delay(detachDelay);
  servo.detach();

  lcd.begin(2, 16);
  lcd.setCursor(0,0);
  lcd.print(" Please enter a ");

  while (currentLength < 4)
  {
    if (millis() - previousFlashMillis > flashInterval) 
    {
      previousFlashMillis = millis();   

      if (flashState)
      {
        lcd.setCursor(0,0);
        lcd.print("4-digit password");
        flashState = false;
      }
      else
      {
        lcd.setCursor(0,0);
        lcd.print(" Please enter a ");
        flashState = true;
      }
    }
    char key = keypad.getKey();

    if (key != NO_KEY)
    {
      lcd.setCursor(currentLength + 6, 1);
      lcd.print(key);
      password[currentLength] = key;
      currentLength++;
      //delay(200);
    }

    if (millis() - previousMillis > interval) 
    {
      previousMillis = millis();   

      if (state)
      {
        lcd.setCursor(currentLength + 6, 1);
        lcd.cursor();
        state = false;
      }
      else
      {
        lcd.setCursor(currentLength + 6, 1);
        lcd.noCursor();
        state = true;
      }
    }
    delay(20);
  }
  if (currentLength == 4)
  {
    lcd.noCursor();
    lcd.setCursor(0,0);
    lcd.print("Your password is");
    delay((screenDelay + detachDelay) * 2);
    currentLength = 0;
  }
} 

void loop()
{
  if (!doorOpen)
  {
    lcd.setCursor(0,0);
    lcd.print(" Enter password ");
    lcd.setCursor(0,1);
    lcd.print("                ");
    lcd.setCursor(6, 1);

    while (currentLength < 4)
    {
      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 (millis() - previousMillis > interval) 
      {
        previousMillis = millis();   

        if (state)
        {
          lcd.cursor();
          state = false;
        }
        else
        {
          lcd.noCursor();
          state = true;
        }
      }
      delay(20);
    }
    if (currentLength == 4)
    {
      if (entered[0] == password[0] && entered[1] == password[1] && entered[2] == password[2] && entered[3] == password[3])
      {
        lcd.noCursor();
        lcd.setCursor(0,0);
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Accepted! --");

        servo.attach(4);
        servo.write(90);
        delay(20);
        servo.write(90);
        delay(detachDelay);
        servo.detach();

        delay(screenDelay);

        lcd.setCursor(0,0);
        lcd.print("----- Door -----");
        lcd.setCursor(0,1);
        lcd.print("---- opened ----");

        delay(screenDelay + detachDelay);
        currentLength = 0;
        doorOpen = true;
      }
      else
      {
        lcd.noCursor();
        lcd.setCursor(0,0);
        lcd.print("--- Password ---");
        lcd.setCursor(0,1);
        lcd.print("--- Incorrect! --");

        delay(screenDelay + detachDelay);
        currentLength = 0;
      }
    }
  }
  else
  {
    lcd.setCursor(0,0);
    lcd.print("--- Press # ----");
    lcd.setCursor(0,1);
    lcd.print("--- to lock. ---");

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

      if (key != NO_KEY && key == '#')
      {
        lcd.setCursor(0,0);
        lcd.print("----- Door -----");
        lcd.setCursor(0,1);
        lcd.print("---- locked ----");

        servo.attach(4);
        servo.write(0);
        delay(20);
        servo.write(0);
        delay(detachDelay);
        servo.detach();

        delay(screenDelay);

        doorOpen = false;
      }
    }
  }
}

Although I am still a little curious to know what is causing the clicking, your sketch looks like a good workaround to the problem. Is everything now functioning as you want?

Yes, using detach like that makes the servo work exactly as I want. The only thing I could think of that would cause the clicking is some interference between the servo trying to update its position in the background, and the keypad scanning the lines. In any case, at least its working now. Thanks for all your help!

And grats on your 5000th post!