View unanswered posts | View active topics It is currently Sat Jul 26, 2014 8:17 am






Reply to topic  [ 2 posts ] 
Motors in RVW ARE NOT perfectly matched 
Author Message
Rookie

Joined: Sat Nov 03, 2012 5:05 pm
Posts: 1
Post Motors in RVW ARE NOT perfectly matched
1st EDIT
So I found someone who asked this same question and here is the response:

Quote:
Re: Does nSyncedMotors Work in Virutal Worlds
"nSyncedMotors" and the other advanced motor commands available in LEGO Mindstorms and TETRIX versions of ROBOTC are not currently implemented.

The good news is that the motors in the virtual world are perfectly matched, removing some of the requirement for using nSyncedMotors.


That sounds great and all, but the motors aren't actually matched. If you run a simple move forward program (included below) at a very low power such as 1, the robot will gradually veer to one side, hence why I wanted to use nSyncedMotors in the first place. When I ran the code below on the metric utility mat the robot veered to the right to the point of half hanging off the table (pictures below).

Code:
task main()
{
  nMotorEncoder[motorC] = 0;
  nMotorEncoder[motorB] = 0;

  while (nMotorEncoder[motorB] < 4092)
  {
    motor[motorC] = 1;
    motor[motorB] = 1;
  }

  motor[motorC] = 0;
  motor[motorB] = 0;
}

PICTURES:
START
Image
END
Image

2nd edit:
Here is some more info. The table shows the gradual difference between the encoder values of motors c and b as the robot gets slower and slower. Values obtained from motor decoder window using same code as above.

Power of Motors:Final Encoder Values(B/C)
100:4096/4096
50:4094/4096
10:4092/4103
1:3091/3183 (At this point the robot fell off the side)

3rd edit:
So I had the idea that maybe since motorC was being activated first in the while loop every time before motorB, the third wheel in the back would gradually angle towards the right. However, even when running code that starts with motorB and then switches the starting order every loop (show below), motorC still always has a higher encoder value, with a more pronounced effect the lower the power.

Code:
task main()
{
  char pulseSide = 'B';
   nMotorEncoder[motorC] = 0;
  nMotorEncoder[motorB] = 0;

  while (nMotorEncoder[motorB] < 4092)
  {
   
     if(pulseSide == 'C') {
        motor[motorC] = 10;
        motor[motorB] = 10;
        pulseSide = 'B';
     }
     else if(pulseSide == 'B') {
          motor[motorB] = 10;
        motor[motorC] = 10;
        pulseSide = 'C';
    }
 
   }

  motor[motorC] = 0;
  motor[motorB] = 0;
}


ORIGINAL QUESTION
So in the Virtual Worlds simulation, the nSyncedMotors and corresponding nSyncedTurnRatio commands don't seem to do anything at all. When the following code (the main() section of the nSyncedMotors example code include with RobotC) is run on the metric measurment utility mat, the robot just turns left, as if the commands weren't doing anything and only the B motor was running.

Code:
task main()
{

  nSyncedMotors = synchBC; //motor B is the master, motor C is the slave
  nSyncedTurnRatio = 100; //motors move at 100% alignment to each other

  motor[motorB] = 30; //turn motor B on, which controls motor C at 30% power
  wait1Msec(2000);  // wait for two seconds

  motor[motorB] = 0;  // turn the motors off.

}


Sat Nov 03, 2012 5:12 pm
Profile
Site Admin
Site Admin

Joined: Thu May 24, 2012 12:15 pm
Posts: 556
Post Re: Motors in RVW ARE NOT perfectly matched
I've been able to test this and confirm that, under very slow speeds, the robot will veer to one side. I've talked to our Virtual Worlds team about this to see why it was doing this, and they've determined that is simply a result of necessary rounding off of values in the Virtual Worlds code. However, when using normal motor values (25 and above), this rounding error is dramatically decreased; the highest difference I saw in the two encoder values (from the very beginning of the table to the very end) was five counts at a motor power level of 25.

Anything less than this is not reliable on a real robot; power levels less than 25 may or may not provide enough current to actually move the motors and in many cases the robot will simply sit in one spot. When looking at the Virtual World code that runs the motor power levels, fixing the low-level rounding accumulated errors would instead ruin the high-motor power calibration. In this case, we wanted to keep the higher motor values as synchronized as possible as they are the values more likely to be used on a real robot.

For a quick fix, simply run the motors at a higher, more realistic value; when the motor power is increased from 25 to a more commonly used level of 50, for example, the error between the two encoders is reduced down to three counts (down from five counts).

Another, more complex option is to use three if statements to check the encoder values of each motor and slightly adjust whichever motor is lagging behind:

Code:
task main()
{
   nMotorEncoder[motorB]=nMotorEncoder[motorC]=0;
   
   while (nMotorEncoder[motorB] <= 4200 && nMotorEncoder[motorC] <= 4200)
   {
      if (nMotorEncoder[motorB] < nMotorEncoder[motorC])
      {
         motor[motorB]=51;
         motor[motorC]=50;
      }

      else if (nMotorEncoder[motorB] > nMotorEncoder[motorC])
      {
         motor[motorB]=50;
         motor[motorC]=51;
      }

      else
      {
         motor[motorB]=50;
         motor[motorC]=50;
      }
   }

   motor[motorB]=0;
   motor[motorC]=0;
   
}


This code clears the encoders, then (while the target encoder count, in this case 4200 is not reached, will continually tweak the two motor values between 50 and 51 depending on which one has a higher encoder count. If both encoder counts are the same, the motors will run in tandem with a power level of 50. Once the target encoder counts have been reached by both motors, they are then turned off and the program ends.

I have used this code with both high-values (99-100) and low values (1-2) and the robot ran to the end of the table without any issues. You can alternatively run this code for a set amount of time by replacing the encoder condition in the while loop with a timer condition:

Code:
task main()
{
   nMotorEncoder[motorB]=nMotorEncoder[motorC]=0;
   
   ClearTimer(T1);
      
   while (time1[T1] < 3000)
   {
      if (nMotorEncoder[motorB] < nMotorEncoder[motorC])
      {
         motor[motorB]=100;
         motor[motorC]=99;
      }

      else if (nMotorEncoder[motorB] > nMotorEncoder[motorC])
      {
         motor[motorB]=99;
         motor[motorC]=100;
      }

      else
      {
         motor[motorB]=100;
         motor[motorC]=100;
      }
   }

   motor[motorB]=0;
   motor[motorC]=0;
   
}


This will do the same thing as the previous code, but will run for 3000 milliseconds (3 seconds) instead of 4200 encoder counts.

_________________
Check out our Blog! And our Facebook page!
Need help? Take a look at our Wiki and our Forums.

I just met you,
And this is crazy,
But here's my code now,
So fix it, maybe?
~ Carly Rae Jepsen parody


Tue Nov 13, 2012 1:17 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 2 posts ] 

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.