|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Holding a position in our arm
Heres the deal:
We have a revolute double jointed arm; say we wnat to hold the lower portion of the arm in one place; how would we do so? We have a potentiometer mesaureing the position values of the arm. Lets say we want the arm at a target val of 180. The arm is plugged into pwm02. We made some simple if/then statements... Please ignore syntax. sensor = Get_Analog_Value(rc_ana_in02); targetval = 180; if (sensor < targetval) { pwm02 = (127 + 53); else { pwm02 = (127 - 53); } This makes the arm oscillate at the target value, and it oscillates way too much. How can we essentially LOCK the arm through programming? |
|
#2
|
|||
|
|||
|
Re: Holding a position in our arm
You can't move the arm at a single hardcoded speed and then suddenly reverse it when you pass your target - you will overshoot, as I'm sure you've noticed. While full-fledged PID (PD, anyway) control would be best here, I understand you're short on time so you can implement a rudimentary version of P control like this:
You will need a PWM-limiting function that takes an integer and bounds it between 0 and 254, because otherwise the unsigned char that representes a PWM setting will roll over and you will find your motors moving backwards. targetVal = 180; float pGain = 0.5; int sensor = Get_Analog_Value(foo); pwm02 = pwm_Limit((pGain*(targetVal-sensor))+127); And then, just tweak the pGain up or down in small increments until your arm movement is acceptable. Again, PID feedback is great, so if you have the time to do it properly I definitely would, but you can get away with this in a pinch. |
|
#3
|
||||
|
||||
|
Re: Holding a position in our arm
Quote:
Integer math is always going to be more computationally efficient and in this case where the data source and destination have very limited precision, can be handled by simply moving the binary point up a few bits for the intermediate math, and then scale the result back down. Here's a different way to approach the problem with a proportional only controller... Code:
int targetVal = 180; int sensor; int err; int itmp; #define PGAIN 5 sensor = Get_Analog_Value(foo); err = targetVal - sensor; itmp = (PGAIN * err)/10; itmp = (itmp < -127)?-127:itmp; itmp = (itmp > 127)?127:itmp; pwm02 = itmp + 127; If more resolution is needed, simply scale up the multiplers and divisors to whatever precision is desired, as long as the intermediate values will still remain within a signed 16 bit value, the math will work out fine. If an intergal and differential term were needed then the code could be expanded like this... Code:
int targetVal = 180;
int sensor;
int err;
int p_out;
int i_out;
int d_out;
static int last_err = 0;
static int integrator = 0;
int delta_err;
int i_err;
int itmp;
#define PGAIN 5
#define IGAIN 3
#define DGAIN 2
sensor = Get_Analog_Value(foo);
err = targetVal - sensor;
delta_err = last_err - err;
last_err = err;
i_err = err + integrator;
p_out = PGAIN * err;
i_out = IGAIN * i_err;
d_out = DGAIN * delta_err;
itmp = (p_out + i_out + d_out)/10; // sum the totals and then move the binary point back into position.
if (itmp > 127) {
itmp = 127;
} else if (itmp < -127) {
itmp = -127;
} else {
integrator = i_err; // limit integrator windup by only accumulating when the output values are not saturated
}
pwm02 = itmp + 127;
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Programming our Arm | brennerator | Programming | 29 | 15-03-2007 01:17 |
| pic: Team 498 Robot Arm Stowed Position | Cactus_Robotics | Robot Showcase | 1 | 10-02-2007 21:42 |
| PID How to hold an arm in a fixed position without a locking gear box | Ian_Xodus | General Forum | 29 | 28-01-2007 08:50 |
| Pneumatics holding their position | sanddrag | Pneumatics | 22 | 15-01-2004 16:36 |