Gyro not sending values?

Hello =) This is our first year using C++ and the WPI Library as opposed to LabView, and it’s been a bit rough getting on our feet. Our current issue is that of the gyro. Modelling off of the example code included, as well as just reading the documentation, you can see what I tried. It seems as if it should work, but it hasn’t. In order to test if I am even getting values I created an autonomous that should run the intake motor according to the values the gyro gives. The wiring is correct (to the extent of my knowledge) with the PWM plugged into the “gyro” plug on the gyro (not temp), with the signal cable facing outwards (I’ve flipped it both ways to see if it makes a difference; it hasn’t), and plugged into the 2nd slot of the analog breakout (which is in module 1 of the cRIO).

In short, the gyro just doesn’t seem to be working, and during the autonomous I created to test it, nothing happens. The wiring seems to be correct, and I was wondering if it could be code? [code below]

#include "WPILib.h"


class RobotDemo : public SimpleRobot
{
	Jaguar frontRight; // robot drive system
	Jaguar frontLeft;
	Jaguar backLeft;
	Jaguar backRight;
	
	Jaguar intakeMotor;
	
	Jaguar leftArm;
	Jaguar rightArm;
	
	Jaguar shooter;
	
	Joystick driveStick; 
	Joystick toolStick;
	Joystick armStick;
	
	Gyro gyro;
	
	Timer timer;

public:
	RobotDemo(void):
		
		frontRight(1),	// these must be initialized in the same order
		frontLeft(2),	// as they are declared above.
		backLeft(3),
		backRight(4),
		
		intakeMotor(5),
		
		leftArm(6),
		rightArm(7),
		
		shooter(10),
		
		driveStick(1),		
		toolStick(1),
		armStick(0),
		gyro(1, 2),
		timer()
	{
		
		frontRight.SetExpiration(0.1);
		frontLeft.SetExpiration(0.1);	
		backLeft.SetExpiration(0.1);
		backRight.SetExpiration(0.1);
		
		intakeMotor.SetExpiration(0.1);
		
		leftArm.SetExpiration(0.1);
		rightArm.SetExpiration(0.1);
		
		shooter.SetExpiration(0.1);
		
	}
	
	void driveSystems()
	{
		
	}
	
	void motorDrive(float speed)//Positive is forward; Negative is backwards
	{
		frontRight.Set(speed);
		frontLeft.Set(-speed);
		backLeft.Set(-speed);
		backRight.Set(speed);	
	}
	
	void motorTurn(float speed)//Positive is right; Negative is left
	{
		frontRight.Set(-speed);
		frontLeft.Set(-speed);
		backLeft.Set(-speed);
		backRight.Set(-speed);
	}
	
	void gyroDrive(float speed, float time) //For automouse only! Uses gyro measurements to keep you straight
	{
		timer.Reset();
		timer.Start();
		while( timer.Get() < time)
		{
			if( gyro.GetAngle() > 1 )
			{
				frontRight.Set( (speed*0.25) );
				frontLeft.Set(-speed);
				backLeft.Set(-speed);
				backRight.Set( (speed*0.25) );
			}
			else if( gyro.GetAngle() < -1 )
			{
				frontRight.Set(speed);
				frontLeft.Set( (-speed*0.25) );
				backLeft.Set( (-speed*0.25) );
				backRight.Set(speed);
			}
			else
			{
				frontRight.Set(speed);
				frontLeft.Set(-speed);
				backLeft.Set(-speed);
				backRight.Set(speed);				
			}
		}
	}
		
	void raiseAndShoot()
	{
		intakeMotor.Set(0.5);
		Wait(0.5);
		intakeMotor.Set(0);
		leftArm.Set(1.0);
		rightArm.Set(1.0);
		Wait(2);
		leftArm.Set(0);
		rightArm.Set(0);
		Wait(1);
		shooter.Set(-0.6);
		Wait(3);
		intakeMotor.Set(0.5);
		Wait(1.5);
		intakeMotor.Set(0);
		shooter.Set(0);
	}
	
	void Autonomous(void)
	{
		gyro.Reset();
		while (IsAutonomous())
		{
			if((gyro.GetAngle()) == 0)
			{
				intakeMotor.Set(0.0);
			}
			else if((gyro.GetAngle()) > 0)
			{
				intakeMotor.Set(0.1);
			}
			else if((gyro.GetAngle()) < 0)
			{
				intakeMotor.Set(-0.1);
			}
			else
			{
				intakeMotor.Set(0.0);
			}
		}
	}

	
	void OperatorControl(void)
	{

		while (IsOperatorControl())
		{
	
			
			frontRight.Set( - ( driveStick.GetX() ) - ( driveStick.GetY() ) );
			frontLeft.Set( - ( driveStick.GetX() ) + ( driveStick.GetY() ) );
			backLeft.Set( - ( driveStick.GetX() ) + ( driveStick.GetY() ) );
			backRight.Set( - ( driveStick.GetX() ) - ( driveStick.GetY() ) );
			
			leftArm.Set( armStick.GetY() );
			rightArm.Set( armStick.GetY() );
			
			if(toolStick.GetRawButton(6))
			{
				intakeMotor.Set(0.7);
			}
			else if(toolStick.GetRawButton(8))
			{
				intakeMotor.Set(-(0.7));
			}
			else
			{
				intakeMotor.Set(0.0);
			}
			
			
			if(toolStick.GetRawButton(4))
			{
				shooter.Set(-1.0);
			}
			else if(toolStick.GetRawButton(3))
			{
				shooter.Set(-0.6);
			}
			else if(toolStick.GetRawButton(1))
			{
				shooter.Set(-0.3);
			}
			else
			{
				shooter.Set(0.0);
			}
			
			
			if(toolStick.GetRawButton(5))
			{
				leftArm.Set(1.0);
				rightArm.Set(1.0);
			}
			else if(toolStick.GetRawButton(7))
			{
				leftArm.Set(-1.0);
				rightArm.Set(-1.0);
			}
			else
			{
				leftArm.Set(0.0);
				rightArm.Set(0.0);
			}
			
			
			Wait(0.005);				// wait for a motor update time
		}
	}
	
