View Full Version : Gyro problem
My teammate didn't even spin the gyro all the way around, but the numbers just kept going up, even when she stopped.
help?
And we made sure the pwm cables were attached correctly.
martin417
01-02-2009, 15:58
There are two outputs on the gyro, one for temperature. and one for turn rate. if you use the wrong outputs, you will get the behavior you described. Check your wiring.
the wiring on it is right, though. we've checked it already. Which is why we're at a loss.
rwood359
01-02-2009, 16:12
The gyro has to be completely still during calibration (done during open I believe) or you will get the kind of response that you are seeing.
EricVanWyk
01-02-2009, 16:12
the wiring on it is right, though. we've checked it already. Which is why we're at a loss.
Check it against the manual. A few mislabled ones escaped into the wild. Your result is typical of wiring into the temperature output.
Rate _should_ be on the outside, temp on the inside.
EricWilliams
04-02-2009, 15:28
Check it against the manual. A few mislabled ones escaped into the wild. Your result is typical of wiring into the temperature output.
Rate _should_ be on the outside, temp on the inside.
This continuous accumulation also occurred to our gyro, however, mislabeling was not the cause. We desoldered the wires and then resoldered them, and magically the gyro worked. Try that.
kevin.li.rit
04-02-2009, 15:30
Keeping the wires short will also help the drift(lower capacitance).
EricVanWyk
04-02-2009, 15:40
Keeping the wires short will also help the drift(lower capacitance).
I do not believe you, yet. Can you please explain your reasoning?
kevin.li.rit
04-02-2009, 21:11
The gyro produces a voltage that will charge the capacitance in the wire. The longer the wire, the larger the capacitance, longer discharge time, longer change in voltage after gyro stops accelerating. It will also catch more noise if the wires are longer.
EricVanWyk
05-02-2009, 09:06
The gyro produces a voltage that will charge the capacitance in the wire. The longer the wire, the larger the capacitance, longer discharge time, longer change in voltage after gyro stops accelerating. It will also catch more noise if the wires are longer.
What you are describing is phase delay. Drift is where the null value (zero turn) drifts away from nominal, which is interpreted as a constant steady spin.
Your comment on phase delay is technically true, but not on a scale that is detectable. A cable that long will contribute a couple dozen picofarads. With a sampling frequency of 62,500Hz and an output impedence of 100 Ohms, you would need to add a couple hundred thousand picofarads to start to change things.
Since the gyro signal is only in the 0-200Hz(ish) range, I'd wager that phase delay will continue to be imperceptible.
However, the noise comment is very valid.
(If you're using C++, not sure about LabView) Are you trying to read the values using printf or cout? If you output too much it all builts up in the cRIO's memory and slowly comes out the console, so you might just be seeing old data in your terminal.
~DtD
Travis Hoffman
23-03-2009, 13:06
OK, I am trying to implement an ADXRS300 gyro on our 2009 bot using WindRiver.
I'm starting with a known-good unit from 2008. Using our bench setup, upon outputting printf's, with the gyro completely stationary, I'm getting a steady increase in gyro angle values that (from memory) is around a degree every five seconds or so. The gyro was stationary throughout the cRIO power-up process, and it is connected to Analog Input #1 on the first input module.
Last year, I used Kevin Watson's code, with much success. Kevin's code implemented a rejection deadband (ours was set to the default of 8) to help filter out junk and eliminate drift. Other than SetSensitivity (which I currently have set to 0.005 but will adjust to .00393 now that I've found the specific tuning values we used in last year's code), what other gyro setup/tuning adjustments are possible with WPILib's C++ gyro code, and how would we implement this tuning?
Thanks in advance,
Team 135
23-03-2009, 14:08
We had the same problem. We found it to be our code by running the sample gyro code. Also check that the wires are not reversed, I know that this has been said before, but it plagued us early in the 6 weeks.
If the gyro is constantly returning the exact same high angular velocity, then the problem is your wiring. Take a multimeter and check the voltage between one of the red/black wires and the signal wire. It should be about 2.5 volts in correct operation. To confirm if this is the case, set up your gyro class so it uses an incorrect PWM input that nothing is plugged into, and see if the behavior changes.
Also, double check that your using both the correct SLOT and correct channel. If you only specify the channel, it might be attempting to read the gyro off of the incorrect cRio slot.
If the gyro is constantly returning a varying low angular velocity (1 degree every 5 seconds as posted above is about right), then everything is fine and that is expected.
Joe Ross
23-03-2009, 17:01
1 degree every 5 seconds doesn't sound too bad (IE, inline with what I've seen with the new control system). You can play with AnalogChannel::SetAccumulatorDeadband if you want to (I think it is a relatively new addition). There was a big thread a few years ago debating whether it was better to have the dead band or not, as having the deadband may throw off the results once you start moving.
You may want to confirm the legality of the ADXRS300 gyro, as Analog devices has stopped making it, and it looks like most suppliers have stopped carrying it.
heydowns
23-03-2009, 17:08
1 degree every 5 seconds doesn't sound too bad (IE, inline with what I've seen with the new control system). You can play with AnalogChannel::SetAccumulatorDeadband if you want to (I think it is a relatively new addition). There was a big thread a few years ago debating whether it was better to have the dead band or not, as having the deadband may throw off the results once you start moving.
We observed significant standing-still error with the new control system as well, somewhere around this order of magnitude.
By modifying the Deadband, as suggested, we got much more stable results and still observed good accuracy when moving.
gwytheyrn
23-03-2009, 17:16
Also, check which analog channel you're using/try changing the channel. I'm not sure if this is true for everyone, but our module didn't like using the last analog in when we had the jumper for battery voltage on (Well...I guess we never tested whether it worked without it, since changing the channel worked).
Since it hasn't been mentioned, could the OP post about how fast the gyro measurement is drifting?
heydowns
23-03-2009, 20:03
Also, check which analog channel you're using/try changing the channel. I'm not sure if this is true for everyone, but our module didn't like using the last analog in when we had the jumper for battery voltage on (Well...I guess we never tested whether it worked without it, since changing the channel worked).
The battery voltage jumper controls what is fed to the last ADC channel on the analog module. You either get to measure battery voltage on that last channel, or you get to hook something up to the last channel header on the bumper and measure that.
So, your experience would hold for everyone on the first cRIO slot since the battery voltage measurement is required by the rules this year.
cabbagekid2
23-03-2009, 21:04
After using the Reset VI for the gyro in Labview we noticed that the angle toggled between 359 360 and 0. Does anyone else have this issue? We've never seen this before with the previous controller and kevin's code.
I know 359, 360, and 0 are about the same but why would it not be -1 or -2 deg rather than 359 360.
gwytheyrn
23-03-2009, 21:09
Can you set the gyro up as an analog input (it's under i/o in the WPI stuff) and probe what it thinks is the voltage when still and when rotating?
Travis Hoffman
24-03-2009, 02:13
Thanks to all who have responded.
First of all, our gyro is wired and connected correctly, as we verified today. We had full confidence in the test gyro as we used it last year.
Second, the thing worked better today with a lot less drift - we did take care to leave the gyro alone for an extended period following initial power up. Other than that, no changes we can think of.
I would still like to know how to adjust the deadband. I did see the AnalogChannel::SetAccumulatorDeadband reference in mucking through the source code. What would the syntax be to call this for the gyro channel on analog module 1, input 1?
Finally, it looks like the ADXRS610 is the replacement for the ADXRS300. I'll have to look into that one.
yoyodyne
24-03-2009, 07:22
We combined gyro and one channel of accelerometer processing so that we could use the same calibration interval for both (and changed the calibration period to 2 seconds which seems to be plenty). Also, we wanted functions to return the filtered angular rate for the gyro and the acceleration and speed from the accelerometer. Anyway, we also used a known good 300 degrees/sec gyro as well as this year's KOP gyro. To do this we copied the WPILib code into our project and then modified it. Part of our modified code is below - notice that we set the deadband for both to 10.
Hope this helps.
The code that set's up the gyro and accelerometer is here:
#ifdef PRACTICE_BOT
#define GYRO_SENSETIVITY 0.0055 /* LAST YEAR's GYRO */
#else
#define GYRO_SENSETIVITY 0.006966667 /* 2009 Gyro */
#endif
void InitializeUtilities()
{
m_gyro = new GYRO_ACC(1,1,1,2);
m_pressure_switch = new DigitalInput(6,14);
m_autonomous_alliance = new DigitalInput(4,6);
m_initial_position1 = new DigitalInput(4,7);
m_initial_position2 = new DigitalInput(4,8);
m_play_1s = new AnalogChannel(2,3);
m_play_10s = new AnalogChannel(2,4);
// m_compressor_relay = new Relay(4, 1, Relay::kForwardOnly);
m_gyro->SetSensitivity(GYRO_SENSETIVITY);
m_gyro->SetAccSensitivity(0.009666207);
m_gyro->Reset();
m_right_odo = new Encoder(6,3,6,4,false,CounterBase::k1X);
m_left_odo = new Encoder(6,1,6,2,false,CounterBase::k1X);
m_right_drive = new Encoder(6,7,6,8,false);
m_left_drive = new Encoder(6,5,6,6,false);
}
/**
* Initialize the GYRO_ACC.
* Calibrate the GYRO_ACC by running for a number of samples and computing the center value for this
* part. Then use the center value as the Accumulator center value for subsequent measurements.
* It's important to make sure that the robot is not moving while the centering calculations are
* in progress, this is typically done when the robot is first turned on while it's sitting at
* rest before the competition starts.
*/
void GYRO_ACC::InitGYRO_ACC()
{
if (!m_analog->IsAccumulatorChannel())
{
wpi_fatal(GyroNotAccumulatorChannel);
if (m_channelAllocated)
{
delete m_analog;
m_analog = NULL;
}
return;
}
if (!m_ana_accel->IsAccumulatorChannel())
{
wpi_fatal(GyroNotAccumulatorChannel);
if (m_accel_channelAllocated)
{
delete m_ana_accel;
m_ana_accel = NULL;
}
return;
}
m_voltsPerDegreePerSecond = kDefaultVoltsPerDegreePerSecond;
m_analog->SetAverageBits(kAverageBits);
m_analog->SetOversampleBits(kOversampleBits);
m_voltsPerG = kDefaultVoltsPerG;
m_ana_accel->SetAverageBits(kAverageBits);
m_ana_accel->SetOversampleBits(kOversampleBits);
float sampleRate = kSamplesPerSecond *
(1 << (kAverageBits + kOversampleBits));
m_analog->GetModule()->SetSampleRate(sampleRate);
Wait(0.25);
m_analog->InitAccumulator();
m_ana_accel->InitAccumulator();
Wait(kCalibrationSampleTime);
INT64 value;
UINT32 count;
m_analog->GetAccumulatorOutput(&value, &count);
UINT32 center = (UINT32)((float)value / (float)count + .5);
gyro_center = (float)value/(float)count;
m_offset = ((float)value / (float)count) - (float)center;
m_analog->SetAccumulatorCenter(center);
m_analog->SetAccumulatorDeadband(10); ///< TODO: compute / parameterize this
m_analog->ResetAccumulator();
m_ana_accel->GetAccumulatorOutput(&value, &count);
center = (UINT32)((float)value / (float)count + .5);
accel_center = (float)value/(float)count;
m_acc_offset = ((float)value / (float)count) - (float)center;
m_ana_accel->SetAccumulatorCenter(center);
m_ana_accel->SetAccumulatorDeadband(10); ///< TODO: compute / parameterize this
m_ana_accel->ResetAccumulator();
}
/**
* GYRO_ACC constructor given a slot and a channel.
*
* @param slot The cRIO slot for the analog module the GYRO_ACC is connected to.
* @param channel The analog channel the GYRO_ACC is connected to.
*/
GYRO_ACC::GYRO_ACC(UINT32 slot, UINT32 channel, UINT32 accel_slot, UINT32 accel_channel)
{
m_analog = new AnalogChannel(slot, channel);
m_channelAllocated = true;
m_ana_accel = new AnalogChannel(accel_slot, accel_channel);
m_accel_channelAllocated = true;
InitGYRO_ACC();
}
/**
* GYRO_ACC constructor with only a channel.
*
* Use the default analog module slot.
*
* @param channel The analog channel the GYRO_ACC is connected to.
*/
GYRO_ACC::GYRO_ACC(UINT32 channel, UINT32 accel_channel)
{
m_analog = new AnalogChannel(channel);
m_channelAllocated = true;
m_ana_accel = new AnalogChannel(accel_channel);
m_accel_channelAllocated = true;
InitGYRO_ACC();
}
yoyodyne
24-03-2009, 07:49
In that last post, I didn't address the gyro drift performance...
With a deadband of 10 it is pretty good. For example the beginning of our navigation dump file shows that the gyro drifted from 45.0 degrees to 44.999695 degrees in the period from when the robot was turned on RobotInit() until the field enabled autonomous which is maybe a minute or two?
In the dump section below, the robot was commanded to execute a CCW arc turn of 20 degrees/second with a forward speed of 0.5 until the heading was 0 degrees. x and y are the estimated field coordinates using the left and right odometry wheels and the gyro. h is the gyro heading, oh is the estimated gyro heading from using the odometry wheels alone, ox and oy are the estimated field coordinates using the left and right odometry wheels only (not the gyro). ror and rol are the raw encoder counts for the right and left odometry wheels.
arc: rate: -20.000000
arc: speed: 0.500000
arc: angle: 0.000000
arc: timeout: 10.000000
Nav: x: 4.000000, y: 4.000000, h: 44.999695, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.999695, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.999695, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.002197, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.002167, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.997162, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.988068, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.989807, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.992462, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.992462, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.990997, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.989685, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 44.994049, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.000427, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.004486, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.007355, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.008381, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.000000, y: 4.000000, h: 45.008022, ox: 4.000000, oy: 4.000000, oh: 45.000000, ror: 5, rol: 5, Arc:
Nav: x: 4.002983, y: 4.002983, h: 45.004089, ox: 4.002979, oy: 4.002987, oh: 44.925629, ror: 7, rol: 6, Arc:
Nav: x: 4.003977, y: 4.003977, h: 44.996216, ox: 4.003973, oy: 4.003981, oh: 45.000000, ror: 7, rol: 7, Arc:
Nav: x: 4.005965, y: 4.005966, h: 44.985992, ox: 4.005961, oy: 4.005970, oh: 45.000000, ror: 8, rol: 8, Arc:
Nav: x: 4.008946, y: 4.008950, h: 44.970764, ox: 4.008940, oy: 4.008956, oh: 44.925629, ror: 10, rol: 9, Arc:
Nav: x: 4.011928, y: 4.011935, h: 44.966827, ox: 4.011915, oy: 4.011947, oh: 44.851257, ror: 12, rol: 10, Arc:
Nav: x: 4.013915, y: 4.013925, h: 44.959839, ox: 4.013899, oy: 4.013941, oh: 44.851257, ror: 13, rol: 11, Arc:
Nav: x: 4.016895, y: 4.016910, h: 44.955292, ox: 4.016878, oy: 4.016928, oh: 44.925629, ror: 14, rol: 13, Arc:
Nav: x: 4.020870, y: 4.020890, h: 44.957764, ox: 4.020850, oy: 4.020910, oh: 44.925629, ror: 17, rol: 15, Arc:
Nav: x: 4.022856, y: 4.022881, h: 44.940948, ox: 4.022836, oy: 4.022902, oh: 44.925629, ror: 18, rol: 16, Arc:
Ken Streeter
24-03-2009, 08:18
Finally, it looks like the ADXRS610 is the replacement for the ADXRS300. I'll have to look into that one.
Just a note on the ADXRS610 -- if using the EVAL-ADXRS610 board, this board is not pin-equivalent to the ADXRS300EB. There is an additional +5V input that needs to be wired on the EVAL-ADXRS610 (as compared to the ADXRS300EB) and we also found that the two EVAL-ADXRS610 boards we purchased from DigiKey did not have connected ground planes, contrary to the datasheet for the board. Accordingly, we also needed to explicitly connect both ground planes when wiring up the board.
I've been intending to email Analog Devices to let them know of the datasheet inaccuracy, but I've been waiting until I get a round tuit.
Just figured I'd try to save you the 6 or so hours we wasted figuring out the above.
Joe Ross
24-03-2009, 09:30
Just a note on the ADXRS610 -- if using the EVAL-ADXRS610 board, this board is not pin-equivalent to the ADXRS300EB. There is an additional +5V input that needs to be wired on the EVAL-ADXRS610 (as compared to the ADXRS300EB) and we also found that the two EVAL-ADXRS610 boards we purchased from DigiKey did not have connected ground planes, contrary to the datasheet for the board. Accordingly, we also needed to explicitly connect both ground planes when wiring up the board.
I've been intending to email Analog Devices to let them know of the datasheet inaccuracy, but I've been waiting until I get a round tuit.
Just figured I'd try to save you the 6 or so hours we wasted figuring out the above.
We found the same thing, but it took us longer then 6 hours ;)
Joe Ross
24-03-2009, 16:17
After using the Reset VI for the gyro in Labview we noticed that the angle toggled between 359 360 and 0. Does anyone else have this issue? We've never seen this before with the previous controller and kevin's code.
I know 359, 360, and 0 are about the same but why would it not be -1 or -2 deg rather than 359 360.
I have not seen that in LabVIEW. Are you sure it's not something in your code?
Travis Hoffman
24-03-2009, 17:19
Thanks once again for all the code samples and other time-saving advice in this thread. I think my team will find the information very useful in the near future.
Ken Streeter
24-03-2009, 23:29
We found the same thing, but it took us longer then 6 hours ;)
OK, Given the fact that at least two of us ran into this, I sent an email off to Analog Devices -- I'll let you all know what I find out...
emersont49
26-08-2009, 14:41
I'm using the KOP gyro with Labview. I connected it to Analog 1 and used the code in the Gyro example.
When I reset the gyro, it doesn't return to 0. The value seems to be consistent (about 0.05 or so). Is this something I can deal with using the temperature input? The VIs don't appear to have any input for temperature.
What is a good a pproach for determining the Gyro offset value?
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.