2008 Gyro Code

Hi. I’m using Kevin’s new 2008 code, but I can’t figure out how to get the Gyro working in either autonomous mode or user mode. I believe that I set up the code right:


void Teleop_Init(void)
{
	Initialize_Gyro();
	
	if (Get_Gyro_Bias_Status() == GYRO_BIAS_NOT_DONE)
	{
		Start_Gyro_Bias_Calc();
		
		
		while (t2 < 76)
		{
			printf("Calculating gyro bias. State: %d.
\r", Get_Gyro_Bias_Status());
			//Start_Gyro_Bias_Calc();
			t2++;
		}
		

		Stop_Gyro_Bias_Calc();
		
		printf("Gyro bias calculated: %ld.
\r", Get_Gyro_Bias());
		
	}

}


void Teleop(void)
{
    ...

    	Process_Gyro_Data();
	tmpangle = Get_Gyro_Angle();
	printf("Gyro Angle %d
\r", tmpangle);

    ...
}

But unfortunately, the only output I get is “Gyro Angle 0”. I’m sure I’ve got the gyro connected right, as I get values from Get_Analog_Value (and they change), but I don’t get anything from Kevin’s code. Can anyone help?

FireJet,
The first thing you need to do is move the Process_Gyro_Data() into the Autonomous_Spin, Disabled_Spin and Teleop_Spin functions. This will allow a Gyro data to be processed all the time, not just during that 26.2 milliseconds loop.
Remember, Get_Gyro_Angle returns a long value. You need to typecast it to an int for your printf statement. Something like this.

tmpangle = int Get_Gyro_Angle();
printf("Gyro Angle %d
\r", tmpangle);

Process_Gyro_Data() should be called in a spin function, as it needs to process the data after each interrupt and the telop function isn’t fast enough.

		Start_Gyro_Bias_Calc();
		
		
		while (t2 < 76)
		{
			printf("Calculating gyro bias. State: %d.
\r", Get_Gyro_Bias_Status());
			//Start_Gyro_Bias_Calc();
			t2++;
		}
		

		Stop_Gyro_Bias_Calc();

The bias calc should last for several seconds. This starts the gyro bias calc, runs the while loop very quickly, and then stops the gyro bias calc too soon.

You should start the bias calc when t2=0, change your while loop to an if statement (so it gets called once each time through telop()) and stop it when t2=76 (or higher, since longer is better). You might also want to consider a delay so that the bias calc doesn’t start right away, for everything to stabilize.

Kevin has an example of all this in the ifi_frc_sensor project.

I tried running Process_Gyro_Data in the _Spin functions, but it still won’t help. To make sure that it wasn’t my code that was broken, I also added a bit of debug output to Kevin’s gyro.c code, in Process_Gyro_Data, so that it now looks like this:


void Process_Gyro_Data(void)
{
	int temp_gyro_rate;

	// fresh ADC data available?
	if(Get_ADC_Result(GYRO_CHANNEL))
	{	
		// should the completed sample set be used to calculate the gyro bias?
		if(calc_gyro_bias == 1)
		{
			// put the ADC reading on the circular queue
			Gyro_Queue[Gyro_Queue_Index] = Get_ADC_Result(GYRO_CHANNEL);
		
			// increment the write pointer
			Gyro_Queue_Index++;
		
			// is the circular queue now full?
			if(Gyro_Queue_Index == GYRO_QUEUE_SIZE-1)
			{ 
				// update the gyro bias status
				Gyro_Bias_Status = GYRO_BIAS_BUFFER_FULL;
			}

			// If the index pointer overflowed, cut-off the high-order bit. Doing this
			// every time is quicker than checking for overflow every time with an if()
			// statement and only then occasionally setting it back to zero. For this 
			// to work, the queue size must be a power of 2 (e.g., 16,32,64,128).
			Gyro_Queue_Index &= GYRO_QUEUE_INDEX_MASK;
		}
		else
		{
			// get the latest measured gyro rate
			temp_gyro_rate = (int)Get_ADC_Result(GYRO_CHANNEL) - gyro_bias;
	
			// update reported gyro rate and angle only if 
			// measured gyro rate lies outside the deadband
			if(temp_gyro_rate < -GYRO_DEADBAND || temp_gyro_rate > GYRO_DEADBAND)
			{
				// update the gyro rate
				gyro_rate = temp_gyro_rate;
	
				// integrate the gyro rate to derive the heading 
				gyro_angle += (long)temp_gyro_rate;
			}
			else
			{
				gyro_rate = 0;
			}
		}

		Reset_ADC_Result_Count();
	}
	else
	{
		printf("NO NEW ADC DATA.
\r");
	}
}

Every time Process_Gyro_Data gets called, I get “NO NEW ADC DATA.” output. So, I don’t believe there’s a problem with my code.

As well, I’ve tried replacing that hard-timed loop with this:


while (Get_Gyro_Bias_Status() != GYRO_BIAS_BUFFER_FULL)
{
    printf("Calculating gyro bias.
\r");
}

But that seems to cause the controller to run out of RAM (it locks up and shows a code error).

Did you enable the ADC and timer? Read adc_readme.txt (and gyro_readme.txt).

The user processor has to communicate with master processor regularly. You can’t have a loop that runs for a long time (ideally, it should never run longer then 26.2ms)*. If it’s hung up for too long, it will cause a code error. Because of this, you should not use while loops that are waiting for any type of outside input. You want to make sure the telop function runs very quickly. In almost all cases, replacing your while with an if works, because telop will be called many times.

*WPILIB/EasyC works around this by doing the communication in the background, but you have to deal with it in IFI and Kevin’s code.

I’ve read through the ADC and gyro readmes, and everything that they require should be set. I’m not sure about the timer, though… is there a readme for that?

As for the while loop, I did that because I wanted to run the gyro calculations in the initialization functions instead of the Teleop and Autonomous functions.

You need to follow the instructions in the “readme.txt” file in the documentation folder.

-Kevin

Looks like I need to get the really new 2008 code. I still have the version from January that has the old readme.txt file. I’ll post more if it still doesn’t work.

Yeah, that code is sooo January <grin>.

-Kevin

Just another question while I’m at it. I used the new default code to test the gyro, and in gyro.h I set “#define TENTHS_OF_A_DEGREE”, but when I get input from the gyro I’m getting numbers that range from the double/triple digits to in the thousands, even when I divide by 10. Should this be happening?

If you are looking at the output of Get_Gyro_Angle, then readings such as 900 would be 90*, 300 would be 30*, 3600 would be 360*, etc.

Even after it’s been divided by 10? And even after that, I shouldn’t be getting values over 6000, should I?

We are getting output greater then 6000 even after it have been divided 10. Is that suppose to be like that?

So, does anyone know how to fix this?