Esempio n. 1
0
        private Magnetometer ReadI2C_MAG()
        {
            //Read the measurements from the sensors, combine and convert to correct values
            //The values are expressed in 2’s complement (MSB for the sign and then 15 bits for the value)
            //Start at OUT_X_L_A and read 6 bytes.

            byte[] data = readBytesMAG(berrryIMU.OUT_X_L_M, (byte)6);

            int accMagX = (int)(data[0] | (data[1] << 8));
            int accMagY = (int)(data[2] | (data[3] << 8));
            int accMagZ = (int)(data[4] | (data[5] << 8));

            if (accMagX >= 32768)
            {
                accMagX = accMagX - 65536;
            }
            if (accMagY >= 32768)
            {
                accMagY = accMagY - 65536;
            }
            if (accMagZ >= 32768)
            {
                accMagZ = accMagZ - 65536;
            }


            Magnetometer mag = new Magnetometer();

            mag.X = accMagX;
            mag.Y = accMagY;
            mag.Z = accMagZ;

            return(mag);
        }
Esempio n. 2
0
        private void TimerCallback(object state)
        {
            // These strings are used to store the readings from the sensors.
            string textGyrX, textGyrY, textGyrZ;
            string textAccX, textAccY, textAccZ;
            string textMagX, textMagY, textMagZ;
            string textGyrAngleX, textGyrAngleY, textGyrAngleZ;
            string textAccXangle, textAccYangle;
            String textHeading, textHeadingTiltCompensated;
            string textFusedX, textFusedY;
            string addressText, statusText;



            float CFangleX   = 0.0f;    // Fused X angle
            float CFangleY   = 0.0f;    // Fused Y angle
            float rate_gyr_x = 0.0f;    // [deg/s]
            float rate_gyr_y = 0.0f;    // [deg/s]
            float rate_gyr_z = 0.0f;    // [deg/s]



            try
            {
                // read the raw values from the gyrscope
                Gyroscope gyr = ReadI2C_GYR();
                // Copy these values into their corresponding strings
                textGyrX = String.Format("Gyro X Axis: {0:F0}", gyr.X);
                textGyrY = String.Format("Gyro Y Axis: {0:F0}", gyr.Y);
                textGyrZ = String.Format("Gyro Z Axis: {0:F0}", gyr.Z);

                // Read the raw values from the accelerometer
                Accelerometer acc = ReadI2C_ACC();
                textAccX = String.Format("Acc X Axis: {0:F0}", acc.X);
                textAccY = String.Format("Acc Y Axis: {0:F0}", acc.Y);
                textAccZ = String.Format("Acc Z Axis: {0:F0}", acc.Z);
                // Read the raw values from the magnetometer
                Magnetometer mag = ReadI2C_MAG();
                textMagX = String.Format("Mag X Axis: {0:F0}", mag.X);
                textMagY = String.Format("Mag Y Axis: {0:F0}", mag.Y);
                textMagZ = String.Format("Mag Z Axis: {0:F0}", mag.Z);



                statusText = "Status: Running";

                //Convert Gyro raw to degrees per second
                rate_gyr_x = (float)gyr.X * G_GAIN;
                rate_gyr_y = (float)gyr.Y * G_GAIN;
                rate_gyr_z = (float)gyr.Z * G_GAIN;

                //Calculate the angles from the gyro
                gyroXangle += rate_gyr_x * DT / 1000;
                gyroYangle += rate_gyr_y * DT / 1000;
                gyroZangle += rate_gyr_z * DT / 1000;

                // Copy these values into their corresponding strings
                textGyrAngleX = String.Format("Gyr X Angle: {0:F2}", gyroXangle);
                textGyrAngleY = String.Format("Gyr Y Angle: {0:F2}", gyroYangle);
                textGyrAngleZ = String.Format("Gyr Z Angle: {0:F2}", gyroZangle);

                //Convert Accelerometer values to degrees
                float AccXangle = (float)(Math.Atan2(acc.Y, acc.Z) + Math.PI) * RAD_TO_DEG;
                float AccYangle = (float)(Math.Atan2(acc.Z, acc.X) + Math.PI) * RAD_TO_DEG;
                // Copy these values into their corresponding strings
                textAccXangle = String.Format("Acc X Angle: {0:F2}", AccXangle);
                textAccYangle = String.Format("Acc Y Angle: {0:F2}", AccYangle);


                if (IMU_upside_down)
                {
                    if (AccXangle > 180)
                    {
                        AccXangle -= (float)360.0;
                    }
                    AccYangle -= 90;
                    if (AccYangle > 180)
                    {
                        AccYangle -= (float)360.0;
                    }
                    //Only needed if the heading value does not increase when the magnetometer is rotated clockwise
                    mag.Y = -mag.Y;
                }
                else
                {
                    AccXangle -= (float)180.0;
                    if (AccYangle > 90)
                    {
                        AccYangle -= (float)270;
                    }
                    else
                    {
                        AccYangle += (float)90;
                    }
                }



                //Complementary filter used to combine the accelerometer and gyro values.
                CFangleX = AA * (CFangleX + (rate_gyr_x * DT / 1000)) + (1.0f - AA) * AccXangle;
                CFangleY = AA * (CFangleY + (rate_gyr_y * DT / 1000)) + (1.0f - AA) * AccYangle;
                // Copy these values into their corresponding strings
                textFusedX = String.Format("{0:F0}", CFangleX);
                textFusedY = String.Format("{0:F0}", CFangleY);



                mag.heading = (float)(180f * Math.Atan2(mag.Y, mag.X) / Math.PI);

                // Have our heading between 0 and 360
                if (mag.heading < 0)
                {
                    mag.heading += 360;
                }
                textHeading = String.Format("{0:F0}", mag.heading);



                // Tilt compensated heading calculations
                //
                // Normalize accelerometer raw values.
                double accXnorm = acc.X / Math.Sqrt(acc.X * acc.X + acc.Y * acc.Y + acc.Z * acc.Z);
                double accYnorm = acc.Y / Math.Sqrt(acc.X * acc.X + acc.Y * acc.Y + acc.Z * acc.Z);



                //////////////////////////// Calculate pitch and roll//////////////////////////
                if (IMU_upside_down)
                {
                    // Use these four lines when the IMU is upside down. Skull logo is facing up
                    accXnorm = -accXnorm;               //flip Xnorm as the IMU is upside down
                    accYnorm = -accYnorm;               //flip Ynorm as the IMU is upside down
                    pitch    = Math.Asin(accXnorm);
                    roll     = Math.Asin(accYnorm / Math.Cos(pitch));
                }
                else
                {
                    // Us these two lines when the IMU is up the right way. Skull logo is facing down
                    pitch = Math.Asin(accXnorm);
                    roll  = -Math.Asin(accYnorm / Math.Cos(pitch));
                }


                // Calculate the new tilt compensated values
                double magXcomp = mag.X * Math.Cos(pitch) + mag.Z * Math.Sin(pitch);
                double magYcomp = mag.X * Math.Sin(roll) * Math.Sin(pitch) + mag.Y * Math.Cos(roll) - mag.Z * Math.Sin(roll) * Math.Cos(pitch);

                // Calculate tilt compensated heading
                mag.headingTiltCompensated = 180 * Math.Atan2(magYcomp, magXcomp) / Math.PI;

                if (mag.headingTiltCompensated < 0)
                {
                    mag.headingTiltCompensated += 360;
                }

                // Copy the tilt compensated heading into its corresponding string
                textHeadingTiltCompensated = String.Format("{0:F0}", mag.headingTiltCompensated);
            }
            // If there are problems, display error message
            catch (Exception ex)
            {
                textGyrX      = "X Raw: Error";
                textGyrY      = "Y Raw: Error";
                textGyrZ      = "Z Raw: Error";
                textAccX      = "X Raw: Error";
                textAccY      = "Y Raw: Error";
                textAccZ      = "Z Raw: Error";
                textAccXangle = " Acc X Angle: Error";
                textAccYangle = " Acc Y Angle: Error";
                textGyrAngleX = " Acc X Angle: Error";
                textGyrAngleY = " Acc Y Angle: Error";
                textGyrAngleZ = " Acc Z Angle: Error";
                textFusedX    = " Fused X Error";
                textFusedY    = "Fused Y Error";
                textHeading   = "Error";
                textHeadingTiltCompensated = "Error";

                statusText = "Failed to read from Gyroscope: " + ex.Message;
            }

            // UI updates must be invoked on the UI thread
            var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                // Here we copy all the strings into their display elements
                DisplayTextGyrX.Text = textGyrX;
                DisplayTextGyrY.Text = textGyrY;
                DisplayTextGyrZ.Text = textGyrZ;

                DisplayTextAccX.Text = textAccX;
                DisplayTextAccY.Text = textAccY;
                DisplayTextAccZ.Text = textAccZ;

                DisplayTextAccXAngle.Text = textAccXangle;
                DisplayTextAccYAngle.Text = textAccYangle;

                DisplayTextGyrAngleX.Text = textGyrAngleX;
                DisplayTextGyrAngleY.Text = textGyrAngleY;
                DisplayTextGyrAngleZ.Text = textGyrAngleZ;

                DisplayTextFusedXvalue.Text = textFusedX;
                DisplayTextFusedYvalue.Text = textFusedY;

                DisplayTextHeadingValue.Text = textHeading;
                DisplayTextHeadingTiltCompensatedValue.Text = textHeadingTiltCompensated;

                DisplayText_Status.Text = statusText;
            });
        }