Getting Angle Measurments from LISY300 gyro

Hi,

I recently purchased the LISY300 gyro sensor from Sparkfun.com. I have a project where I need the angle data from the gyro. I have already found out how to get the rotational rate from this tutorial: GyroLISY300AL \ Learning \ Wiring I have tried to get the gyro's angle data through my own programming, but I am not that good. I will post the code that I tried to use to get the angle data from the gyro. The code is a combination of a few different sources: Arduino Playground - Gyro
GyroLISY300AL \ Learning \ Wiring

If you could please help me interface the LISY300 gyro with Arduino to get the angular data... THANKS

int gyroPin = 0; //Gyro is connected to analog pin 0
float gyroVoltage = 3.3; //Gyro is running at 3.3V
float gyroZeroVoltage = 1.65; //Gyro is zeroed at 1.65V
float gyroSensitivity = .0033; //Our example gyro is mV/deg/sec
float rotationThreshold = 1; //Minimum deg/sec to keep track of - helps with gyro drifting
int pinPowerDown = 2; // digital pin for Power Down mode
// LOW = Normal, HIGH = Power down
float currentAngle = 0; //Keep track of our current angle

void setup() {
pinMode(pinPowerDown, OUTPUT);
digitalWrite(pinPowerDown, LOW); // set gyroscope to Normal
Serial.begin (9600);
}

void loop() {
//This line converts the 0-1023 signal to 0-5V
float gyroRate = (analogRead(gyroPin) * gyroVoltage) / 1023;

//This line finds the voltage offset from sitting still
gyroRate -= gyroZeroVoltage;

//This line divides the voltage we found by the gyro's sensitivity
gyroRate /= gyroSensitivity;

//Ignore the gyro if our angular velocity does not meet our threshold
if (gyroRate >= rotationThreshold || gyroRate <= -rotationThreshold) {
//This line divides the value by 100 since we are running in a 10ms loop (1000ms/10ms)
gyroRate /= 10;
currentAngle += gyroRate;
}

//Keep our angle between 0-359 degrees
if (currentAngle < 0)
currentAngle += 360;
else if (currentAngle > 359)
currentAngle -= 360;

//
Serial.println(currentAngle, DEC);

delay(10);
}

since we are running in a 10ms loop

That is an incorrect statement. You have a 10ms delay in your loop, but you also have a lot more going on. In particular, a Serial output at 9600 baud. Even outputing a single float, that's going to take around 10ms itself, so you aren't running anywhere near a 10ms loop.

Aside from the above, programming integration with sensors like standard gyros (what you're doing) isn't going to give you great results and, in fact, is likely to exhibit drift over an extended run time (depending on how well you implemented the integration, the extended run time might be only a few seconds). It's usually best to "fuse" together information from multiple sensors to get a better "estimate" of what you're looking for. Your best bet would be using an accelerometer in conjunction with your gyro and implementing a Kalman filter. But that would only work for roll and pitch.

If you want to measure yaw (you were ambiguous in your post about what the orientation of your sensor is), then your best off with a digital compass, perhaps with internal tilt compensation (usually not cheap!) and some additional filtering from your gyro (just in case the compass gives off error, the gyro could be used in a Kalman filter implementation in this case as well).

If you want stable timing don't use delay(), use millis() and test the result:

int next_time = 0 ;

void loop ()
{
  if (millis () - next_time >= 0)
  {
    next_time += 10 ;
    ... do some stuff ....
  }
}

This way the jitter in your code won't accumulate.

I've used a trick or two to allow next_time to be an int not a long (the way the comparison is coded matters). Use a long if you aren't worried about the extra overheads.

I'm sorry to comment twice, but I found some new information. In this instrucatable (step 3) it shows how to get angle from angular rate. But I do not know what these variables stand for... Can someone help me out?

"Because the gyro give us the angular rate, so a simple way to get the angle is have the angular rate multiplied by the time [angle = angle + w * dt]"

angle - the angle turned so far
w - the angulare rate read from the gyro
dt - delta time, the time between gyro readings

so the total angle turned is the the angle so far plus (the turn rate times the sample period)

The goal is to get the tilt angle in degrees? as seen in this video. Can anyone help? I know that a gyro outputs only a rotational rate, but I know it is possible to get the angle in degrees --->
Thanks

I know that a gyro outputs only a rotational rate, but I know it is possible to get the angle in degrees

The "rate" is simply "degrees per second" or "radians per second" - just take the "per second" out of the expression, and you're left with the angular rotation since some datum.

Can someone please help me understand where I am going wrong. I am using the above code and have added the timer using millis into the main loop. Its meant to give me the current angle of the gyro but it cycles down very quickly. I expect a bit of drift but this is massive. Heres my output

11670 83.21
11680 83.12
11690 83.02
11700 82.93
11710 82.84
11720 82.75
11730 82.66
11740 82.57
11750 82.48
11760 82.39
11770 82.30
11780 82.21
11790 82.12
11800 82.03
11810 81.94
11820 81.85
11830 81.76
11840 81.67
11850 81.58
11860 81.49
11870 81.40
11880 81.31
11890 81.22

So its drifting down by 1.99 degrees every 220ms. So you can see how this quickly erodes the angle

Heres my code

int gyroPin = 4;                 //Gyro is connected to analog pin 4
float gyroVoltage = 3.3;         //Gyro is running at 3.3V
float gyroZeroVoltage = 1.36;    //Gyro is zeroed at 1.36V
float gyroSensitivity = .002;    //Our example gyro is 2mV/deg/sec
float rotationThreshold = 5;     //Minimum deg/sec to keep track of - helps with gyro drifting

float currentAngle = 0;          //Keep track of our current angle
int timer = 0 ;                  //Keep rack of time

void setup() {
  Serial.begin (115200);
  analogReference(EXTERNAL);
}

void loop() 
{
  if (millis () - timer >= 0)
  {
    timer += 10 ;
    float gyroRate = (analogRead(gyroPin) * gyroVoltage) / 1023;

    //This line finds the voltage offset from sitting still
    gyroRate -= gyroZeroVoltage;

    //This line divides the voltage we found by the gyro's sensitivity
    gyroRate /= gyroSensitivity;

    //Ignore the gyro if our angular velocity does not meet our threshold
    if (gyroRate >= rotationThreshold || gyroRate <= -rotationThreshold)
    {
    //This line divides the value by 100 since the timer gives a 10ms loop (1000ms/10ms)
    gyroRate /= 100;
    currentAngle += gyroRate;
    }
    
    //Keep our angle between 0-359 degrees
    if (currentAngle < 0)
      currentAngle += 90;
    else
    if (currentAngle > 89)
      currentAngle -= 90;

    //DEBUG
    Serial.print(timer);
    Serial.print(" ");
    Serial.println(currentAngle);
  }
}

Thanks in advance

Can you post the exact code? Using the # button?

Im a bit confused Mark. The code I am having problems with was as the bottom of the last post.