Gyro Angle calculations isn't precise ?

Hey,

I'm using this LISY300AL Gyro: http://www.sparkfun.com/datasheets/Sensors/LISY300AL.pdf
But i cant get a precise data..

Here is my calculation:

//Global Gyros
float sensitivity;
long Threshold = 2;

//Gyro 1
float gyroZero;
float gyroAdc;
float gyroRate;
float gyroRotation;
float gyroAngle;
long stime = millis();
long dtime = 0;

    float calculateGyroAngle(int pin)
    {
        gyroAdc = analogRead(pin);
        if(abs(gyroAdc - gyroZero) <= Threshold)
          gyroAdc = gyroZero;
        gyroRate = (gyroAdc-gyroZero)/sensitivity;
        gyroRotation+=gyroRate*dtime/1000;
        gyroAngle = abs((gyroRotation - 360 * ceil(gyroRotation / 360))); // Round up between 0-360
        dtime = millis() - stime;
        stime = millis();
        return gyroAngle;
    }
    void InitGyro(int pin)
    {
        sensitivity = 0.716454545;
        gyroAdc = 0;
        gyroRate = 0;
        gyroRotation = 0;
        gyroAngle = 0;
        gyroZero = calibrateGyro(pin);
    }

    int calibrateGyro(int pin)
    {
        long resultGyro = 0;
        for(int i=0;i<100;i++)
        {
            resultGyro += analogRead(pin);
            delay(1);
        }
        resultGyro = resultGyro/100;
        return resultGyro;
    }

I dont get a precise angle, i move my object 90 degrees but the gyro drifts too much so it showes something else...
Maybe i'm doing something wrong ? or i should just add an Accelerometer to make it more precise ?

please post the whole code as I have to make assumptions about variable types etc to understand the working ...

Updated with full code, hope you can understand.

OK,
analogRead() will never be 100% accurate, there is allways some jitter in the conversion. You need to stabilize the reading similar to the calibrate function.

other remarks see code below

float calculateGyroAngle(int pin)
{
        // average multiple readings
        gyroAdc = 0;
        for (int i=0; i<32; i++)
        {
          gyroAdc += analogRead(pin);
        }
        gyroAdc /= 32;

        // this test introduces small deviations as it removes small movements too...
        if (abs(gyroAdc - gyroZero) <= Threshold) 
        {
          gyroAdc = gyroZero;
        }

        gyroRate = (gyroAdc-gyroZero)/sensitivity;  // or  * 1.39576... (just faster)

        gyroRotation += gyroRate*dtime/1000;   //  * 0.001

        // as gyroRotation can be megative ceil() might introduce unexpected artifacts.
        // gyroAngle = abs((gyroRotation - 360 * ceil(gyroRotation / 360))); // Round up between 0-360


if (gyroRotation >= 0)
{
   gyroAngle = gyroRotation - 360 * ceil(gyroRotation / 360);
}
else
{
   gyroAngle = - (abs(gyroRotation) - 360 * ceil(abs(gyroRotation) / 360);
}

        
      

        // To prevent skipping 1 millisec by calling millis twice ...
        unsigned long t = millis();
        dtime = t - stime;
        stime = t;

        return gyroAngle;
}

2 cents sofar

Hey, thanks alot for you replays i learn alot of new stuff and you are being very helpfull :slight_smile:

So in my Gyro i have VCC & GND pin, i connected the VCC to the Arduino 3.3v pin and the GND to one of the GND pins on the Arduino.
And i connected the OUT pin of the gyro to the Analog0 pin on the Arduino.

I use this external Power Supply

As you can see i'm giving 12v to the Arduino, and the Fixed volts are set to 3.3v and connected stright to the AREF pin and one of the GND pins on the arduino.

Now i changed my sensitivity back to 1.023, and added analogReference(EXTERNAL); to the setup() in my code.

You can see the purple black and red goes to the gyro, the big connector that connected to the 7,8,9 digitals is a Servo controller, and the 2 pins from the external supply to the AREF & GND.

Here is the code, every one milliseconds i call this:

void gyroTest()
{
    if(gyroInit) {
      finalGyroAngle = calculateGyroAngle(0);
      Serial.println(finalGyroAngle);
    }
}
float calculateGyroAngle(int pin)
{
    gyroAdc = calibrateGyro(0);
    if(abs(gyroAdc - gyroZero) <= Threshold)
      gyroAdc = gyroZero;
    gyroRate = (gyroAdc-gyroZero)/sensitivity;
    gyroRotation+=gyroRate*dtime/1000;
    unsigned long t = millis();
    dtime = t - stime;
    stime = t;
    return gyroRotation;
}

void InitGyro(int pin)
{
  Serial.println("Calibrating Gyro...");
  sensitivity = 1.023; //0.692454545; //0.716454545;
  gyroAdc = 0;
  gyroRate = 0;
  gyroRotation = 0;
  gyroAngle = 0;
  gyroZero = calibrateGyro(pin);
  Serial.print("Gyro Calibrated: ");
  Serial.println(gyroZero);
}

int calibrateGyro(int pin)
{
  long resultGyro = 0;
  for(int i=0;i<100;i++)
  {
    resultGyro += analogRead(pin);
    delay(0.5);
  }
  resultGyro = resultGyro/100;
  return resultGyro;
}

Am i doing everything ok ?

Am i doing everything ok ?

THen it should work....

I see a delay(0.5) that is pertinent incorrect as delay expect an int/long as parameter, not a float. It will be truncated to 0 so effectively doing nothing. For AnalogRead you don't need to do delay's but if you want use the - http://www.arduino.cc/en/Reference/DelayMicroseconds -

After doing all of this, my gyro is still like 95% accurate ...
i need 99% atleast..

I just think i'm gonna get an Absolut Angle sensor and connect it to the servo..

Thanks for the help :slight_smile:

Remember these MEMS gyros are not gyros! They are rate-gyros, which means you have to integrate the output to get absolute angle and that this absolute angle will drift with time. I'd never expect 99% accuracy, 95% sounds pretty good to me. If you want absolute angle you need to use a digital compass (or a digital compass in combination with a rate gyro and Kalman filtering).

The accuracy can be increased by sampling the gyro output more frequently (increases the accuracy of the software integration) and by sampling on a regular clock tick via interrupts. But 99% isn't going to happen with this technology.