I am trying to interface a gyro with an Arduino Mega and need some help. The program below 'should' output the angle the gyro is at... but instead it is constantly summing (Probably because of the line GyroDegrees += GyroSense * dt; ?)
Anyway, removing the sum still leaves me without an angle. Am I doing something stupid?
Thanks in advance
Simon25176
p.s. Gyro is an ADXRS613, datasheet can be found here...
#define GyroPin 0 #define GyroBias 512
float dt=0.01;
int GyroRaw;
int GyroAdjusted;
float GyromV;
float GyroSense;
float GyroDegrees;
void loop(){
GyroRaw = analogRead(GyroPin); //Raw Gyro data (0 to 1023)
GyroAdjusted = GyroRaw - GyroBias;// GyroBias about equals 512 to make it a value from -512 to +512. Bias measured by leaing gyro still and measuring output.
GyromV = GyroAdjusted * 4.88; // 4.88mV per division - Gives a voltage for gyro reaction (in millivolts)
GyroSense = GyromV / 12.50;// datasheet - 12.5 mV/degree/second gyrosense is in degrees per second (Also, is differential of GyroDegrees, can be used in PID)
GyroDegrees += GyroSense * dt; // Leaves degrees, i.e integration
Serial.print(GyroDegrees);
}
The program below 'should' output the angle the gyro is at
No, a gyro only outputs rate of rotation.
If you want an absolute angle i.e.heading, you'll need a magnetometer.
If the gyro is not rotating, then it will output a null.
If this is an analogue, ratiometric gyro, then null will output half the supply voltage.
You have "dt", but nothing connects that to the rate "loop()" is running.
GyroAdjusted = GyroRaw - GyroBias
GyroBias may need some adjustment - it may not be exactly 512.
You have "dt", but nothing connects that to the rate "loop()" is running
I measured this using the millis() command with a simple equation, I did have it in the program but I've removed it since then.
Quote:
GyroAdjusted = GyroRaw - GyroBias
GyroBias may need some adjustment - it may not be exactly 512.
As it says in the comment I measured it by just letting it sit on the table, so bar drifting, it's 'about' 512 but I was hoping to complimentary filter it later to remove most of this...
Sorry, by Angle, I meant tilt angle rather than . The application is a Segway style vehicle.
In that case a 2D accelerometer will give the average direction of 'up' (but is too noisy to use for good balance feedback).
In fact you can avoid integrating the output of the gyro by just treating its output as the high-frequency component of an error signal, the matching low-frequency component comes from the accelerometer.
The gyros I've used once corrected have a drift of a few degrees a minute, so the cross-over frequency for complementary filtering can be quite low I guess (0.1Hz?) which will lose most of the accelerometer/vibration noise.
I sum 30 consecutive readings from the gyros to calibrate the zero-points then divide by three - this gives an extra order of magnitude accuracy in the zeroing, and thereafter I take a reading and multiply by ten before subtracting the zero value. If you just assume 512 is the zero you will get large drifts.
void callibrate_gyros ()
{
delay (1000) ; // Let gyro stabilize before calibrate
int x = 0 ;
int y = 0 ;
int z = 0 ;
for (int i = 0 ; i < 30 ; i++)
{
x += analogRead (RATEX) ;
y += analogRead (RATEY) ;
z += analogRead (RATEZ) ;
delay (20) ;
}
zero_rate_x = (x+1)/3 ;
zero_rate_y = (y+1)/3 ;
zero_rate_z = (z+1)/3 ;
Serial.print ("zero X=") ; Serial.print (zero_rate_x) ;
Serial.print (" Y=") ; Serial.println (zero_rate_y) ;
Serial.print ("Z=") ; Serial.println (zero_rate_z) ;
// delay (3000) ;
}