ROBOTC.net forums
http://robotc.net/forums/

Issues regarding the vex quadrature encoder
http://robotc.net/forums/viewtopic.php?f=11&t=11003
Page 1 of 1

Author:  goneaswind [ Mon Apr 27, 2015 12:00 pm ]
Post subject:  Issues regarding the vex quadrature encoder

I am using the quadrature encoder to measure the distance my robot drive, so I defined a function to translate the metric distance to encoder counts. I used robotC debugger to see how the encoder sensor ticks change when I pushes the robot, and write down the corresponding encoder ticks to metric distances, and use these tuples to calculate the proportion.

But here comes the issue. I used the calculated proportion to write an autonomous program to drive my robot some distance, say 30 centimeters; the calculated proportion is 10.67, so it is about 320 encoder ticks. But when the program reaches the target encoder tick, the robot will always drive several centimeters more, about 34 cm rather than 30. I also used the debugger to check the sensor value, and when the robot stops, the reported encoder value is around 320, not more than 325, which means the metric distance error should not exceed 1 cm. So where does this error come from?

The more weired issue is when I use the same proportion to drive the robot backward, say -30 cm, which means -320 encoder ticks. In this case, when the program reaches the target encoder tick, the metric distance error will not exceed 1 cm. Why does the quadrature encoder has different performance in the different directions??

My robot's sensor configuration is as follows, the 'base_quad' is the one I am using to measure distance. I plugged two quad encoders and made them one port (port 4) separated on purpose, because when I plug them in port 2, 3 and 4, 5, the first one will only return -1, 1 or 0 values. Is this a bug of robotC or the VEX cortex?

Code:
#pragma config(Sensor, dgtl1,  bumper,         sensorTouch)
#pragma config(Sensor, dgtl2,  base_quad,      sensorQuadEncoder)
#pragma config(Sensor, dgtl5,  lift_quad,      sensorQuadEncoder)
#pragma config(Sensor, dgtl7,  jump7,          sensorDigitalIn)
#pragma config(Sensor, dgtl8,  jump8,          sensorDigitalIn)
#pragma config(Sensor, dgtl9,  arm_pump,       sensorDigitalOut)
#pragma config(Sensor, dgtl10, gripper_pump,   sensorDigitalOut)
#pragma config(Sensor, dgtl11, cube_pump,      sensorDigitalOut)


I have been stuck here for several days, I really appreciate if anyone can answer my questions or point me somewhere I can look for.

Author:  CARBOT [ Mon Apr 27, 2015 10:30 pm ]
Post subject:  Re: Issues regarding the vex quadrature encoder

Please post your entire code. You may have issues with an INTeger variable truncating the decimal and need a FLOATing point variable instead.

Author:  goneaswind [ Mon Apr 27, 2015 10:47 pm ]
Post subject:  Re: Issues regarding the vex quadrature encoder

CARBOT wrote:
Please post your entire code. You may have issues with an INTeger variable truncating the decimal and need a FLOATing point variable instead.


Thanks for your reply, but could you please explain it a bit more? As far as I know the SensorValue[] returns type 'short', where do I need floating point variable?

Author:  JohnWatson [ Tue Apr 28, 2015 12:56 pm ]
Post subject:  Re: Issues regarding the vex quadrature encoder

On top of what Carbot has said; the issue you may be encountering is commonly caused by the robot "drifting" past its target value. Essentially, when you tell the robot to go from a full-speed movement to a dead stop, the motor may continue to 'drift' past the target point. This drift is a fairly common issue and is affected by several factors, including the weight of the robot, weight distribution, speed of the motors, type of wheels being used, the drivetrain, the surface the robot is being run on, etc.

A good analogy for this is driving a car at 20 mph until the front bumper reaches a stop sign, then slamming on the brakes. Even though you've technically told the car to 'stop' exactly at the stop sign, the car will most likely keep sliding/moving past the target point. The faster you are moving (or the more inerta the car has), the further it will 'drift' past the stop sign.

A good way to test this is to record the encoder values of the same movement with the robot on different surfaces and free spinning with the wheels off the ground.

Author:  goneaswind [ Wed Apr 29, 2015 2:49 am ]
Post subject:  Re: Issues regarding the vex quadrature encoder

JohnWatson wrote:
On top of what Carbot has said; the issue you may be encountering is commonly caused by the robot "drifting" past its target value. Essentially, when you tell the robot to go from a full-speed movement to a dead stop, the motor may continue to 'drift' past the target point. This drift is a fairly common issue and is affected by several factors, including the weight of the robot, weight distribution, speed of the motors, type of wheels being used, the drivetrain, the surface the robot is being run on, etc.

A good analogy for this is driving a car at 20 mph until the front bumper reaches a stop sign, then slamming on the brakes. Even though you've technically told the car to 'stop' exactly at the stop sign, the car will most likely keep sliding/moving past the target point. The faster you are moving (or the more inerta the car has), the further it will 'drift' past the stop sign.

A good way to test this is to record the encoder values of the same movement with the robot on different surfaces and free spinning with the wheels off the ground.


Thanks for your reply, of course I know the "drifting" issue, but it's not the problem here. In fact, what I was doing was recording the encoder values through two ways: 1) manually push the robot and 2) remote control using joystick. In both ways the encoder would give about 320 ticks for 30 cm distance. But when I use the auto program to drive the robot the same distance (using the measure of 320 ticks for 30 cm), when the robot *completely* stops, the encoder value shows it's around 320 ticks (not more than 10 ticks error), but the actual distance error could be 3 to 4 cm, which is not as expected.

EDIT: A possible reason could be the motor exceeds the maximum rotating speed of quadrature encoder's limit, in which case the robot drives more ticks but the encoder can not record them properly. I measured the time and ticks in the auto program, and the calculated revolutions per second is at most 13-14, could this be the reason? I tried a smaller value for motor speed and the error also reduced.

Author:  JohnWatson [ Wed Apr 29, 2015 4:21 pm ]
Post subject:  Re: Issues regarding the vex quadrature encoder

We will need to see the program to debug it; if drifting has been accounted for, then the problem may be with how the program is using/accessing the encoder values, how the motors are being run and stopped, etc. Please post the code using the [code] tags, if possible, and we will be more than happy to take a look at it for you.

Author:  goneaswind [ Thu Apr 30, 2015 2:21 am ]
Post subject:  Re: Issues regarding the vex quadrature encoder

JohnWatson wrote:
We will need to see the program to debug it; if drifting has been accounted for, then the problem may be with how the program is using/accessing the encoder values, how the motors are being run and stopped, etc. Please post the code using the code tags, if possible, and we will be more than happy to take a look at it for you.


Thanks for your promote reply, as I encountered this problem when I was debugging PID control so the original program is a bit long, I would paste the experimental code below where I can reproduce the error.

Here are the steps to reproduce the error. I put a measure tape beside the robot to measure the metric distance the robot moves, all the values are recorded when the robot was completely stopped. As I mentioned before I used two ways of both manually pushing & joystick controlling to record the encoder values (in the debugger in robotC). The calculated proportion of encoder ticks to metric distance in centimeters is about 10.6, which is 530 ticks for 50 cm. I used the code below to run the robot for multiple times for a certain speed, which is set in variable 's_drive_spd'. I set the speed to 127(full speed of), 80, 50, respectively. And here are the results I got.

Speed = 127:
drive(50) ----> LAST error (-32, -11), actual distance of about 57 cm
drive(-50) ----> LAST error (33, 53), actual distance of about -(57-6) cm

Speed = 80:
drive(50) ----> LAST error (-24, 7), actual distance of about 53 cm
drive(50) ----> LAST error (30, 28), actual distance of about -(53-2) cm

Speed = 50:
drive(50) ----> LAST error (10, 7), actual distance of about 49 cm
drive(50) ----> LAST error (-10, -4), actual distance of about -(49-0) cm

Note: the 'LAST error (left_encoder_stop_err, right_encoder_stop_err)' is an average from three independent runs.

As you can see, when I set the speed a higher value, the more error encoder would produce.

Code:
#pragma config(Sensor, in8,    gyro,           sensorGyro)
#pragma config(Sensor, dgtl1,  base_quad_r,    sensorQuadEncoder)
#pragma config(Sensor, dgtl3,  jump7,          sensorDigitalIn)
#pragma config(Sensor, dgtl4,  jump8,          sensorDigitalIn)
#pragma config(Sensor, dgtl5,  lift_quad,      sensorQuadEncoder)
#pragma config(Sensor, dgtl7,  base_quad_l,    sensorQuadEncoder)
#pragma config(Sensor, dgtl9,  arm_pump,       sensorDigitalOut)
#pragma config(Sensor, dgtl10, gripper_pump,   sensorDigitalOut)
#pragma config(Sensor, dgtl11, cube_pump,      sensorDigitalOut)
#pragma config(Motor,  port1,           frontLeftMotor, tmotorVex393HighSpeed_HBridge, openLoop, driveLeft)
#pragma config(Motor,  port2,           backLeftMotor, tmotorVex393HighSpeed_MC29, openLoop, driveLeft)
#pragma config(Motor,  port3,           lift1,         tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port4,           lift2,         tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port5,           lift3,         tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port6,           lift4,         tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port7,           lift5,         tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port8,           lift6,         tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port9,           frontRightMotor, tmotorVex393HighSpeed_MC29, openLoop, reversed, driveRight)
#pragma config(Motor,  port10,          backRightMotor, tmotorVex393HighSpeed_HBridge, openLoop, reversed, driveRight)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

void setTurnSpeed2(int left, int right)
{
   motor[frontLeftMotor] = left;
   motor[backLeftMotor]  = left;
   motor[frontRightMotor] = right;
   motor[backRightMotor]  = right;
}

void drive(int dist_cm)
{
   static int s_error_thres = 40;
   static int s_drive_spd = 50;
   float set_point = dist_cm * 10.6;
   SensorValue[base_quad_l] = 0;
   SensorValue[base_quad_r] = 0;
   float errorl = set_point - SensorValue[base_quad_l];
   float errorr = set_point - SensorValue[base_quad_r];
   float error_avg = (errorl + errorr) / 2;
   float drive_spd = error_avg >0? s_drive_spd:-s_drive_spd;
   setDriveSpeed(drive_spd);
   while (true)
   {
      float l_spd = drive_spd, r_spd = drive_spd;
      if (abs(errorl - errorr) > 10)
      {
       if (errorl > errorr)
          l_spd += 10;
       else
          r_spd += 10;
      }
      setTurnSpeed2(l_spd, r_spd);
      if (abs(error_avg) < s_error_thres)
      {
         // brake
         setDriveSpeed(set_point>0? -10:10);
         writeDebugStream("===> Drive MID error[%d,%d], set point[%.2f]\n", set_point - SensorValue[base_quad_l], set_point - SensorValue[base_quad_r], set_point);
         break;
      }
      writeDebugStreamLine("Drive in progress: error[%.2f,%.2f], speed[%.2f,%.2f]", errorl, errorr, l_spd, r_spd);
      wait1Msec(20);
      errorl = set_point - SensorValue[base_quad_l];
      errorr = set_point - SensorValue[base_quad_r];
      error_avg = (errorl + errorr) / 2;
   }
   wait1Msec(300);
   stopDriveMotors();
   writeDebugStreamLine("===> Drive LAST error[%d,%d], set point[%.2f]\n", set_point - SensorValue[base_quad_l], set_point - SensorValue[base_quad_r], set_point);
}

#define LEN(array) sizeof(array)/sizeof(array[0])

void testBase()
{
   clearDebugStream();
   int dists[] = {50, -50, 50, -50, 50, -50, 80, -80, 100, -100};
   for (unsigned int i = 0; i < LEN(dists); ++i)
   {
      while (true)
         if (vexRT[Btn7U] == 1)
            break;
      writeDebugStreamLine("Drive dist [%d]", dists[i]);
      drive(dists[i]);
      //driveQuadPid(dists[i]);
      wait1Msec(500);
   }
}


Page 1 of 1 All times are UTC - 5 hours [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/