Motor Outrage

Hi Peeps,
One of my friend’s (whose account is not getting certified) team needs help. Their wheel motors move without any commands being given to them. (Commands are there but only when you move joysticks) This is the code:

*#pragma config(I2C_Usage, I2C1, i2cSensors)

#pragma config(Sensor, I2C_1, , sensorQuadEncoderOnI2CPort, , AutoAssign )

#pragma config(Sensor, I2C_2, , sensorQuadEncoderOnI2CPort, , AutoAssign )

#pragma config(Sensor, I2C_3, , sensorQuadEncoderOnI2CPort, , AutoAssign )

#pragma config(Motor, port1, LeftgoalMtr, tmotorVex393_HBridge, openLoop)

#pragma config(Motor, port3, ArmMtrLeft, tmotorVex393_MC29, openLoop)

#pragma config(Motor, port4, ClawMtr, tmotorVex393_MC29, openLoop)

#pragma config(Motor, port5, ArmMtrRight, tmotorVex393_MC29, openLoop)

#pragma config(Motor, port6, RightbackMtr, tmotorVex393_MC29, PIDControl, encoderPort, I2C_3)

#pragma config(Motor, port8, RightfrontMtr, tmotorVex393_MC29, PIDControl, reversed, encoderPort, I2C_2)

#pragma config(Motor, port9, LeftfrontMtr, tmotorVex393_MC29, PIDControl, encoderPort, I2C_1)

#pragma config(Motor, port10, RightgoalMtr, tmotorVex393_HBridge, openLoop, reversed)

//!!Code automatically generated by ‘ROBOTC’ configuration wizard !!//

/---------------------------------------------------------------------------/

/* */

/* Description: Competition template for VEX EDR */

/* */

/---------------------------------------------------------------------------/

// This code is for the VEX cortex platform

#pragma platform(VEX2)

// Select Download method as “competition”

#pragma competitionControl(Competition)

#pragma autonomousDuration(20)

#pragma userControlDuration(60)

//Main competition background code…do not modify!

#include “Vex_Competition_Includes.c”

/---------------------------------------------------------------------------/

/* Pre-Autonomous Functions */

/* */

/* You may want to perform some actions before the competition starts. */

/* Do them in the following function. You must return from this function */

/* or the autonomous and usercontrol tasks will not be started. This */

/* function is only called once after the cortex has been powered on and */

/* not every time that the robot is disabled. */

/---------------------------------------------------------------------------/

void pre_auton()

{

// Set bStopTasksBetweenModes to false if you want to keep user created tasks

// running between Autonomous and Driver controlled modes. You will need to

// manage all user created tasks if set to false.

bStopTasksBetweenModes = true;

// Set bDisplayCompetitionStatusOnLcd to false if you don't want the LCD

// used by the competition include file, for example, you might want

// to display your team name on the LCD in this function.

// bDisplayCompetitionStatusOnLcd = false;




// All activities that occur before the competition starts

// Example: clearing encoders, setting servo positions, ...

}

/---------------------------------------------------------------------------/

/* */

/* Autonomous Task */

/* */

/* This task is used to control your robot during the autonomous phase of */

/* a VEX Competition. */

/* */

/* You must modify the code to add your own robot specific commands here. */

/---------------------------------------------------------------------------/

void waitforencoders()

{

	waitUntilMotorStop(LeftfrontMtr);

	waitUntilMotorStop(RightfrontMtr);

	waitUntilMotorStop(RightbackMtr);

}

void resetencoder()

{

resetMotorEncoder(RightbackMtr);

resetMotorEncoder(LeftfrontMtr);

resetMotorEncoder(RightfrontMtr);

}

task autonomous()

{

	resetencoder();




	setMotorTarget(LeftfrontMtr, nEncoderCountTarget, 127, true);

	setMotorTarget(RightfrontMtr, nEncoderCountTarget, 127, true);

	setMotorTarget(RightbackMtr, nEncoderCountTarget, 127, true);




	waitforencoders();




	resetencoder();




	motor(RightgoalMtr) = 127;

	motor(LeftgoalMtr) = 127;

	wait10Msec(700);




	setMotorTarget(LeftfrontMtr, nEncoderCountTarget, -127, true);

	setMotorTarget(RightfrontMtr, nEncoderCountTarget, 127, true);

	setMotorTarget(RightbackMtr, nEncoderCountTarget, 127, true);

	

// ..........................................................................

// Insert user code here.   1.84 rotation from start to goal

// ..........................................................................

}

