Asked — Edited
Resolved Resolved by DJ Sures!

4 In One Orientation Sensor

I have purchased a 4 in One Orientation Sensor. My desire is to use the compass function.

Once loaded and running, I view the compass heading values in the Variable watch window.. The value fail to read correctly. I find when I set the device in 90 degree directions ( 0 - 90 - 180 - 270 - back to zero ) I get value that do not even come close to the set position., nor do they repeat. I have changed my location, and even tried it in a wooden shed without any potential magnetic interferences, and still it did not work.

Has anyone use this sensor and has been able to get it to display correctly?

My reason for buying this was for the compass only and I am disappointed to see it not work.

Ron R


ARC Pro

Upgrade to ARC Pro

Discover the limitless potential of robot programming with Synthiam ARC Pro – where innovation and creativity meet seamlessly.

PRO
Synthiam
#33  

Here's some behind the scenes code on the average circular buffer histogram module that is included with ARC's Open plugin framework....

Notice how the buffer is initiated at object creation, and all data added to it is circular. The average is returned upon each appended data call...


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EZ_B {

  public class AvgHistogramCls {

    double [] datas;
    int       position;

    public AvgHistogramCls(int historySize) {

      datas = new double[historySize];

      position = 0;
    }

    public void Reset() {

      position = 0;
    }

    /// <summary>
    /// Add a new item to the histogram and return the current average
    /// </summary>
    public double Add(double data) {

      datas[position % datas.Length] = data;

      position++;

      return GetRollingAverage();
    }

    public int Add(int data) {

      datas[position % datas.Length] = data;

      position++;

      return (int)GetRollingAverage();
    }

    public double GetRollingAverage() {

      int max = Math.Min(datas.Length, position);

      double total = 0;

      for (int p = 0; p < max; p++)
        total += datas[p];

      return total / max;
    }
  }
}
#34  

Gotcha I think. Since the phone/gps/whatever isn't trying to collect the data over WiFi it can take far more samples in the same amount of time and average them to appear more stable. It isn't the chip, it is the processing ability. If I set my reads to every millisecond and averged the data, it would appear more precise, but likely flood the data channel. Yes?

Alan

PRO
Synthiam
#35  

Lastly, the MPU has a built in accelerometer, which i use for tilt compensation. This is a filter which increases each compass axis based on the tilt to produce a heading...

First i normalize the data because each sensor returns a different data range. Then calculate Pitch and Roll. Then, tilt compensation based on the normalized values. Finally, produce a heading degree from the 3 axis.

Prior to all of this is the calibration data calculations - which merely grabs an average of highest and lowest values and adjusts the range based on your physical location, and the sensor's environment.

If you calibrate the sensor while it is not in the robot - that's defeating the purpose.


      double normSqrt = Math.Sqrt(cls.AccelX * cls.AccelX + cls.AccelY * cls.AccelY + cls.AccelZ * cls.AccelZ + cls.CompassX * cls.CompassX + cls.CompassY * cls.CompassY + cls.CompassZ * cls.CompassZ);

      double accxnorm = cls.AccelX / normSqrt;
      double accynorm = cls.AccelY / normSqrt;

      double magX = cls.CompassX / normSqrt;
      double magY = cls.CompassY / normSqrt;
      double magZ = cls.CompassZ / normSqrt;

      cls.Pitch = Math.Asin(-accxnorm);
      cls.Roll = Math.Asin(accynorm / Math.Cos(cls.Pitch));

      double mag_gY = magY * Math.Cos(cls.Pitch) - magZ * Math.Sin(cls.Pitch);
      double mag_gX = magX * Math.Cos(cls.Roll) + magY * Math.Sin(cls.Pitch) * Math.Sin(cls.Roll) + magZ * Math.Cos(cls.Pitch) * Math.Sin(cls.Roll);

      cls.Heading = Math.Atan2(-mag_gY, mag_gX) * (180 / Math.PI);
PRO
Synthiam
#36  

Alan, that's correct about "Flooding" the channel. What you could do is plug it into an arduino and read the data quickly, and return your own "smoothed" data.

This is something to consider for a new version of the compass module. Might be worth considering if we added a second IC that collects the data quickly, and filters it...

#37  

Cool. Now that it is working it will meet my needs and I imagine most of us. I want to have controlled turns of around 45 degrees without worrying about timing which can vary from surface or motor speed, so this will work. Someone trying to aim a turret at a precise location or something similar may not he as happy.

Alan

PRO
Synthiam
#38  

I might think of an EZ-Script command to throw in that will perform a range check between two degrees - should be useful for your needs. Let me think on that...

#39  

I have applied the last update but I even after calibration $CompassX, $CompassY and $CompassZ are stuck to 129 (or -129). Am I missing something ?

PRO
Synthiam
#40  

If it's not working, then yes you are:)

Here's the manual page for the MPU 9150 All In One module:https://synthiam.com/Tutorials/Help.aspx?id=213

Also, unless you wish to perform serious math, as in my previous posts, do not pay attention to the $compassx $compassy $compassz variables - that's a whole new world that you most likely don't want to experience.

Follow the manual page and use the $CompassHeading variable only.