	/**
	 * Runs during test mode
	 */
	void Test() {

	}
};

START_ROBOT_CLASS(RobotDemo);


One thing you might try is to put the robot in Test mode from the DriverStation and verify that you are getting expected values for the gyro. It should show you the headings it is returning as you grab the robot and rotate it. Verify that the gyro sensitivity parameter is correct - if you look at the Gyro.h header file there is a parameter for this. The default is kDefaultVoltsPerDegreePerSecond = 0.007. Make sure that this matches the gyro that you are using.

Unrelated to the gyro problem, to make the driving easier, you might consider using the RobotDrive object instead of having separate speed controllers. The RobotDrive object in WPILib takes 2 or 4 drive speed controllers and supplies a number of methods to operate on them. It was designed to do exactly what you want to do.

While the code shown below is completely untested and it’s possible that some of the parameters are not quite right, you can look at the samples and get the idea from this.

So you can replace this code:


	Jaguar frontRight; // robot drive system
	Jaguar frontLeft;
	Jaguar backLeft;
	Jaguar backRight;

with something like this:


        RobotDrive drive;

Then instead of having the separate controllers:


		frontRight(1),	// these must be initialized in the same order
		frontLeft(2),	// as they are declared above.
		backLeft(3),
		backRight(4),

you have something that looks like this:


                drive(1, 2, 3, 4),

Once you’ve defined the RobotDrive object it becomes easy to operate the robot so this code:


	void motorDrive(float speed)//Positive is forward; Negative is backwards
	{
		frontRight.Set(speed);
		frontLeft.Set(-speed);
		backLeft.Set(-speed);
		backRight.Set(speed);	
	}
	
	void motorTurn(float speed)//Positive is right; Negative is left
	{
		frontRight.Set(-speed);
		frontLeft.Set(-speed);
		backLeft.Set(-speed);
		backRight.Set(-speed);
	}

can be written like this:


        void motorDrive(float speed) {
                drive.Arcade(speed, 0.0);  // for forward speed and 0 turn
        }

        void motorTurn(float speed) {
                drive.Arcade(0.0, speed); // for 0 forward speed and "speed" turn
        }

and for OperatorControl, the RobotDrive object helps again by letting you do this:


                drive.Arcade(driveStick); // it automatically does the arcade driving stuff

and the last piece for driving straight using the gyro can be done using proportional control. That is taking the gyro heading and mapping it to a turn rate. If the heading goes negative, you turn one way, and if it goes positive, you turn the other way. So you can do something like this:


void gyroDrive(float speed, float time) {
	timer.Reset();
	timer.Start();
	while( timer.Get() < time)
	{
              // in this example kP is a constant that maps the gyro headings
              // into turn rates. The greater the deviation from 0 degrees 
              // (straight) the faster the turn. the turn rates range from
              // -1 to 1 and the gyro headings are in degrees so they
              // need to be scaled.
	      drive.Arcade(speed, gyro.GetAngle() * kP);
	}
}

Producing turn rates that are proportional to the amount the robot is off of the 0 degree heading. Be careful that the correction is going in the right direction, that is kP will certainly be between 0 and 1 to scale down the headings but it might also be negative if the turns that need to be made are opposite the gyro angles.

If you look here: http://wpilib.screenstepslive.com/s/3120/m/7913/l/79734-creating-a-robot-project it shows some of these concepts.

Hope this helps.

Brad

Thank you for the reply! I’ve found the problem, and it seemed that the gyro wasn’t grounded well enough -_- And in regards to RobotDrive, it was what we first attempted. Our front motors are reversed in the front, so it was giving us some trouble at first before we tried inversing, and even after we inversed their values (SetInvertedMotor) we were having odd control issues. I figured it’d be more handy and easy in the end to declare them separately =)

If its alright to ask another question, I’ve been using a Logitech Dual Action joystick, and for the life of me I can’t figure out how to get values to be modified by the 2nd (right) stick. I thought maybe defining it in the constructor as 0, 1, or 2 would work, but it hasn’t :confused:

Thanks again!
Jacque

The left thumbstick is read as axes 1 and 2. The right thumbstick is read as axes 3 and 4. (The D-pad above the left thumbstick is read as axes 5 and 6, but they’re “digital” values of -1, 0, or 1.)

This seems like a common enough question that there is this new page in the documentation for you…

http://wpilib.screenstepslive.com/s/3120/m/7912/l/95588-getting-your-robot-to-drive-with-the-robotdrive-class

Brad

Sorry to derail, but I had a question about the Gyro GetAngle function.

We want to incorporate the gyro that comes attached with the ADXL345 accelerometer in a Complementary filter which kinda looks like

angle = 0.98(angle + GyroAngularRateOfChange * dt) + 0.02(asin(Acceleration))

My question is whether the Gyro class already performs this integration for us in the GetAngle function (which according to the comments in the class header, it does), or if we need to find the rate of angular change ourselves with voltage readings and then do fancy things.

The cRIO’s analog accumulators perform simple integration of the gyro at rates much higher then you could do in software (it runs at approximately 50khz). It does not use the acceleration as shown in your formula.