Gearing Motors Down Using Easy C4

Okay, so our team has been having trouble with our motors. We have 2 wire- 393 in the back for the two wheels, and we have 2 three wire 292 motors toward the front of the robot. Not directly on the shaft of the wheel due to interference with our intake. We used gears and chain system to turn the front wheels with the motors. ANYWAYS, we are still cutting out after driving about 10-15 min straight. I don’t know if it is due to overheating or not. They are not cool to the touch, but they are not really hot either… So I put a thread out and a lot of people are telling me to gear the motors down so we are not going from zero to blast off all the time. I am using Easy C4 to program. I have tried googling, youtubing, ect to find out how to write a program like that or how ever you word it. Can anyone that uses Easy C4 please help me. We have our first competition on the 18th.

Thank you,
eloveless

“Gearing down” is a mechanical term for lowering the mechanical gear ratio of your robot. This is not something you should try to fix in easyC.

Have you tried looking for any mechanical friction in your drive train? This is typically the culprit.

Is each motor shaft supported by two bearings?

Can you manually rotate the spacers/lock collars on the motor shaft (no binding)?

If you press down on the center of your robot, do the motor shafts and wheels flex inward?

Friction is your enemy, try to reduce it as much as you can.

Sorry to sound dumb, but what do you mean by mechanical friction?
Also, what do you mean by two bearings? I doubt it…
Let me put some pictures on here…
Yes, when pushing down they flex inward. To be honest, I can’t get my fingers between the metal to see if spacers move or not. I doubt they do b/c we have it TIGHT so the wheel doesn’t slide side to side…

Give me a few min and search North Lamar Robotics or Team 4607 and pics will be up.

Thanks.

Surely when you say 10 minutes you mean 10 minutes? If it cuts out after 10 minutes then what are you worrying about? Matches only last 2:20 and have plenty of time for your robot to cool off in between. (Even if you only have 1 minute breaks)

If when you said 10 minutes you were exaggerating then you should check these things:

  • Is your chassis perfectly square or rectangular?
  • Check all shafts that power the drive train for friction (Maybe someone mounted a bearing flat wrong and the shaft rubs against the metal?)
  • check all of your motors

Next time you ask a question please be very specific. It is hard to answer someone who isn’t specific with their problem. Also please search before you post. There are countless “drive train problem” threads.

Dpbailey,

I wasn’t exaggerating… I am serious: 10 minutes. I didn’t know how long we had in between matches because this is our first event. How was I not very specific? I thought people help on here, not criticize. Just asking questions. Thanks for your recommendations.

Regarding programming for reduced motor overheat stress, A forum seach for
linear filtering
shows this discussion.
https://vexforum.com/t/acceleration-linear-flitering/20277/1&highlight=linear+filter

It is a lot more complicated than tank4(,);
But you (or your students!) could learn a lot from reading that example, or the other examples of code in the code forum. Or by searching for code.

Also, what do you mean by two bearings? I doubt it…
The gallery pictures from 2/9 tagged North Lamar
[https://vexforum.com/gallery/showimage.php?i=5581&catid=searchresults&searchid=708319
show a screwhead on each side of each axle, which are a good sign that there are bearing blocks present on the outside.
A bottom view of the drive train might be helpful.

Check all shafts that power the drive train for friction (Maybe someone mounted a bearing flat wrong and the shaft rubs against the metal?)

Sorry to sound dumb, but what do you mean by mechanical friction?

He just explained it with the parenthesis:
Its hard to communicate when we don’t have a common language.
“shaft” is axle, “metal” is vex metal frame supporting the wheel axles.

Experiments with friction.
Take 2 vex metal and stick an axle with a wheel on it between them.
Spin the wheel, listen to the metal clicking as the square axle jumps around in the square vex metal hole. Thats bad.
Twist the metal so that it binds on the axle: Thats worse.
Pinch the metal together so that it grips the wheel: Thats worst.
Add black plastic bearing blocks to hold the axle centered in the metal hole.
Now spin again, its quieter, and spins longer and smoother: thats better.
Squeeze the metal together so that the bearing are pinching the sides of the wheels, but not the tires: thats worse again.
If you take off the motors, and the wheels spin freely and for a long time, thats good; No friction problems.

10-minutes hard driving before cut out is pretty good.
Lots of teams would be happy with that as is.

This picture also shows 5" wheels in the back.
Going back to 4" wheels is the same as mechanically gearing down.

You still have protruding axles, which may put you over the 18" width limit.

Maybe at some point, your students will join the forum.](https://vexforum.com/gallery/showimage.php?i=5581&catid=searchresults&searchid=708319)

Jgraber,

Thank you for breaking it down. I wasn’t trying to be rude, I was just getting frustrated. Yes 10 min of hard driving is what I am getting. I didn’t know how good that was. I didn’t know other teams would consider that good. I understand the matches only last 2:20 sec and then we would get a break… Just don’t want to get there and the motors go out the kids are disappointed. I agree, I need to let the kids on here more. I am still in the learning process being the first year doing such a big competition. I let them on the forums for Best Hub since it was our second year. Next year and later I will let them respond on here. They have done all of the building, I was just worried about the motors… So you think we should go back do the original “middle” wheel size on the back? I can always hacksaw the axle that is sticking out :slight_smile: We were just not getting much traction and I know b/c we are running on slick tile… I have bearing flats (I believed that are called) on at least one side of the axle… Should they be on both sides? If so we can check that… Again, thank you for the help.

I’m going to post some code that answers your question about how to filter the control to the motors so that they do not go from full reverse to full forward. This code is based on the RobotC example I posted here that was referenced in the thread jgraber pointed you at. That example was for an arcade drive and used tasks in RobotC, the closest thing in EasyC is the repeating timer so that’s what I used here. Although I’m going to post some code I don’t think this is the cause of your problems (which if you can drive for 10 mins is probably not critical) but rather think they are caused by mechanical issues having seen the photos you posted. IMHO a combination of different wheel sizes, different gearing between front and back and probably the chassis flexing and causing friction when you turn.

Anyway, here it is with no explanation, it would be implemented as user created C file with these prototypes added to the UserInclude.h file. It uses motor ports 1,2,9 & 10. If it looks a little complicated that is because it is, I really suggest that you save this sort of thing for next season.

Add to UserIncludes.h
void    SetMotorSlewed( int index, int value );
void    SetMotorJ( int index, int value );
int     GetMotorJ( int index );
void    MyTimer(void);
void    MotorSlewRateTask(void);
void    InitMotorSlew(void);
void    CustomTankDrive(void);
#include "Main.h"
#include "stdlib.h"

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  definitiona and variables for the motor slew rate controller.              */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

#define MOTOR_NUM               10
#define MOTOR_MAX_VALUE         127
#define MOTOR_MIN_VALUE         (-127)
#define MOTOR_DEFAULT_SLEW_RATE 10      // Default will cause 375mS from full fwd to rev
#define MOTOR_FAST_SLEW_RATE    256     // essentially off
#define MOTOR_DEADBAND          10

// Array to hold requested speed for the motors
// motors are indexed from 1 in EasyC so add 1 to the array
static int motorReq MOTOR_NUM + 1 ];