/---------------------------------------------------------------------------/

/* */

/* User Control Task */

/* */

/* This task is used to control your robot during the user control phase of */

/* a VEX Competition. */

/* */

/* You must modify the code to add your own robot specific commands here. */

/---------------------------------------------------------------------------/

task usercontrol()

{

// User control code here, inside the loop




while (true)

{




	resetencoder();

	

	motor(RightbackMtr) = vexRT[Ch2];

	motor(RightfrontMtr) = vexRT(Ch2);




	motor(LeftfrontMtr) = vexRT[Ch3];







	if (vexRT[Btn6U] == 1)

	{

		motor(ArmMtrLeft) = 80;

		motor(ArmMtrRight) = 80;

	}

	else if (vexRT[Btn6D] == 1)

	{

		motor(ArmMtrLeft) = -80;

		motor(ArmMtrRight) = -80;

	}

	else

	{

		motor(ArmMtrLeft) = 0;

		motor(ArmMtrRight) = 0;

	}




	if (vexRT[Btn5U] == 1)

	{

		motor(LeftgoalMtr) = 20; //This speed will change as it is the speed of the mobile goal holder move.

		motor(RightgoalMtr) = 20; //Same here.

	}

	else if (vexRT[Btn5U] == 0)

	{

		motor(LeftgoalMtr) = 0;

		motor(RightgoalMtr) = 0;

	}




	if (vexRT[Btn5D] == 1)

	{

		motor(LeftgoalMtr) = -20;

		motor(RightgoalMtr) = -20;

	}

	else if (vexRT[Btn5D] == 0)

	{

		motor(LeftgoalMtr) = 0;

		motor(RightgoalMtr) = 0;

	}




	if (vexRT[Btn7R] == 1)

	{

		motor(ClawMtr) = 25;

		wait1Msec(600);

		motor(ClawMtr) = 0;

	}

	else if(vexRT[Btn7L] == 1)

	{

		motor(ClawMtr) = -25;

		wait1Msec(600);

		motor(ClawMtr) = 0;

	}
}

*}

Please Respond if you know how to help, and feel free to ask questions about any further things that you need to know to help us.

THANK YOU!!!

Check if you have a faulty motor controller, because sometimes if the wire is broken, it can cause it to run even when its not supposed to be powered.

How much do they move? Crawl or run full speed?
For unexpected crawl (robot drift), the issue might be the joystick not perfectly centered, which we usually solve by using a deadband - if the absolute value of a joystick channel is less than, say, 20, treat it as zero.

A couple thoughts:

  1. What @nenik said. If it’s a slow crawl, it may well be the joysticks not actually sending 0s.

  2. Are motor controllers being used? Or were 2-wire motors plugged straight into 3-wire ports on the cortex?

Ports 1 and 10 work fine for a drivetrain. They do not inherently drive themselves.

The issue is likely code or poorly calibrated joysticks, although the code looks good to me, apart from a motor that seems to be missing. Other people may find more errors. As @nenik said, more details about the driving are needed.

In general, because joysticks tend to be a little annoying, you’ll want to deadband input to around 15-20 PWM, depending on your controller, so you only act on real instructions. For example, instead of:


motor[drive] = vexRT[Ch1];

Try:


if (abs(vexRT[Ch1]) > 20) {
motors[drive] = vexRT[Ch1]
}

They asked if the team plugged 2 wire motor directly into 3 wire port. That will cause the behavior of running full speed whenever the cortex is on.

You motors have been doing this wierd behavior because the motor needs a motor controller. If that doesnt work check ur code.

I’d put big money on the IMEs as the source of your friend’s problem. We had no end of random problems last year, including what you’re describing (referred to as “ghosting”). In one of our competitions, in the middle of driver control the robot just started strafing across the field by itself, with all joystick control lost. That lasted for a few seconds (on that occasion) and then it returned to normal.

I wrote a long article about what’s going on and what manner of nuisances can/will occur with integrated motor encoders (the I2C port stuff). Even if your program is not using the sensor data from the IMEs, they can still cause all the problems described in the article; just being plugged in is the source of the problem. When we removed them from our robot, our problems stopped.
Why I’ll Never Use IMEs Again

This is probably not good news, as it’s late in the season and your friend’s robot is already built, and they probably don’t have a way to switch to optical shaft encoders. However, the article linked above has some suggestions on how to make the best of it if they are stuck with IMEs.

Turn off PID control for those motors, not very useful when you are trying to drive the robot.

If you want to turn off PID from code use


nMotorPIDSpeedCtrl RightbackMtr ] = RegIdle;

etc.

Another problem that my friend is facing is that his MOGO motors aren’t moving. It’s probably the code’s fault. Here’s the code:

         *   if (vexRT[Btn5U] == 1)
	{
		motor(LeftgoalMtr) = 127; //This speed will change as it is the speed of the mobile goal holder move.
		motor(RightgoalMtr) = 127; //Same here.
		
	}
	else
	{
		motor(LeftgoalMtr) = 0;
		motor(RightgoalMtr) = 0;
	}

	if (vexRT[Btn5D] == 1)
	{
		motor(LeftgoalMtr) = -127;
		motor(RightgoalMtr) = -127;
		
	}
	else
	{
		motor(LeftgoalMtr) = 0;
		motor(RightgoalMtr) = 0;
	}

Thanks

Here lies one problem:

if (vexRT[Btn5U] == 1) {
   motor(LeftgoalMtr) = 127; 
   motor(RightgoalMtr) = 127;
}
else {
   motor(LeftgoalMtr) = 0;
   motor(RightgoalMtr) = 0;
}

if (vexRT[Btn5D] == 1) {
   motor(LeftgoalMtr) = -127;
   motor(RightgoalMtr) = -127;
}
else {
   motor(LeftgoalMtr) = 0;
   motor(RightgoalMtr) = 0;
}

What’s happening here is:

  • press 5U
  • first if-statement true; turns on to 127 power
  • skips next else statement
  • next if-statement (is 5D pressed?) is false
  • executes next else statement; sets motors to 0
  • repeat

Alternately:

  • press 5D
  • first if-statement false
  • executes next else statement, sets motors to 0
  • next if-statement is true
  • sets motors to -127
  • skips final else statement
  • repeat

In both scenarios, you are sending commands—in very quick succession, each time through the loop—to set the motors to 127 and then 0. I imagine that what happens is that they get jittery motors because they’re being turned on & off very quickly. (Not good for the motors, either.)

To fix, you need to have one unified if-else tree for both buttons:

if 5U is pressed, turn on motor to 127
else if 5D is pressed, turn on motor to -127
else set to 0

Better yet, use a variable in your if-else tree, and then just have one motor command at the end of the section, like so:

int goalPower

if 5U pressed, set goalPower to 127
else if 5D pressed, set goalPower to -127
else set goalPower to 0

motor(LeftgoalMtr) = goalPower;
motor(RightgoalMtr) = goalPower;

With this setup, there is no possible way that you could be accidentally turning the motors on & off each time through the loop, because there is only set-motor command, down at the bottom of the section. (See my article, Set Motor Power Just Once.)

An even cooler way to code button action is to figure out the correct power all in one line instead of an else-if tree:

   int goalPower;

   goalPower = (vexRT[Btn5U] - vexRT[Btn5D]) * 127;

   motor(LeftgoalMtr) = goalPower;
   motor(RightgoalMtr) = goalPower;

In this all-in-one-line method, if 5U is pressed, you have (1 - 0)*127 = 127; if 5D is pressed, you have (0 - 1)*127 = -127. If neither is pressed, you have (0 - 0)*127 = 0. I think it’s pretty nifty. (See my other article, New Programming Concepts for Us.)

Their ClawMtr section is problematic from a performance standpoint. The way these blocks are written, when a person presses 7L or 7R, all other joystick functionality on both joysticks will be completely frozen until the 600msec is over. It’s better to put this whole section into a RobotC task so that it can run in parallel and not freeze out all other driver control for a half-second+. (See my other other article describing how to do this: RobotC Tasks: The Basics).

Hope some of this helps. And, to echo what’s been said above,

  • if the robot is moving along very slowly on its own, jiggle the joysticks around their center point and see if it stops.
  • do you have a 3-wheeled robot? Because there’s no code or motor setup for LeftBack.