ROBOTC.net forumshttp://www.robotc.net/forums/ Encoder Position....http://www.robotc.net/forums/viewtopic.php?f=1&t=433 Page 1 of 1

Author:  asma [ Fri Mar 07, 2008 9:23 am ]
Post subject:  Encoder Position....

Hi Everyone,
I’m writing a program that:
• Turn motor A to right and measure the distance.
• Return motor A to its original position (which supposes to be zero).
• Turn motor A to left and measure the distance.
• Return motor A to its original position (which also supposes to be zero).
The problem is that: the encoder value doesn’t return to its original position and after a while the accumulated shift has increased which causes some problems.
Here is the code:

 Code:int leftDistance(tMotor mName, int mSpeed, int mAngle, bool mReturn){   nMotorEncoder[mName] = 0; //reset the encoder   motor[mName] = -1*mSpeed ; //speed   while(nMotorEncoder[mName] > -1*mAngle){} //loop   motor[mName] = 0; //stop   //get the distance here   wait1Msec(600); //to get the value   int dis = SensorValue[sonar];   if(dis >= 250){      dis = 250; //infinity   }   //return to your position   if(mReturn){      //back to original direction      motor[mName] = mSpeed; //speed      while(nMotorEncoder[mName] < 0){}//loop      motor[mName] = 0; //stop      nMotorEncoder[mName] = 0; //reset the encoder   }//if   return dis;}//rotateLeftint rightDistance(tMotor mName, int mSpeed, int mAngle, bool mReturn){   nMotorEncoder[mA] = 0 ;//reset the encoder   motor[mName] =  mSpeed ; //speed   while(nMotorEncoder[mName] < mAngle){} //loop   motor[mName] = 0; //stop   //get the distance here   wait1Msec(600); //to get the value   int dis = SensorValue[sonar];   if(dis >= 250){      dis = 250; //infinity   }   //return to your position   if(mReturn){      //back to original direction      motor[mName] = -1*mSpeed; //speed      while(nMotorEncoder[mName] > 0){}//loop      motor[mName] = 0; //stop      nMotorEncoder[mName] = 0; //reset the encoder   }//if   return dis;}//rotateRight

I tried to use nMotorEncoderTarget instead; however, I got the same result. So could please guide me how to do it more accurately?

Thanks
Asma

Author:  MK [ Sat Mar 08, 2008 8:37 pm ]
Post subject:  Re: Encoder Position....

In order to avoid encoder drift, you want to remove the encoder reset from your return blocks. You wait until encoder value zero is reached and then stop the motor and reset the encoder to zero. If the commands execute fast enough, then the encoder value is still zero when you reset it. In this case the command is useless. If execution is not fast enough, then encoder value will drift with respect to physical position.

You could use the nMotorEncoderTarget variable in order to perform the task. However, be aware that the value is not understood as absolute target position but as a number of encoder increments to advance.

This has some drift implications as well. Consider the ROBOTC example NXT Position Control with the suggested "hand of a clock" robot design. You will find that you can create a permanent delay in the hand by blocking it for one or more loop iterations. For a clock, such relative, incremental position control is not really an ideal solution. Absolute control is better.

However, I do not know of a smart way to implement it. My solution consists of a PD control that forces the moter to go to a given absolute encoder value.

 Code:task PDA(){   int nE = 0;         // Fehler (offset)   int nEalt = 0;      // alter Fehler (previous offset)   int y = 0;          // Stellgroesse (action)   float fKp = 10;      // Kp Faktor Proportionalglied   float fKd = 400;      // Kd Faktor Differentialglied   int nTa =10;        // Ta Zeitschritt   while(true)   {      nE = t - nMotorEncoder[motorA];      y = fKp*nE + fKd/(float)nTa*(nE-nEalt);      nEalt = nE;      if (y > 100) y = 100;    if (y < -100) y = -100;    motor[motorA] = y;      wait1Msec(nTa);   }}task main(){   bFloatDuringInactiveMotorPWM = true;   motor[motorA] = 0;   nMotorEncoder[motorA] = 0;   nMotorEncoderTarget[motorA] = 0;   StartTask(PDA);   wait1Msec(1000);   while(SensorValue(soundSensor)<80)   {      //nMotorEncoderTarget[motorA] = t;      t = random(360);      wait1Msec(500);   }   StopAllTasks();}

This code implements an absolute position control for motorA. The example sets the motor to a random angle every 500 ms.

You can go to any absolute target encoder value by setting t to that value. There will be no drift due to overshoot or external influences.