Good point. Have you adjusted or tried changing the default PID values?
Ok so messing with my MX-12W Dynamixel I have noticed a little slack in the horn. When the motor is on and I am sitting in a while loop, printing the present position every second, with little to no force I can move the horn back and forth in the slack range and it will update my position. The slack range is approximately 5 positions.
As mentioned earlier by tician and r3n33, I think there is a PID solution. I don't see a lot of information on the e-manual about setting the PID values except the default values are as followed: P = 8; I = 0; D = 8. I'm nervous I am going to mess something up because I am using this motor in a project and I will not have enough time to replace it by the end of the semester.
Any guidance besides a wiki page to what PID means would be more than appreciated.
Yep tician lives up to the title.. like google but for robotsHe's pretty sharp! ... and probably could do a better job explaining PID but I'll give it a try.
P is the proportional gain relative to the error at the time of the reading. This is typically the main driving force of a PID controller. Too low of a value and the goal position may never be reached. Too high of a value the goal position will be reached but overshot.. causing an oscillation.
I is the integral term which is applied to the error over time. It can help a PID controller reach the goal quickly and can also be used to compensate for a persistent error offset. This term isn't always necessary for decent PID control which is likely why it's 0 by default. In your case this is the term I'd try increasing slowly to help your situation (small error of 1-5).
D is the derivative gain which is applied to change in error since the last reading. This can have a couple effects. One it will "slow" or decrease the controller's output as the goal position is approaching. On the other side of things it can also drive the output quickly toward the goal position if the error is increasing.
PID tuning can be tricky. Sometimes a PID tune will work for one situation but not another (differences in load, external disruption, etc.). I'd recommend trying to increase the P gain slightly or the I gain at first. Keep in mind PID is like a balance game.. changing one value may require another to change for good output.
As I mentioned, I have 1 MX-12, so thought I would do a quick and dirty test... I ran the test on my Odroid XU4 with an USB2AX in it and hacked in a simple pan test into my Raspberry Pi test AX servo program... I have not updated my project on github with this, but the code looks like:
Please pardon that as I said this is Quick and dirty!.Code:void PanServoTest(void) { unsigned long ulBefore; unsigned long ulDelta; word wID; int start_pos; int end_pos; int Pos; int cur_pos; int cur_speed; int servo_increment = 1; int loop_count; word w; int dxl_result; if (!FGetNextCmdNum(&wID)) return; // no parameters so bail. if (!FGetNextCmdNum(&w)) return; // no parameters so bail. start_pos = (int)w; if (!FGetNextCmdNum(&w)) return; // no parameters so bail. end_pos = (int)w; if (FGetNextCmdNum(&w)) servo_increment = (int)w; printf("Servo %d Pan test %d - %d step %d\n", wID, start_pos, end_pos, servo_increment); ax12SetRegister2(wID, AX_GOAL_POSITION_L, start_pos); delay(200); // give some time to get there! if (start_pos > end_pos) servo_increment = -servo_increment; for (Pos = start_pos; ; Pos += servo_increment) { if ( ((servo_increment > 0) && (Pos > end_pos)) || ((servo_increment < 0) && (Pos < end_pos)) ) break; ax12SetRegister2(wID, AX_GOAL_POSITION_L, Pos); dxl_result = dxl_get_result(); // Lets wait until we get there for (loop_count = 0; loop_count < 50; loop_count++) { delay(10); cur_pos = ax12GetRegister(wID, AX_PRESENT_POSITION_L, 2 ); if (cur_pos == Pos) break; } if (cur_pos != Pos) { cur_speed = ax12GetRegister(wID, AX_PRESENT_SPEED_L, 2 ); printf(" Goal: %d Actual: %d Speed: %d res=%d\n", Pos, cur_pos, cur_speed, dxl_result); } } printf("Completed\n\n"); }
The test program has a real simple command line UI,
Sample run:
So for this run I had the servo move 100 units at a time from 1000 to 4000, and tried to read the Current position back in up to 50 times until servo position matched... Disregarding the first one, where maybe I should have let the servo have some more time to settle in position, you can see there were several of these runs where the servo was off by a few...Code:[email protected]:~/Raspberry_pi/AX12_Test$ ./AX12_Test Start Controller model 4201 on fd(253) System Voltage in 10ths: 123 0 - All Servos off 1 - All Servos center 2 - Set Servo position [<Servo>] <Position> [<Speed>] 3 - Set Servo Angle 4 - Get Servo Positions 5 - Sync Read Servo positions 7 - Set Servos return delay 8 - Set ID: <old> <new> 9 - Print Servo Values t - Toggle track Servos w - write <servo> <reg> <val> (can be multiple values... p - Pan servo start end step h - hold [<sn>] f - free [<sn>] :p 1 1000 4000 100 Servo 1 Pan test 1000 - 4000 step 100 Goal: 1000 Actual: 1016 Speed: 0 res=1 Goal: 1200 Actual: 1198 Speed: 0 res=1 Goal: 1400 Actual: 1399 Speed: 0 res=1 Goal: 1500 Actual: 1501 Speed: 0 res=1 Goal: 1700 Actual: 1698 Speed: 0 res=1 Goal: 1800 Actual: 1798 Speed: 0 res=1 Goal: 1900 Actual: 1898 Speed: 0 res=1 Goal: 2000 Actual: 1996 Speed: 0 res=1 Goal: 2200 Actual: 2203 Speed: 0 res=1 Goal: 2300 Actual: 2296 Speed: 0 res=1 Goal: 2400 Actual: 2398 Speed: 0 res=1 Goal: 2500 Actual: 2497 Speed: 0 res=1 Goal: 2600 Actual: 2596 Speed: 0 res=1 Goal: 2700 Actual: 2696 Speed: 0 res=1 Goal: 2800 Actual: 2794 Speed: 0 res=1 Goal: 2900 Actual: 2896 Speed: 0 res=1 Goal: 3000 Actual: 2996 Speed: 0 res=1 Goal: 3100 Actual: 3097 Speed: 0 res=1 Goal: 3200 Actual: 3196 Speed: 0 res=1 Goal: 3300 Actual: 3296 Speed: 0 res=1 Goal: 3400 Actual: 3396 Speed: 0 res=1 Goal: 3700 Actual: 3696 Speed: 0 res=1 Goal: 3800 Actual: 3795 Speed: 0 res=1 Completed
Now back to my other playing.
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks