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


Upgrade to ARC Pro

Synthiam ARC Pro is a new tool that will help unleash your creativity with programming robots in just seconds!


Thanks for posting. I know Jeremie is working on this, but the topic is buried in another only slightly related thread (my fault actually) and needs to be brought to the forefront. I too am disappointed that I bought a 4in1 sensor that only works as a 3in1, and does not appear to have been fully tested prior to release.



Hi Alan,

Yeah I figured I would put it out there. I really wanted it to work. Lets hope we hear good news. I didn't really care about the other features, like I am sure many others.

Ron R


So I guess I may be lucky since my order for four of the 4 in 1 sensors from AiLRobotics resulted in a backorder condition due to no present stock available from EZ-Robot.

Hopefully the sensors will be better designed/engineered and all 4 functions work for the robot design I have in mind using the EZB-(V4) controller and Lidar with the Teensy controller.


It's not the twenty bucks. I was going to blow that much money on playing Dave Schulpius' pinball machines anyway. I just want a working compass, preferably the one I have.

Ron R


I have the sensor on order myself for my JD Humanoid Robot. Is there a compass calibration process for this device? If there is not, that could be the problem.


@dalmonte1 No.... we are waiting to hear back from EZ Robot on the issue...

FYI the sensor you get may be updated anyway especially if you bought it from ez robot's store.... The affected sensors are probably from the initial batch of production?...


Hi @OldBotBuilder,

I read what you said in the thread, but even so, there should be some functionality. I expected this device to give at least basic values ( 0 - 90 - 180 - 270 - back to zero ) +- 10 degrees, and somewhat repeatable.

Ron R


Has anyone been able to get this to work to at least show 4 quadrants? I want to verify home direction and 90 degree turns. I will then "know", forward, right, left, and return.

Is there a way to calibrate it?

Ron R


I get totally random numbers out of the compass. The other three sensors are consistent and usable, but the compass makes absolutely no sense. Huge value jumps for the slightest turn, and doesn't return back to the original when facing the same way. only thing that is consistent is that the values hold steady until you move the sensor, and change values when you move it, but the values are useless.



Thanks, I had hoped someone found a way to calibrate it and got it working.

Ron R


The compass needs to be perfectly flat - there is a calculation that can be done to use the accelerometer to aid in the compass calculation. I will make a tutorial about it this week.


Hi Dj,

Thanks for the tutorial. Will vibration or movement screw up the readings, or will I have to stop to update readings?

Ron R


I just want to know if there has been any updates on the compass.

If not, does anyone know of a compass that I can get that will work with the EZB? If something has been used in the past, is there any example code I can look at? My project is kind of on hold until I can get the ability of 8 readings from a compass. (about every 45 degrees +- 5 degrees will work).


Ron R


I was wondering about the Compass listed in the i2C menu, HMC5883. Is this a device which works? I am not being sarcastic, just looking for an available device which will give me the feedback I want.

Ron R


Ron, In the original thread where we were discussing this, Elfage successfully got a different compass sensor working, but it was tricky because I2C is such a pain and very sensitive to wire length, proper resistors, etc, but if you go through that thread (particularly the later pages until we start talking about the problems using the EZ-B 4in1) you can probably figure out how to get one working.

Personally, I am going to wait for an EZ-B solution, but my project(s) are not on hold waiting for this, they just aren't as efficient as they will be once it does work.



Hi Alan, I guess I will continue to wait also. I would rather have a device which is compatable with the EZB, than mess around to get something working.

Dj mentioned he would work on a tutorial. I will see how he makes out.

Ron R


Moving my conversation over here where it belongs instead of in the release note thread. I am having a little more luck tonight. It is very strange. It kind of works in 2 orientations With the board right side up, and the plug to the rear it detects turns, in the right direction, but when I get it generally towards "0" it is facing south. If I turn it around with the plug facing forwards to try to fool it into thinking it is pointed north, it doesn't work at all, just fluxuates up and down in the mid "200's" when I turn it, which makes no sense at all, accept that with tonight's tests it is mounted to a cube off the front of Adventurebot, so maybe the servos or even the EZ-B itself, which it is pointed towards in that position is having an impact.

Any other orientation has the same issue even if I move it as far away from the EZ-B and 2 servos as the cable will allow. It only works at all oriented one way.

OK, so with it in the position where it sort of works, comes the next problem. It isn't consistent in how far a degree is... If I turn face south, so it measures ~ 0 (it is very jumpy, but I can get it jumping between 355 and 5) and I turn 90 degrees to the right, it measures that I have turned 180 degrees. If I go back to 0, then turn 90 degrees to the left, it reads 300, thinking I have gone 60 degrees. It spends most of the circle in the 200's, with a big jump from 200 down to 0 in the last ~90 degrees or so.

All of this is with the default settings and using the default script. Increasing the smoothing just seems to make it react late to turns, but doesn't smooth out the jumpyness. Same with increasing or decreasing the time between reads in the script.

So, some progress, but still not really useful.



I haven't had as much luck as Alan so far, although (as mentioned) it doesn't jump around as much. But right now no matter what orientation I have the compass in it tends to read only from about 200 - 300 (but not really accurately). It seems to ignore anything between 0 and 180... I did calibrate it once, but I will keep at it today to see if I can improve on it... I did this waving the compass by hand. Later I will put it on my Roomba to have a stable platform to rotate from...

United Kingdom

To help with gathering more test results, I'll test the compass my 4 in 1 later as well and post the results. This will be the one ordered directly from China when it was first released.


Thanks steve - you won't need to do that. I have the issue resolved for the next release.

United Kingdom

Olay DJ. That's cool.


Yeah - it's been 18 hours of math class getting it right:) and learning a lot about compasses and calibration requirements. It's good now.


Good morning.

I ran a number of tests. I only used the compass on an ezb, nothing else connected. The compass and EZB was placed on my desk with my monitor and keyboard local to it. I don't believe they caused any interference. I placed the compass on the top slot of 3 stacked cubes. I ran the compass script, init. script. and Variable watch. I used the figure 8 motion to calibrate. I marked a base line on the pad below the cubes to set a zero point, which was south by a magnetic compass. Typical outputs shown on sweep display. I will re run tests later and monitor the variable watch display.

I rotated the block and ezb compass 90 degrees at a time and got the following results.

Angle turned (clockwise from top)

Pointed Degrees 0, 90, 180, 270, 0

Tests results 358-4 , 103-104, 208-220, 284- 290, 355- 6

Readout values were not stable and varied about +- 10 points at rest. Any movement caused additional lack of accuracy. Accuracy of coordinates to true value was not good, but without any movement seemed somewhat repeatable. The zero point value (south) seemed to repeat within tolerance +-10 points.

I don't know if I will have the opportunity to connect the compass to my adventure Bot until next week to see if it works while running. If I can sneak in some time later, I will try to do additional tests.

The results seems better than they were during my initial tests in the past.

Ron R


Hi DJ, I see you are up early too (or late). I saw your update after I posted my test results. I look forward to your next release.


Ron R


This evening's build is much much better. With the circuit board facing up and the plug to the rear, it is working correctly. Heading still jumps around a good bit. +/- about 6 degrees when sitting still, but for gross motor movements (~45/90/180 turns) it will be quite useable.

Does not seem to work, even if recalibrated, if the board is facing down, like you would if installing on JD's chest. Also does seem to pick up some interference and lose accuracy if too close to the EZ-B (or maybe too close to the servos). I am testing with adventure bot, and have it on a pair of extension cubes off the front and it works fine. If I put it on the cube closest to the body, it loses all sense of direction. But with careful placement, this will definitely do what I need it to.



At this point it's in the hands of physics:D


Actually, if I calibrate with it in the "face forward" position (ie, like on a JD chest) it does work, but the jumping is +/- 15 instead of +/-6. So, maybe useable like that, but not as precise.



