Resolution question - 12 bit servo, 8 bit Arduino Ethernet

Hello all,

I am using an Arduino Ethernet w/o POE board to control 2 HS-M7990TH servo, which have a 12 bit digital programmable circuit and silly amounts of torque. The board and servos are being powered by a 6.8V, 14A power supply.

When controlling the servos through the official HITEC (company who make the servos) software, the servos work fine with a 5V, 35A power supply (Overkill, yes, but I wanted to make sure there was enough power). I hook the Arduino and servos up to the 6.8V, 14A power supply and have their PWM leads connected to pins 3 and 5 on the Arduino. When I run my code, I notice that the servos have some jitter to them. I first checked the pulse width to see if my Arduino code was accidentally changing it or the servos were being loaded too heavily via Serial Monitor output of pin 5 (The PWM pin for the servo). The read out said it was at the proper microsecond and everything was fine. Then I thought that the servos might not be getting enough current (They can draw up to 4-5A by switching back and forth at a fast pace). I hooked up the servos to a 5V, 35A power supply and had the servo control connected to pin 5 to get the microsecond pulse from the Arduino for control. There was still jittering in the servos. I hooked up the pulses trains from the Arduino and the HITEC software to an Oscope to see if there was anything different between them. The only difference was see in voltage levels (HITEC was 4.2 and the Arduino was 4.5, but the servos can handle 3-5V PWM signal). I currently believe that the servos are not jittering from not enough power.

I think my problem is with 12 bit precision for the servos. I think the 8 bit provided by the Arduino is too low which gives me the jitter in the servos. I started looking into the schematics of the Leonardo, Due, and Mega to find out how precise they are, but I am not sure what exactly I am looking at. Basically, I'm looking for something like the Arduino Ethernet, but has more precision to it. I don't think something like that exists, so I am currently looking for an Arduino which can support 12 bit precision with PWM and then at the Wiznet chip in a custom satellite board. Is there an Arduino which supports 12 bit precision with their PWM?

Thanks,
Matt

That's a long post, but short on code or links.

Could be issues with your code or bad wiring like not connecting the servo and arduino grounds together. Also, the Dead Band Width of 1usec might be causing hunting and may need to be increased.

Is there an Arduino which supports 12 bit precision with their PWM?

No.

I think my problem is with 12 bit precision for the servos. I think the 8 bit provided by the Arduino is too low which gives me the jitter in the servos.

Per the info below I'm not sure which part of the servo has the " high resolution "G2.5" 12 bit generation programmable digital circuit". The specs for the servo say it has a programmable us deadband, which is listed at 1us and the statement that "Resolution (default is set at high)". The arduino may or may not be able to achieve "stable" pulse widths at 1us.

http://www.servocity.com/html/hs-m7990th_servo.html

AWOL:
That's a long post, but short on code or links.

Sorry about that, here my code to set up servos and then move them.

Set up Servos

    free(servos);
  servos = (Servo*) malloc(2*sizeof(Servo));
  for(int i=0; i<2; i++)
  {
    servos[i] = Servo(); 
  }
  servos[0].attach(3);
  servos[0].writeMicroseconds(1500);
  servos[1].attach(5);
  servos[1].writeMicroseconds(1775);
  delay(1000);

Move servos - check if updated PW is different and the time is greater than variable interval, if so, release brake (pull type solenoid - currently not installed yet), if not, apply brake.

if ( oldPanPW != newPanPW && currentMillis - previousPanMillis > interval)
 {
   digitalWrite(PanSolenoidFlag,HIGH);  //  releases the solenoid to stop the brake and allow servos to move
   if ( oldPanPW < newPanPW)  
   {
   previousPanMillis = currentMillis;
   oldPanPW++;
   servos[0].writeMicroseconds(oldPanPW);
   }
   else
   {
   previousPanMillis = currentMillis;
   oldPanPW--;
   servos[0].writeMicroseconds(oldPanPW);
   }
 }
 else if ( oldPanPW == newPanPW && currentMillis - previousTiltMillis > interval)
 {
   previousTiltMillis = currentMillis;
   digitalWrite(PanSolenoidFlag, LOW);  // Applies brake
 }

The code for the other servo is the exact same with different variables.

Also, I thought I set a link to the servo page, but looking back at my original post, i did not. This is what I'm using for the servo data - HS-M7990TH High Voltage, Mega Torque, Magnetic Encoder Ultra Premium Servo | HITEC RCD USA.

zoomkat:
Could be issues with your code or bad wiring like not connecting the servo and arduino grounds together. Also, the Dead Band Width of 1usec might be causing hunting and may need to be increased.

I have the servos and Arduino being powered by the same power supply. I've tested using a pulse generator to create my pulse train for servo control and the servos didn't jitter.

zoomkat:
Per the info below I'm not sure which part of the servo has the " high resolution "G2.5" 12 bit generation programmable digital circuit". The specs for the servo say it has a programmable us deadband, which is listed at 1us and the statement that "Resolution (default is set at high)". The arduino may or may not be able to achieve "stable" pulse widths at 1us.