// Array to hold "slew rate" for the motors, the maximum change every time the task
// runs checking current motor speed.
static int motorSlew MOTOR_NUM + 1 ];

// Shadow register for values sent to motors (array element 0 not used)
static int currentMotorValue MOTOR_NUM + 1 ];
    
/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Request a new speed for the motor, use this as an alternative to calling   */
/*  SetMotor.  This routine will also limit maximum and minimum speeds.         */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

void
SetMotorSlewed( int index, int value )
{
    int motorValue = value;

    // bounds check index
    if((index < 1) || (index > MOTOR_NUM))
        return;

    // limit value and set into motorReq
    if( motorValue > MOTOR_MAX_VALUE )
        motorReq index ] = MOTOR_MAX_VALUE;
    else
    if( motorValue < MOTOR_MIN_VALUE )
        motorReq index ] = MOTOR_MIN_VALUE;
    else
    if( abs(motorValue) >= MOTOR_DEADBAND )
        motorReq index ] = motorValue;
    else
        motorReq index ] = 0;
}

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Wrapper for SetMotor so we can save the current value                      */

void
SetMotorJ( int index, int value )
{
    // bounds check index
    if( (index<1)||(index>MOTOR_NUM) )
        return;
    
    // Save requested speed
    currentMotorValue[index] = value;

    // Set motor
    SetMotor ( index ,  value ) ;
}

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Get current motor speed                                                    */

int
GetMotorJ( int index )
{
    // bounds check index
    if( (index<1)||(index>MOTOR_NUM) )
        return(0);
    else
        return( currentMotorValue index ] );
}

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Callback that is registered as a repeating timer                           */

#define MYTIMER_TIME    15

void MyTimer()
{
    // Call the motor slew rate function
    MotorSlewRateTask();
}

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Compares the requested speed of each motor to the current speed and        */
/*  increments or decrements to reduce the difference as nexessary             */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

void
MotorSlewRateTask()
{
    int motorIndex;
    int motorTmp;


    // run loop for every motor
    for( motorIndex=1; motorIndex<=MOTOR_NUM; motorIndex++)
        {
        // Get current motor speed
        motorTmp = GetMotorJ( motorIndex );

        // Do we need to change the motor value ?
        if( motorTmp != motorReq[motorIndex] )
            {
            // increasing motor value
            if( motorReq[motorIndex] > motorTmp )
                {
                motorTmp += motorSlew[motorIndex];
                // limit
                if( motorTmp > motorReq[motorIndex] )
                    motorTmp = motorReq[motorIndex];
                }

            // decreasing motor value
            if( motorReq[motorIndex] < motorTmp )
                {
                motorTmp -= motorSlew[motorIndex];
                // limit
                if( motorTmp < motorReq[motorIndex] )
                    motorTmp = motorReq[motorIndex];
                }

            // finally set motor
            SetMotorJ(motorIndex, motorTmp);
            }
        }
}


/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Initialize the motor slew rate code                                        */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

