Help with quad encoder controlled speed correction

I’d like to use two optical shafts (one on a left wheel and one on a right) to dynamically alter the speeds of the wheels so they spin at the same rate. As you can see in the attached easyC code, the method I tried was to compare the values of each encoder and slow down the motor which corresponded to the higher quad shaft value. This was supposed to slow down the faster motor repeatedly until the speed of this motor balanced with the other.
I was aware that there was a possibility for the motor which was originally faster to slow down beyond the other motor, thus causing the originally slower motor to slow down. I was worried this cycle would repeat until both values were near 127, so I added the motor function to bring the slower motor back up to full.
I received several different erroneous results after executing the program. The first was motor 2 returning a value of -1 (which caused motor 2 not to turn at all) while motor 1 began at maximum speed and quickly dropped down to a stop.
After some manipulation I managed to get both motors returning values of -1 (at least it was consistent :mad:).
After changing more I managed to get both motors spinning at full speed, then switching direction for a few milliseconds, then switching back. This switching alternated on each motor 180 degrees out of phase. They kept perfect time with each other, but failed to show any sort of speed control.
After further manipulation I got both motors to switch at the same time, but they switched four times each cycle.
I gave up at this point due to pure frustration. I wish I had saved the different stages of this code, but all I have is the original. I would really like to know the correct way to do this. Someone please help.
Dynamic Speed Correction.zip (2.08 KB)

**Unfortunately we can not help with Code questions. I have moved your question to the easyC Section. They should be able to provide some pointers. You should also post your question were the Vex Community can answer – they may have a solution for you. **

Your best bet is to create a proportional loop to control the speed. Use a timer at a 20ms update rate and calculate ticks per period. Use some gearing / chain and run the encoder at greater ratio then the motor output/wheel output, just keep the encoder from spinning at more then 1000rpm at full speed. Then use a Proportional loop to control the speed.

Output_to_Motor = Gain*(Target_Speed - Actual_Speed);
example:


void main ( void )
{
      int Encoder = 0; 
      int TargetSpeed = 90; 
      int Output = 0; 
      int Timer = 0; 
      int Gain = 1; 

      // Code Assumes a 2:1 ratio 
      // Quad Encoder Plugged into Interrupt: 1 and Digital: 5 
      // Motor on Port 1 
      StartQuadEncoder ( 1 , 5 , 0 ) ; //If Motor Runs Away from Target Invert Direction

      while ( 1 )
      {
            Wait ( 20 ) ;
            Encoder = GetQuadEncoder ( 1 , 5 ) ;
            PresetQuadEncoder ( 1 , 5 , 0) ;
            Output = Gain*(TargetSpeed - Encoder)  ;
            if ( Output > 127 )
            {
                  Output = 127 ;
            }
            if ( Output < -127 )
            {
                  Output = -127 ;
            }
            SetMotor ( 1 , Output + 127 ) ;
      }
}

This should get you close, if you want to get tighter control then ask Google about velocity PID.

this makes a lot of sense. thanks for your help. id like to break down a few things about this tho.
first of all, why a target speed of 90 and a gain of 1?
what differences would there be if we were to assume a 4:1 ratio instead of 2:1?
if i don’t want to suspend my loop with a wait time (if im waiting for another type of feedback that i dont want to miss) could i use a counter and place the output assignment in an if statement that only executed every 50 cycles of the loop? like this:

int Encoder = 0;
int TargetSpeed = 90;
int Output = 0;
int Gain = 1;
int count = 1;

StartQuadEncoder ( 1 , 5 , 0 ) ;

while ( 1 ) {
Encoder = GetQuadEncoder ( 1 , 5 ) ;
if ( count%50 == 0 ) {
Output = Gain*(TargetSpeed - Encoder) ;
if ( Output > 127 ) {
Output = 127 ;
}
if ( Output < -127 ) {
Output = -127 ;
}
PresetQuadEncoder ( 1 , 5 , 0) ;
}
SetMotor ( 1 , Output + 127 ) ;
count++ ;
}

As long as your loop time in consistent you should be ok. You should note the motors only update every 20ms so updating them any faster you are just spinning your wheels so to speak.

You can also use a timer and say:

StartTimer(1);

while {

if (GetTimer(1) >= 20ms)
enc = GetEnco
ResetEnco
ResetTimer

}

Going 4:1 would just add more resolution, and just make your target values larger. Which would be a good thing in my book, if you ask me if you can keep the encoders spinning around 800rpm when the motor is running at full speed that’s the best. It’s also very important that you support both sides of the encoder shaft as it has no internal bearings to support the disk itself.