http://www.servocity.com/html/hs-m7990th_servo.html

I am not 100% sure, I am calling HITEC today to get more information from them about the precision, but I thought it was for the feed back from the servo. I know the servo has "High Resolution Magnetic Digital Ecoder" which makes me think its the feedback.

Side note, what exactly is the deadband? I believe it to be the "slop" of the servo, so say it moves from 1700us to 1701us with the deadband being set to 3us, the servo wont move. However, if the pulse width moves to 1704us, it will change its position. right?

Thanks for the help thus far guys, I truly appreciate it.

So I changed the deadband width around and found out the following. Attached is an image of the HPP-21 software, and I will be referencing to section 4 of the image.

I set the deadband to 1, 2, and 4. At these different deadband widths, I stressed the servo (pushed down on it) and noticed that as the deadband width increased, so did the jittering amplitude. Therefore, when it was set to 1, the jitter was less, while the deadband width being set to 4 caused a larger jitter. With the deadband width at 2, it the amplitude of jitter was greater than 1 and less than 4.

I am unsure on terminology, is it considered increasing the deadband when I go from 1 to 4?

That all being said, I don't think the deadband width is something that will fix my problem. Do you think it could be a problem with the a unit mismatch? I know I have the servo pulse width Arduino side as an unsigned int and I don't know what the unit type is.

Matt

Arduino_help.PNG

Grumpy_Mike:

Is there an Arduino which supports 12 bit precision with their PWM?

No.

Are you ure about this? I was looking around PWM for arduinos and found this - http://arduino.cc/en/Reference/AnalogWriteResolution

The Due has the following hardare capabilities:
12 pins which default to 8-bit PWM, like the AVR-based boards. These can be changed to 12-bit resolution.
2 pins with 12-bit DAC (Digital-to-Analog Converter)
By setting the write resolution to 12, you can use analogWrite() with values between 0 and 4095 to exploit the full DAC resolution or to set the PWM signal without rolling over.

From my understanding, I can get a due to make 12 bit precision... right? if so, i could make my own Ethernet shield for the due

Does the servo jitter when there is no load on it? I think a standard servo can be expected to jitter when it is under load due to the way it is built and the way the motor in it is operated. Remember the motor is being turned on and off rapidly (~50 hz for standard servos, your servo may be different) in an attempt to hold position.

I just took everything off of the jittering servo and ran the sweep example, and it looks fine there.

I found this out about analogWrite

he PWM outputs generated on pins 5 and 6 will have higher-than-expected duty cycles. This is because of interactions with the millis() and delay() functions, which share the same internal timer used to generate those PWM outputs. This will be noticed mostly on low duty-cycle settings (e.g 0 - 10) and may result in a value of 0 not fully turning off the output on pins 5 and 6.

Ironically enough... the servo at pin 5 is jittering while the servo at pin 3 isnt... that being said, the servo at pin 5 is also being stressed a hell of a lot more than the servo at pin 3.

zoomkat:
Does the servo jitter when there is no load on it? I think a standard servo can be expected to jitter when it is under load due to the way it is built and the way the motor in it is operated. Remember the motor is being turned on and off rapidly (~50 hz for standard servos, your servo may be different) in an attempt to hold position.

The servos I'm using have a torque around 600 oz/in, and when I use a pulse generator - which looks similar to the PWM from the Arduino - the servo doesn't jitter.

I am currently rebuilding my project with a new servo for pin 5 to make sure I am not having a bad servo problem, but a signal problem. I have eliminated considereing it to be a power problem, because I can stop the servo from jittering using the project power supply and a pulse generator for signal instead of the arduino.

Matt

Some simple servo test code you can try to see if the servo still jitters.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7, 500, 2500);  //the pin for the servo control, and range if desired
  Serial.println("servo-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}

In my experience some servos just jitter anyway due to particular combinations of load, backlash, electrical noise etc even when they are driven from conventional RC receiver hardware (which I assume produces consistently accurate timing). May be that is all you are seeing. But I remember reading a thread here recently which implied that the Servo library did not produce very consistent pulse timing and if so that could be exacerbating the problem. I suggest doing a search for terms like servo pulse timing accuracy over the past few months and see if you can track down the thread. If I remember correctly, the problem was resolved in one case by using a different Servo library implementation.

Apparently the Arduino Servo library has limitations that can cause servo jitter. This guy has written a workaround. http://www.karlssonrobotics.com/tutorials/arduino/workaround-for-servo-jitter-on-arduino/ It may not fix your problem but is worth a try.

So I put in a new servo, changed the servo's PWM pin from 5 to 9, and everything is fine now. I'm still getting some jitter when it's heavily loaded (me pushing down on it pretty hard) but for the use I'm using, it wont be a problem.

I haven't looked into the work around yet, but I wouldn't mind trying it out to help my project come along.

Thank you for all the help you guys have given me and I'll update when I have tested the work around to see how everything goes for it.
Matt