Help for my shaking quadruped robot

Hi, this is my first post in this forum.

First, sorry for my english. =(

I'm new to microcontrollers or electronics. In fact, this is my first microcontroller project.
I had made a quadruped robot with 12x HXT900 servo (3 DOF per leg). I use atmega328 with arduino bootloader. The problem is the servos are jitter too much. I already have research that most conclude that the problem is on the cheap servos (HXT900). Is that true? Is there any solution without replace the servos?
Please tell me if you need more information about this robot to help me. Here is my robot video :

Thanks before for your help.. :slight_smile:

At least it seems to work!
It looks like the input-readings are distorted.
Check the sketch for unused (but defined as input) pins and make them outputs or attach a pullup resistor on the inputs.

But don't expect too much:
the Arduino has only 256 different PWM steps per channel. A servo only 'understands' PWM signals from lets say 20% to 80% duty cycle ( wild guesssing here )
Both facts limit accuracy on the electronics side. Add mechanical inaccury and you see a trembling robot.

Probably a bit smoothing/averaging of the input-signals make it calm down, but at the same time it gets slower.

Never used a servo (yet), but if I remember correctly they shouldn't be controlled by pwm pins. This library has to (should) be used:

Can you post your code ?

I would advice to use simplot http://www.negtronics.com/simplot (or something similar) to look at the values you are sending to the servo's.
At least then you know whether the problem is in your code or in the electronics/mechanics.
If you have a scope you can also read the signals send to the servo's. I would also check the voltage. I would not be surprised you have voltage spikes because you have 12 servo's.
Best regards
Jantje

o_lampe:
It looks like the input-readings are distorted.
Check the sketch for unused (but defined as input) pins and make them outputs or attach a pullup resistor on the inputs.

Thanks for answering o_lampe.
I'd checked, there is no unused input pin in my code

tuxduino:
Never used a servo (yet), but if I remember correctly they shouldn't be controlled by pwm pins. This library has to (should) be used:

Servo - Arduino Reference

o_lampe:
the Arduino has only 256 different PWM steps per channel. A servo only 'understands' PWM signals from lets say 20% to 80% duty cycle ( wild guesssing here )
Both facts limit accuracy on the electronics side. Add mechanical inaccury and you see a trembling robot.

I don't understand o_lampe, I used standard Servo library like tuxduino mentioned before.
Can you explain how PWM has something to do with servo library?

Hi, tuxduino I was trying to post my code, but then my post exceeds 9500 character, which is not allowed. Sorry :frowning:

Jantje:
I would advice to use simplot http://www.negtronics.com/simplot (or something similar) to look at the values you are sending to the servo's.
At least then you know whether the problem is in your code or in the electronics/mechanics.
If you have a scope you can also read the signals send to the servo's. I would also check the voltage. I would not be surprised you have voltage spikes because you have 12 servo's.

Thanks alot Jantje. That's way above my level of knowledge.
I guess I need to learn from your link first..

You can zip it and add it to a post as an attachment. (Hint: additional options below the textbox)

That looks really good, well done.

If anything it looks as if the servos are struggling to hold position meaning they do not have enough torque.

If you beleive that you are sending smooth values to them, one moderate risk solution is to increase the servo refresh frequency.

This has the potential to shorten the lives of your servos, but will increase thier holding torque - theres always a trade off.

If you would like to try this I have a library which is similar to the existing servo library but which allows the refresh rate to be increased.

First find a way to check that the values you are sending are smooth, then if you want to try a higher refresh rate, let me know.

Duane B

rcarduino.blogspot.com

DuaneB:
That looks really good, well done.

If anything it looks as if the servos are struggling to hold position meaning they do not have enough torque.

First find a way to check that the values you are sending are smooth, then if you want to try a higher refresh rate, let me know.
rcarduino.blogspot.com

Hi DuaneB, thanks for your reply and compliment.
I think they have enough torque, because the jitter still occured when I lift up the robot.
I'd already checked the servos values thru serial monitor before, and they appeared as they expected.
May I have your servo library please?
P.s. Great blog you have there, must bookmark it!

tuxduino:
You can zip it and add it to a post as an attachment. (Hint: additional options below the textbox)

Done tuxduino. Hope you could help me.
But I have to warn you that my code is unprofessional, all messy and I didn't put comment lines to explain what doing what since I didn't expect someone would read it in the future. Sorry :frowning:

Quadruped_FULLCODE.rar (6.47 KB)

Me ? Help ? I was just suggesting a way to avoid the post length limit 8)

