Optical shaft encoder while loop frequency

We are using two optical shaft encoders to make our robot drive straight, and we did this by adjusting one wheel to the other in a master-slave setup. We have been having issues with the while loop not running fast enough… we think. Everytime we run our robot and try to have the right encoder adjust to the left encoder to move in a straight line, it takes much longer than we think it should. It impacts the robot’s ability to drive in a straight line, and its veering off course, taking too long to adjust from the previous data. Is there a way to change the frequency of the while loop, or is there something else wrong with our code?

{
  float Lencoder = LeftEnc.rotation(rotationUnits::deg);
  float Rencoder = RightEnc.rotation(rotationUnits::deg);
  float Lvel = 50;
  float Rvel = 50;
  float whileCounter = 0;
 while (1)
 {
   whileCounter = whileCounter + 1;
    Lencoder = LeftEnc.rotation(rotationUnits::deg);
    Rencoder = RightEnc.rotation(rotationUnits::deg);
    Controller1.Screen.clearScreen();
    Controller1.Screen.setCursor(1, 1);
    Controller1.Screen.print("LVe = %3.0f" ,Lencoder);
    Controller1.Screen.setCursor(2, 1);
    Controller1.Screen.print("RVe = %3.0f" ,Rencoder);
    Controller1.Screen.setCursor(3, 1);
    Controller1.Screen.print("LV = %3.0f" ,Lvel);
    Controller1.Screen.setCursor(3, 11);
    Controller1.Screen.print("RV = %3.0f" ,Rvel);
    Controller1.Screen.setCursor(1, 14);
    Controller1.Screen.print("%3.0f" ,whileCounter);
    if(Rencoder > Lencoder)
    {
      Rvel = Rvel - 1;
    }
    if (Rencoder < Lencoder)
    {
      Rvel = Rvel + 1;
    }
     LeftMotors.spin(vex::directionType::fwd, Lvel, vex::velocityUnits::pct);
     RightMotors.spin(vex::directionType::fwd, Rvel, vex::velocityUnits::pct);
  }
}

Welcome to the world of real-time programming. As far as I can tell, your loop repeats itself immediately, which is part of the problem. You are not giving both the motors and the encoders time to actually move and detect movement. Typically, one would put a delay of 20 milliseconds at the end of the loop. Without this delay, you are also likely saturating the communication channel from the Brain to the Controller with the Screen.print statements. I believe the Brain buffers this, ensuring that data is sent no more frequently than once every 50 milliseconds to the Controller. You’re better off if you restrict this data rate yourself.

There are several other potential issues with the code; hopefully the printed statements give you hints as far as where these are. Take the printout and walk thru the code and think about what effects your code will have. It’s often hard to imagine what realworld values sensors will actually return when one starts programming. What you have is a reasonable start, but will need to change to make it work the way I think you want it to work. Keep at it!

3 Likes

Unless I am mistaken, I don’t believe this is VEXCode VR as you are writing code in a world that is not perfect in mathematics, alongside VEXCode VR robots do not have a controller screen to print to. That being said, I believe this is likely “VEXCode V5 Pro Support” category instead. As for your code, please surround it with [code] and [/code] to have a better presentation of it:

{
float Lencoder = LeftEnc.rotation(rotationUnits::deg);
float Rencoder = RightEnc.rotation(rotationUnits::deg);
float Lvel = 50;
float Rvel = 50;
float whileCounter = 0;
while (1)
{
whileCounter = whileCounter + 1;
Lencoder = LeftEnc.rotation(rotationUnits::deg);
Rencoder = RightEnc.rotation(rotationUnits::deg);
Controller1.Screen.clearScreen();
Controller1.Screen.setCursor(1, 1);
Controller1.Screen.print(“LVe = %3.0f” ,Lencoder);
Controller1.Screen.setCursor(2, 1);
Controller1.Screen.print(“RVe = %3.0f” ,Rencoder);
Controller1.Screen.setCursor(3, 1);
Controller1.Screen.print(“LV = %3.0f” ,Lvel);
Controller1.Screen.setCursor(3, 11);
Controller1.Screen.print(“RV = %3.0f” ,Rvel);
Controller1.Screen.setCursor(1, 14);
Controller1.Screen.print("%3.0f" ,whileCounter);
if(Rencoder > Lencoder)
{
Rvel = Rvel - 1;
}
if (Rencoder < Lencoder)
{
Rvel = Rvel + 1;
}
LeftMotors.spin(vex::directionType::fwd, Lvel, vex::velocityUnits::pct);
RightMotors.spin(vex::directionType::fwd, Rvel, vex::velocityUnits::pct);
}
}

Looking at your code, as what @Mentor_355U said, you should have a wait statement (I would advise roughly 20 miliseconds) to give the V5 Brain room to breathe (and also reduce crashing).

As per your controller, I believe there’s a chance where the print function is a yield function where your code will temporarily pause to complete the function of printing to the screen. It may be a good idea to try it without all the controller prints and see if that makes a difference.

As for your streightening code, I believe it is nearly impossible to straighten your robot with code with the V5 system unless you know odometry and pure pursuit (and this is where things would become complicated, far more complicated than the simplest solution). The simplest solution would be to fix the friction on your drivetrain. Although you have bearing flats most likely, there’s a good chance that some of the following would be a possibility:

  1. Your bearing flats may have a hole too small (due to being used on more than one robot) causing extra friction for the drive on one side of the robot
  2. Your bearing flats are not aligned. Since bearing flats are a very rubbery plastic they will never be aligned properly as time continues. I would advise drilling a slightly larger hole onto the C-Channels that the axles go through to ensure metal-on-metal never happens.

Making sure your wheels spin with negligible friction can drastically reduce drivetrain veering to a point where you will never feel like you need to compensate in any way in code (which honestly should be a better alternative).

1 Like

One other suggestion would be to keep the robot plugged into the computer as you run your program. I forget the syntax, but there’s a way to print to the debug stream rather than the controller. This would let you copy the output and put it into something like Excel. Add the loop iteration count if you do this, and plot out the values of the encoder. Sometimes visualizing the data can shed light on the problem; the old RobotC did a great job of this.

3 Likes

I think printf and std::cout will both work for that.

https://www.cplusplus.com/reference/iostream/cout/

(I would assume any other way to get stuff to stdout would work as well)

Works over VEXnet if you connect the controller to your computer too.

5 Likes