There is no axis at that angle for the sensor to read... well - not easily anyway. The Z axis has to make up for two axis at that point. Because X is front, Y is side, and Z is bottom.

Here's some code with will generate a file that you can load into excel and display what the compass values return. Notice how the Z axis is much less sensitive and really only used for tilt compensation,

ControlCommand("MPU9150", Init)

$xMax = 0
$xMin = 0
$yMax = 0
$yMin = 0
$zMax = 0
$zMin = 0

$filename = "c:\data.csv"



ControlCommand("MPU9150", RunOnce)

FileWrite($filename, $CompassX)
FileWrite($filename, ",")
FileWrite($filename, $CompassY)
FileWrite($filename, ",")
FileWriteLine($filename, $CompassZ)

if ($CompassX > $xMax)
  $xMax = $CompassX

if ($CompassX < $xMin)
  $xMin = $CompassX

if ($CompassY > $yMax)
  $yMax = $CompassY

if ($CompassY < $yMin)
  $yMin = $CompassY

if ($CompassZ > $zMax)
  $zMax = $CompassZ

if ($CompassZ < $zMin)
  $zMin = $CompassZ




Example graphed in excel:

User-inserted image


Fair enough. I wonder what chip is used in Android and iPhones, and my even my old Delorme GPS that has a tri-axial compass. All work in any position and hold position more stable (my even older Garmin only works when held flat, but the new ones are tri-axial). I am guessing that the chip they use is more expensive?



It's data interpolation on the collected data - and data smoothing by averages over a time period. You can do that same, collect a bunch of data over time and divide to obtain the average. However, you will only want a rolling average with a circular buffer. Meaning, there are only a maximum number of X measurements in the buffer. Adding to the buffer overwrites the oldest measurements. This is really really easily done on phones/micro's with DMA. DMA has circular buffer attribute. So as the dma collects data from the specified peripheral, the data is added and overwrites the oldest.

Doing it like that, gives you the ability to keep "motion" so the compass points in directions.

Because you are only collecting 1 sample every X ms, you're own circular buffer would need to consider the sample frequency as to not appear "lagged".


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;


      return GetRollingAverage();

    public int Add(int data) {

      datas[position % datas.Length] = data;


      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;


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?



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);


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...


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.



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...


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 ?


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

Here's the manual page for the MPU 9150 All In One module:

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.



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...

yes, that would be helpful I think. I was going to use a if $bearing <= $heading (or >= depending on which way I am turning), but being able to have a target range would probably be better. Will have to figure out what happens when I cross the 0/360 boundary to keep from turning to far. Figuring out the target $heading (ie $bearing) is easy, but knowing I have hit it trickier. For instance, if I am at 270 and my new target is 5, I need to keep going until I am greater than 360, and then continue until I am up to 5, so probably move in two steps instead of one. I'll figure it out.



Ok @DJ, I followed your advice and look only at the heading variable. However, the heading value don't change when I rotate the sensor, but only when I roll it...


Hi Alan,

I was wondering about converting 360 degrees to 1 to 179 positive and 181 to 359 as 1 to 179 negative numbers. 0 and 180 unsigned. This would allow the numbers to become directional. I haven't fully thought it thru, but what do you think? It should simplify the math?

Ron R

I forgot to mention invert the numbers, i.e. count + 177, +178, +179,180, -001, -002,-003, etc. 180 for example = South 0=North


Hi Dj.

I know it took a lot of work to get it right. Thanks very much ! I am sure many of us will put it to good use.

Ron R


I have been following this thread and decided to try the compass for myself. Perhaps I've missed something, but from what I've tried, the compass only seems to work when it is in a vertical position. Even then, it has to be turned in a circle, edgewise, for the readings to work out for 360 degrees. Is this correct?

I have calibrated it flat by putting it in the slot between JDs legs and again vertically by putting it in the chest slot. When flat it does nothing as I turn JD. In the chest, it only works when I tilt JD side to side.


WBS, you need to calibrate the sensor. View the ARC manual page for a video demonstrating.


I did calibrate it, twice. All according to the tutorial and the video in it. As I said above:


I have calibrated it flat by putting it in the slot between JDs legs and again vertically by putting it in the chest slot
Did the figure-8 thing and all. That seemed to go well. Ran the calibration once when I placed the sensor in the flat position, and ran it again when I placed it in the chest. When the chest position didn't work either, I put it back in the flat position and ran the calibration yet again. It works in both positions but only when I turned JD such that the board is upright (vertical) and rotated the robot such that the sensor board was turning in a circle with the edge of the board leading the way. Only then did the pointer in the control rotate appropriately, 360 degrees. If I rotated JD around the vertical (Z) axis while he is standing, the pointer did not move.


Hi @WBS00001,

I just tried it again with the new release. I started the init script., Hit the calibrate button and move it as was requested. Once the time zeroed, I placed the sensor flat on my desk. Rotating it on the horizontal plane I got the readings. I placed the sensor in three stacked ez blocks and found I could angle the sensor about 45 degrees from horizontal and still have it read. If you get to close to the ezb it seems unable to work correctly.

Ron R

User-inserted image

User-inserted image


Hi Dj, First, Again thanks for the upgrades of the compass.

The Quadrant displays are great. This will help with turns and direction.

Are we still able to get the "degree" numbers also? I want to experiment with both. I want to use them also as coordinates.

EDIT: Oops,, I messed with the setup and found the rounding works. This is great! Now I can go play.

Ron R


@ANDYROID Thanks for the input.

Ok, I decided to start from scratch so I made a new project and tried the calibrate and run script with it. I even made sure the servos had no power going to them yet. And ... it worked perfectly! Progress! Set it to nearest 10 degrees and it still worked perfectly.

Then I imported the Auto Position control from the example so I would have a servo setup model from which I could load a servo profile to set and energize the servos. Still worked fine. Even tried another calibration with the servos energized, still perfect.

Finally I went back to the original project I was running last night. Went through the calibration process again and all went well this time.

I kind of hate it when that happens because now I don't know why it didn't work last night. I changed nothing in the project.

Anyway, now I'm going to try another unit (still in the original packaging) and see if the same thing happens with the project from last night.

All of which leads to a question .... Once calibrated, do the calibration values get stored on the MPU9150 itself or in the EZB project file?


I would say in each project because of how the config settings work with plugins but that is a good question.


I think in the project. Doesn't the sensor only send the raw data and Dj's all night math, makes the values work ? I am not even sure the calibration will stay accurate? We will need some more tests or confirmation.

Ron R


The calibration is required each time - because it is not saved, yet. Also, the calibration continues to "learn" the longer the compass is used. So, if you continue to use it the calibration will become more accurate over time.

What can really screw the calibration up is large jolts or bangs. The compass will need to be re calibrated if that happens - this is due to the physics of a compass module and how it works - if they are jolted the calibration will be lost.

The drawing of how to calibrate does not imply the compass should be thrown in a figure 8:). Simply gently wave it in a figure 8 motion like you do with an iPhone when prompted.


Only had a little time for testing tonight, but the rounding function is perfect for my needs. I set it to 15 and it gives just the right amount of precision for navigation, and enough stability that I can trust my scripts not to overshoot their turn.




Wicked - it should come in handy the most with Roli because the PWM can be modified slightly for forward rolling turns to compensate for the compass variations.


Hi Alan,

Are your tests with the adventure Bot or Roli?

My goal is to get my adventure Bot to track on a compass coordinate until a ping distance then go to next step in the sequence script. The bot compass also is used to trim the straight line track by trimming the wheel servos. The compass also confirms turns are complete. Is this similar to what you are doing?

Ron R


I was testing with Adventurebot. I put an expansion cube off the front and then another on top of it and put the compass on that to get a little distance from the motors in the servos and any interference from the EZ-B itself.

My mid term goal is to put it in or on Roli.

Long term is a custom robot.