void
InitMotorSlew()
{
    int motorIndex;

    // Initialize stuff
    for(motorIndex=1;motorIndex<=MOTOR_NUM;motorIndex++)
        {
        motorReq[motorIndex] = 0;
        motorSlew[motorIndex] = MOTOR_DEFAULT_SLEW_RATE;
        currentMotorValue[motorIndex] = 0;
        }

    // Init our timer with 25mS repeat
    RegisterRepeatingTimer( MYTIMER_TIME, MyTimer );
}

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Custom 4 motor tank drive using motor slew rate control                    */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

void 
CustomTankDrive()
{
    int joyCh2, joyCh3;

    // Read analog joysticks
    joyCh2 = GetJoystickAnalog( 1 , 2 ) ; 
    joyCh3 = GetJoystickAnalog( 1 , 3 ) ; 

    // Tank drive
    // one or the other of these may need reversing
    // for example to reverse left drive
    //
    // SetMotorSlewed(  1, -joyCh3 );
    // SetMotorSlewed(  2, -joyCh3 );

    // Left
    SetMotorSlewed(  1, joyCh3 );
    SetMotorSlewed(  2, joyCh3 );

    // Right
    SetMotorSlewed(  9, joyCh2 );
    SetMotorSlewed( 10, joyCh2 );
}

You would call this from operator control as follows.

https://vexforum.com/attachment.php?attachmentid=5299&stc=1&d=1328853616
EasyCTankCode.jpg

if you can run for 10 minutes at full power before you stall you are in good shape. Normally my team will run for 5 minutes with everything running to do our testing. Dont worry too much about it.

Hey jpearman,

I was trying this code out to see if it will help in our chain driven drive which causes sometimes slippage when the drives yanks it from full forward to full reverse.

I put the code in an when I run it I get no errors but I cannot drive the motors. The motors I’m trying to drive are ports 4 and 8 on the left side of the tank and 5 and 9 on the right side of the tank.

So based on that I’m using your code with my drive numbers, right?


SetMotorSlewed ( 4 , joyCh3 ) ;
SetMotorSlewed ( 8 , joyCh3 ) ;

SetMotorSlewed ( 5 , joyCh2 ) ;
SetMotorSlewed ( 9 , joyCh2 ) ;

I’m getting values from the joystick because I’m dumping those to the LCD - so the values change as I move the joystick but no output to the drives.

Any ideas on what I might be doing wrong here? I didn’t change any of the other lines of code, but perhaps I should?

I’m calling CustomTankDrive ( ) and I know it gets that far because thats where the code is I’m getting the values from the joystick and writing them to the LCD.

That function calls SetMotorSlewed ( ) but then I’m having trouble following the program logic after that. I cannot see how the other functions get called from there?

Any ideas would be most helpful! Thanks!

Did you initialize correctly by calling InitMotorSlew() at the top of operator control ?

Doh! No, I didn’t… feeling a little sheepish now… thank you so much. Working now - on to further development!

Hey,

Working really good. Question for you. Our driver would rather have arcade mode though. Usually our programmer uses the built in Arcade function in EasyC but I don’t think we can use that and call the Slew function from it.

So, my question is how would we program a 4 motor arcade mode using channel 4 to turn left and right and channel 3 to go forward and back and still be able to call the SetMotorSlewed like with tank drive?

I’ve searched around for it with them but no luck. Any help would be appreciated. Thanks!!

I have not used this function before but from what I see when you call the function slew
use
SetMotorSlewed ( 4 , joyCh3+joyCh4 ) ;
SetMotorSlewed ( 4 , joyCh3-joyCh4 ) ;

Like you would if you were doing a standard arcade drive.

Tabor is basically correct, this was a function I wrote that simulated the Arcade2 function, I updated it to use the slewed control, it came from this post.

https://vexforum.com/showpost.php?p=326323&postcount=26

If you are using 4 motors then they need to be added in but the concept is the same.

void New_Arcade2(unsigned char ucJoystick,
                unsigned char ucMoveChannel, unsigned char ucRotateChannel,
                unsigned char ucLeftMotor, unsigned char ucRightMotor,
                unsigned char ucLeftInvert, unsigned char ucRightInvert)
{
    long drive_l_motor;
    long drive_r_motor;
    int forward, turn;

    // get joystick values
    forward = GetJoystickAnalog( ucJoystick , ucMoveChannel );
    turn    = GetJoystickAnalog( ucJoystick , ucRotateChannel );
    
    // Set drive
    drive_l_motor = (forward + turn);
    drive_r_motor = (forward - turn);

    // normalize drive so max is 127 if any drive is over 127
    int max = Abs(drive_l_motor);
    if (Abs(drive_r_motor)  > max)
        max = Abs(drive_r_motor);
    if (max>127) {
        drive_l_motor = 127 * drive_l_motor / max;
        drive_r_motor = 127 * drive_r_motor / max;
    }

    // Invert if necessary
    if( ucLeftInvert )
        drive_l_motor = -drive_l_motor;
    if( ucRightInvert )
        drive_r_motor = -drive_r_motor;

    // set motors
    SetMotorSlewed ( ucLeftMotor ,  drive_l_motor ); 
    SetMotorSlewed ( ucRightMotor , drive_r_motor ); 
}