Seriously, though... I'll have a look at the code. I've never used a servo, let alone built a self-sustaining robot (very nice project of your, btw!). I hope I can be of some help nonetheless.

:slight_smile:

I spotted this:

else if(distance <= CRITdistance) {
        CRITvar = 1;                    // you assign a value
        switch(CRITvar) {            // then immediately test for its value
        case 1 :                            // of course this case will always be selected
            resetPREVangle();
            prevmillis = millis();
            while(millis() - prevmillis < 5000) {
                walkBWD();
                CRITvar = 2;
            }                          // missing "break", so case 2: will also be executed

        case 2 :
            resetPREVangle();
            ultrasoundSWITCH = 1;
            stallVAR = 0;
            turnRightVAR = 0;
            turnLeftVAR = 0;

            rotate();
            break;
        }
    }

CRITVar is not used elsewhere, so the code can be simplified as follows:

    else if(distance <= CRITdistance) {
            resetPREVangle();
            prevmillis = millis();
            while(millis() - prevmillis < 5000) {
                walkBWD();
            }

            resetPREVangle();
            ultrasoundSWITCH = 1;
            stallVAR = 0;
            turnRightVAR = 0;
            turnLeftVAR = 0;

            rotate();
    }

my 1 cent :slight_smile:

tuxduino:
I spotted this:

else if(distance <= CRITdistance) {

CRITvar = 1;                    // you assign a value
        switch(CRITvar) {            // then immediately test for its value
        case 1 :                            // of course this case will always be selected
            resetPREVangle();
            prevmillis = millis();
            while(millis() - prevmillis < 5000) {
                walkBWD();
                CRITvar = 2;
            }                          // missing "break", so case 2: will also be executed

case 2 :
            resetPREVangle();
            ultrasoundSWITCH = 1;
            stallVAR = 0;
            turnRightVAR = 0;
            turnLeftVAR = 0;

rotate();
            break;
        }
    }




CRITVar is not used elsewhere, so the code can be simplified as follows:




else if(distance <= CRITdistance) {
            resetPREVangle();
            prevmillis = millis();
            while(millis() - prevmillis < 5000) {
                walkBWD();
            }

resetPREVangle();
            ultrasoundSWITCH = 1;
            stallVAR = 0;
            turnRightVAR = 0;
            turnLeftVAR = 0;

rotate();
    }




my 1 cent :-)

Awesome tuxduino!! And that's not 1 cent, that's a million for your kindness to help me!

But I need "switch" function to keep the robot rotate routine not interfere by CRITdistance value till it's rotate routine completed. You see, the robot rotate left then right (or right then left, randomly) to compare which direction has longest distance to walk by.

But it still just my argument, I need to prove it by implementing your suggestion. :stuck_out_tongue:
So I'll try your revision first..
I'll report whether it works or not.. :slight_smile: :slight_smile:

tuxduino:

    else if(distance <= CRITdistance) {

resetPREVangle();
            prevmillis = millis();
            while(millis() - prevmillis < 5000) {
                walkBWD();
            }

resetPREVangle();
            ultrasoundSWITCH = 1;
            stallVAR = 0;
            turnRightVAR = 0;
            turnLeftVAR = 0;

rotate();
    }

OOPS.. Sorry tuxduino!!
You were right! It did work!!
I forgot I'd used "while" function inside my rotate function that make sure the rotate routine won't interfere by the change of "CRITdistance" value.
THANKS ALOT tuxduino!!!! :smiley: :smiley:

Well, I'm not sure I fully understand how I helped, but I'm glad I did :slight_smile: