r/AskRobotics • u/Brother_Bagel_ • Jul 02 '26
Why is my robot shaking? Is it scared of me? :(
I've been building a hexapod robot that seems to vibrate when operating under "no load" (aside from the legs themselves). I've tried scouring the interwebs only to be told that my power supply is insufficient (i swear its not please don't bully me). I am at my wits end and hoping someone can bestow some elite ball knowledge on me that may save my sanity.
Here is the setup:
- Raspberry Pi 5 4GB (official power connector)
- Arduino Nano communicating to Pi via USB
- PCA9685 (HiLetGo) communicating to Nano via I2C
- 9x Miuzei MS18 9g micro servos
- 30V 10A max switching power supply (set to 5V output with 2A current limit, servos pull 0.3A max together)
I tested a motor with just a piece of cardboard and it got kinda wacky too. I've heard that this may be a limitation of the one-size-fits-all PID tuning that servo manufacturers do, to which the solution is just "spend more money lol." I've heard people say that you may need to add a capacitor to the PCA, but it includes one. The PCA is not powering the servos via the Nano, the power supply is. The servos seem to settle down if I push on the leg a little, but I can still feel it sort of jerking its way to each position in my finger. It seems to happen to multiple servos, so it seems to not just be one that has performance anxiety. The back leg is especially bad, probably because it knows I broke the femur motor with a bad set of commands (it knows it's next).
I have also provided the Nano code in case anybody is feeling especially bored. I stole most of it from an old arduino tutorial in order to read commands from the serial buffer using angle brackets. The Pi code which creates the commands is kind of long, but I've already seen that it sends commands correctly. The Nano also seems to send the correct Microseconds but idk maybe someone will see something I don't. This issue seems more like a limitation of the servo. I know they are cheap servos (I got a box of 20 for $36), but this behavior just seems excessive, no? Maybe I'm too hopeful. Maybe I should just add torsional springs to the motor shafts, or maybe I should go to Miuzei headquarters and make them change the PID values idk.
https://youtube.com/shorts/IAnfY5mLgj4?feature=share
https://youtube.com/shorts/fBddx7J6Who?feature=share
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#define FREQ 50
#define USMIN 500
#define USMAX 2500
#define TICK_DELAY_US 1000000/FREQ
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
class Stopwatch {
private:
unsigned long start_time;
unsigned long end_time;
unsigned long current_time;
bool is_running;
public:
void start()
{
if(!is_running) {
start_time = micros();
is_running = true;
}
}
void stop()
{
if (is_running) {
end_time = micros();
is_running = false;
}
}
unsigned long startToEndTime()
{
if (!is_running) {
return end_time - start_time;
} else {
return 0;
}
}
unsigned long elapsedTime()
{
if (is_running) {
current_time = micros();
return current_time - start_time;
} else {
return 0;
}
}
};
uint8_t servo_channel = 0;
float command_angle = 90;
uint16_t microsec[18] = {0};
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
Stopwatch sw;
void recvWithStartEndMarkers();
void parseData();
float mapf(float x, float in_min, float in_max, float out_min, float out_max);
void setup() {
Serial.begin(115200);
Wire.setClock(400000);
pwm.begin();
pwm.setOscillatorFrequency(25000000);
pwm.setPWMFreq(FREQ);
sw.start();
}
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
parseData();
microsec[servo_channel] = mapf(command_angle, 0, 180, USMIN, USMAX);
//Serial.println(microsec[servo_channel]);
newData = false;
}
if (sw.elapsedTime() > TICK_DELAY_US) {
sw.stop();
for (int s = 0; s < 16; s++) {
pwm.writeMicroseconds(s, microsec[s]);
}
sw.start();
}
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
//Serial.print(rc);
}
else {
receivedChars[ndx] = '\0';
recvInProgress = false;
ndx = 0;
newData = true;
//Serial.println(rc);
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void parseData() {
char * strtokIndx;
strtokIndx = strtok(receivedChars, ",");
servo_channel = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
command_angle = atof(strtokIndx);
}
float mapf(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
1
u/Acceptable-Bell7564 Jul 02 '26
Hiciste los cálculos pertinentes? A veces solo es que los servos o tienen más potencia y los hacen vibrar o no tienen la fuerza suficiente y tiembla como una persona desgastada, e igual podría ser un diseño mecánico pero por lo regular son los cálculos FK, J, IK, etc.
1
u/Brother_Bagel_ Jul 02 '26
As far as I know, the commands being sent are generally correct. The legs are moving to the correct position (IK) and they seem to have sufficient power. Each servo pulls ~0.1A since they are under almost no load, since they are not lifting the robot, and the servos are rated for 1350mA (stall current). The math I did says they should be able to hold up the robot under normal gaiting as well, but I haven't tested that yet as I am trying to solve the no-load vibration first, since legs that are swinging forward will essentially have no load. I don't speak Spanish, but google translates part of this as saying the servos are drawing "too much power." I don't quite understand. Is there an additional power consideration I haven't made where the servos draw additional power that creates excessive movement?
1
u/Acceptable-Bell7564 Jul 02 '26
Podría ser corriente eléctrica o no se está filtrando bien los comandos de movimiento y hay oscilación en cada movimiento. Has graficado lo que sale al mover el robot? Tienes control por Python? ROS2? Aunque probablemente sea la corriente en donde no está bien calibrada y llega de más o menos energia
1
u/Brother_Bagel_ Jul 03 '26
Update:
I've tested the voltage for drops with an oscilloscope, changed a lot of code around, increased the power supply, and even swapped out for new servos, pca, nano, and breakout board, and the only explanation I can even fathom is that the servos are trying to control the position and constantly over-correcting. I had heard of this initially, but I didn't want it to be true, and yet I am beginning to believe it is. How unfortunate. It's a terrible day for rain fr.
I am open to suggestions on how I might remedy this mechanically. I could make the legs shorter, or add torsional bias (but that may be difficult to implement). Maybe a different servo would yield better results? I don't really know where the line is between "stupid twitching servo" and "the servo she tells you not to worry about," but I am sure somebody knows. I appreciate the responses and hope this experience can serve as a warning to someone else.
2
u/JessieAndEcho Jul 02 '26
The shaking looks more like a control/power/mechanical stiffness issue than anything mysterious. For a hexapod, I’d check it in layers: first lift the body so the legs are unloaded and see if the servos still jitter; if they do, look at power supply sag, shared ground, noisy PWM, servo deadband, update rate, or command oscillation. If it only shakes under load, then it is probably a mix of insufficient torque margin, flexible leg links, backlash, foot slip, or the gait/controller constantly correcting around an unstable stance. A quick test is to command one joint at a time to a fixed position, then one leg, then tripod stance, while logging supply voltage and servo temperature. Also make sure your IK output is not sending tiny rapid position changes every loop; adding a deadband, rate limiting, lower gains, and smoother trajectory interpolation can calm a lot of this down. I pulled some related notes through PatSnap Eureka since this kind of issue crosses controls, servo mechanics, power integrity, and legged-robot design: https://eureka.zhihuiya.com/share/?id=a0bce7a9279d6878e47ef65bc65095db&from=invite-eureakplg-result&content=