# Linear compass display to use with a MPU

**URL:** <https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060>\
**Category:** Electronics (Arduino, etc.)\
**Created:** [March 9, 2026, 8:18pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060 "2026-03-09T20:18:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 9, 2026, 8:18pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/1 "2026-03-09T20:18:02Z")

</div>

I’m trying to make a linear compass using a MPU(I2C) and Arduino. I was able to get a regular compass to function properly reading data from the Arduino. Now I’m trying this. I’m using the MouseX() to give me the 0-360 degrees. I’m a bit lost as to how to have it display “N” at 0 degrees and properly display the proper degrees moving the mouse. Any help would be greatly appreciated

 ![linear compass](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/e/2/e21b25eca9674f604bb1192acd8120faeb4d0a57.jpeg)

```auto
// LINEAR COMPASS
PGraphics hdg;

float degree1;
int degree = 180; 

//
// ---------------------------------------------------------------
//
void setup()
{
  // init
  size(800, 600);
  hdg = createGraphics(360,40);
} // func 
 
void draw() 
{ 
 degree1=map(mouseX, 0, width, 0, 360);
 degree=int(degree1);
  
 hdg.beginDraw();
 hdg.background(255);

// black rect (the whole compass)
 hdg.noFill();
 hdg.stroke(0); //Black
 hdg.rect(0, 0, 359, 39);
  
  // yellow rect (the display)
  
 hdg.fill(255,255,2);
 hdg.rect(0, 20, 359, 19);
  
  // yellow triangle 
   
 hdg.stroke(0);// black
 hdg.fill(255, 255, 2); // yellow 
  
 hdg.triangle(180-5, 13, 180+5, 13, 180, 19);
  
  // DISPLAY DEGREES
 hdg.stroke(0);// black
 hdg.fill(0); // black 
 hdg.textAlign(CENTER);
 hdg.text(int(degree1),180, 11); 
  
 // DRAW BLACK DEGREE MARKS
 hdg.stroke(0); // black
 int lengthLine = 0;  
 for (int i=0; i < 360; i+=5)
 {
   if (i%20==0) { 
     lengthLine=8;
   } else
   {
     lengthLine=4;
   }
   hdg.line(degree+i, 21, degree+i, 21+lengthLine);
   hdg.fill(0);
   hdg.text("N", degree, 38);
  }
  
    // red line in display
 hdg.stroke(255, 2, 2); // red
 hdg.line(180, 21, 180, 39);
  
 hdg.endDraw();
 image(hdg, 220, 280);
 
// print(" ",degree);
// println(" ",mouseX);
}

```

```auto

```

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 11, 2026, 12:30am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/2 "2026-03-11T00:30:50Z")

</div>

Hello @philtkp,

The modulo operator will help you:

> **[% (modulo) / Reference](https://processing.org/reference/modulo.html)**
>
> Calculates the remainder when one number is divided by another. For example, when 52.1 is divided by 10, the divisor (10) goes into the dividend (52.1) five times (5 \* 10 == 50), and there is a remain…

Work through this minimal example:

```processing
// LINEAR COMPASS

float h; //hecta
int xOff = 50;

void setup()
  {
  size(400, 150);
  }

void draw() 
  { 
  background(0);
  h = map(mouseX, 0, width, 0, 300);
  point( h%300 + xOff, height/2-10); 

  strokeWeight(5);
  stroke(255, 255, 0);
  
  for(int i=0; i<300; i+=10)
   {
   float x = i+h;  
   point(x%300 + xOff, height/2);   
   }
 }

```

`:)`

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 11, 2026, 3:59pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/3 "2026-03-11T15:59:25Z")

</div>

Thanks,

let me try and get my head around this. what I’m trying to do, is make it look like it’s going around in a 360. if it hits the ends of the points, it pops out on the other side.

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 11, 2026, 6:20pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/4 "2026-03-11T18:20:00Z")

</div>

Hello,

> [@philtkp](#):
>
> if it hits the ends of the points, it pops out on the other side

Example assumes data from MPU is converted to 0 to \<360 and positive.

Example:

```processing
// LINEAR COMPASS

int compassScale = 360;
int xOff = 40;

int angle = 0;

void setup()
  {
  size(800, 150);
  strokeWeight(5);
  textAlign(CENTER, CENTER);
  textSize(16);
  }

void draw()
  {
  background(0);

  // For simulation! Will be converted to 0 to <360. Don't get dizzy!
  angle = (int) map(mouseX, 0, width, 0, 2*compassScale + 80);
  text(angle, mouseX, mouseY, 10);

  int mpuData = angle%compassScale; //0 to <360 with modulo operator
  text(mpuData, 20, 25);

  println(angle, mpuData);

  stroke(255, 255, 0); // yellow
  point(mpuData + xOff, height/2 - 10);
  //text(mpuData, 10, 25);

  for(int i = 0; i < compassScale; i += 20)
    {
    float x = i + angle;
    point(x%compassScale + xOff, height/2);
    }
  }

```

You may be able to adapt this to your linear compass.  
It is only a starting point.

I have worked with many MPUs in the past and it is a learning curve to visualize the data.

I adapted one line in your code to make it wrap as I moved the mouse:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/1/0/10d9e675e4b57ec71f2bade4f93078d6828cadde.png)

`:)`

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 14, 2026, 4:24am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/5 "2026-03-14T04:24:35Z")

</div>

I’m slowly starting to get my head around this.

---

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [March 14, 2026, 5:53pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/6 "2026-03-14T17:53:21Z")

</div>

There are several ways to do this. The approach I would take would be to create a full 360° image of the scale like this which is tiled horizontally (image will wrap on x axis)

![cs](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/6/7/67a06d41e0c14f338df6be96558959acdb5cbc92.png)

And then position it according to the heading. I created a sketch using this approach and this video shows it in action.

[![](https://i.ytimg.com/vi/QFCzUQ9SqGs/hqdefault.jpg "Linear Compass created with Processsing") ](https://www.youtube.com/watch?v=QFCzUQ9SqGs)

The code is modular so would be easy to incorporate into your own sketch. For instance in my sketch the draw method for my sketch is just this.

```auto
void draw() {
  background(220);
  updateAngle();
  drawCompass((width - 360)/2, height/2 - 20, angle);
}

```

the `drawCompass` call requires just 3 parameters, the first 2 control where it is displayed and the third the heading in degrees.

If you want the sketch code I can post it here but I fully understand if you want to create the linear compass yourself. 😄

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 14, 2026, 9:24pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/7 "2026-03-14T21:24:57Z")

</div>

on this one i wont mind seeing the sketch. I’ve never tried to use images.😳

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 14, 2026, 9:50pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/8 "2026-03-14T21:50:43Z")

</div>

> [@philtkp](#):
>
> I’ve never tried to use images

_[get() / Reference / Processing.org](https://processing.org/reference/PImage_get_.html)_

Minimal example:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/6/4/64cdfb1f891c46881f87787c7ce43014548ab052.png)

Your code was used to make the compass.  
I then sliced it with `PImage.get()` and moved it around.

I offset the slices:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/6/c/6c41417f30264c04db558df64704cc2b15ab54b3.png)

You still need to move modify x for correct placement and wrapping around.  
I encourage you to work through this one on your own.

Note: I had an offset of 8 pixels for the glyphs. The code needs more work to align everything.

`:)`

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 14, 2026, 10:00pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/9 "2026-03-14T22:00:11Z")

</div>

Hello @quark,

Small bug:  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/9/d/9daeb7b707589c07502062da9b9e9965578b9b69.png)

I am sure it is a simple fix on your end.

Note:  
I offset my image by 8 pixels so I did not have to split a glyph.  
Not sure what smoothing does on the edges and gave the glyph some breathing room.

`:)`

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 14, 2026, 11:15pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/10 "2026-03-14T23:15:47Z")

</div>

@ glv

this is where I’m at. I changed a few things to mirror some of your code. I’m closer but, still have a glitch.

![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/5/3/531b151c3216dc5c401db3492be77582f15f6f36.png)

![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/b/3/b30160bdaede76ea5891942d1d21501f17c52ab1.png)

```auto
// LINEAR COMPASS
PGraphics hdg;

int compassScale = 360;
int degree = 0; 
int degree1 = degree%compassScale;
//
// ---------------------------------------------------------------
//
void setup()
{
  // init
  size(800, 600);
  hdg = createGraphics(360,40);
} // func 
 
void draw() 
{ 
 degree = (int)map(mouseX, 0, 360, 0, 2*compassScale);
 //text(degree,mouseX,mouseY, 11);
   // DISPLAY DEGREES
 hdg.stroke(0);// black
 hdg.fill(0); // black 
 hdg.textAlign(CENTER);
 //text(degree1,180, 11); 
 

 hdg.beginDraw();
 hdg.background(255);

// black rect (the whole compass)
 hdg.noFill();
 hdg.stroke(0); //Black
 hdg.rect(0, 0, 359, 39);
  
  // yellow rect (the display)
  
 hdg.fill(255,255,2);
 hdg.rect(0, 20, 359, 19);
  
  // yellow triangle 
   
 hdg.stroke(0);// black
 hdg.fill(255, 255, 2); // yellow 
  
 hdg.triangle(180-5, 13, 180+5, 13, 180, 19);
  
  int degree1 = degree%compassScale;
  
  println(degree, degree1);
  // DISPLAY DEGREES
 hdg.stroke(0);// black
 hdg.fill(0); // black 
 hdg.textAlign(CENTER);
 hdg.text(degree1,180, 11); 
  
 // DRAW BLACK DEGREE MARKS
 hdg.stroke(0); // black
 int lengthLine = 0;  

 for (int i=90; i < 450; i+=5) {
  if (i%90==0) { 
     lengthLine=8;
   } 
   else if (i%20==0){
     lengthLine=5;
   }
   else   
   {
     lengthLine=3;
   }
   hdg.line(-degree1%360+i, 21, -degree1%360+i, 21+lengthLine);
   hdg.fill(0);
   hdg.text("N", -degree1+180, 38);
   hdg.text("E", -degree1+270, 38);
   hdg.text("S", -degree1+360, 38);
   hdg.text("W", -degree1+450, 38);
  }
  
    // red line in display
 hdg.stroke(255, 2, 2); // red
 hdg.line(180, 21, 180, 39);
  
 hdg.endDraw();
 image(hdg, 220, 280);
 

}

```

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 14, 2026, 11:30pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/11 "2026-03-14T23:30:53Z")

</div>

Hello @philtkp,

Try this in original code in the first post in the correct location.

`(degree+i)%360 // Take modulus of sum`

It also helps to use `println()` statements in your code you help understand the values.

The modulo operator can take some time to wrap your head around. No pun intended!

`:)`

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 15, 2026, 2:40am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/12 "2026-03-15T02:40:23Z")

</div>

Hello @glv

the only place I could find was

hdg.line((degree+i)%360, 21, (degree+i)%360, 21+lengthLine);

but it still was unable to get it to wrap 🙁

---

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [March 15, 2026, 8:48am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/13 "2026-03-15T08:48:18Z")

</div>

> [@philtkp](#):
>
> on this one i wont mind seeing the sketch. I’ve never tried to use images.

Sorry I didn’t make myself clear. The compass scale image was created using your code (with slight modifications) the only difference being it was created once and is drawn in a position to reflect the heading.

In the sketch I create a clipping zone the same size as the compass scale then I draw the image 3 times to make sure that I fill in any gaps at the left or right of the compass. This is much more efficient that recreating the compass scale for every heading because drawing an image and clipping is a very fast operation for Java.

Here is the sketch if you have any questions about it please ask. 😄

```auto
PGraphics compassScale;
float angle = 0;

void setup() {
  size(400, 120);
  cursor(HAND);
  compassScale = createCompassScale();
}

void draw() {
  background(220);
  updateAngle();
  drawCompass((width - 360)/2, height/2 - 20, angle);
}

void updateAngle() {
  // Rate will increase rapidly as the mouse moves towards the sides of the display
  float rate = 0.02 * tan(radians(map(mouseX, 0, width, -80, 80)));
  // Create a dead zone near the centre
  if(abs(rate) < 0.002) rate = 0;
  angle += degrees(rate);
  // Force the angle into the range >=0 and <360
  while(angle < 0) angle += 360;
  while(angle >= 360) angle -= 360;
}

// Draw linear compass heading (degrees)
// posX, posY = top-left corner display position
// angle the heading in degrees (must be in range >=0 and <360
void drawCompass(float posX, float posY, float angle) {
  push();
  translate(posX, posY);
  fill(255);
  noStroke();
  rect(0, 0, 360, 40);

  // DRAW SCALE
  clip(0, 20, 360, 40);
  float mark = 180; // compass marker position
  // Draw scale under compass marker / gratuicule
  image(compassScale, mark - angle, 20);
  // Fill any gaps to the left
  image(compassScale, mark - angle - 360, 20);
  // Fill any gaps to the right
  image(compassScale, mark +360 - angle, 20);
  noClip();

  // RED GRATICULE LINE
  stroke(255, 0, 0);
  strokeWeight(1);
  line(mark, 20, mark, 38);

  // TRIANGLE MARKER
  fill(255, 255, 2);
  stroke(0);
  triangle(mark, 20, mark - 6, 13, mark + 6, 13);

  // ANGLE TEXT
  textAlign(CENTER, TOP);
  textSize(12);
  fill(0);
  noStroke();
  text(""+ floor(angle), mark - 30, 1, 60, 20);

  // COMPASS BORDER
  noFill();
  stroke(0);
  rect(0, 0, 360, 40);

  pop();
}

PGraphics createCompassScale() {
  PGraphics cs = createGraphics(360, 20);
  cs.beginDraw();
  cs.background(255, 255, 2);

  // DISPLAY DEGREES
  cs.stroke(0);// black
  cs.fill(0); // black
  cs.textAlign(CENTER);

  // DRAW BLACK DEGREE MARKS
  cs.stroke(0); // black
  cs.strokeWeight(1.2);
  for (int i = 0; i < 360; i += 5) {
    cs.line(i, 0, i, 4);
  }
  for (int i = 0; i < 360; i += 30) {
    cs.line(i, 0, i, 8);
  }
  cs.line(0, 0, 360, 0);

  // DRAW COMPASS POINTS
  cs.textAlign(CENTER, TOP);
  cs.textSize(12);
  cs.noStroke();
  cs.fill(0);
  String pts = "NESWN";
  for (int i=0; i<pts.length(); i++) {
    cs.text(""+pts.charAt(i), i * 90 - 10, 10, 20, 12);
  }
  cs.endDraw();
  cs.save("cs.png");
  return cs;
}

```

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 15, 2026, 11:38pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/15 "2026-03-15T23:38:25Z")

</div>

> [@philtkp](#):
>
> MPU(I2C)

Hello,

Which MPU(I2C) are you using?

I made some adjustments to your last code to sort out some of the issues:

> **Code**
>
> ```processing
> // LINEAR COMPASS
> PGraphics hdg;
> 
> int compassScale = 360;
> int degree = 0; 
> int degree1 = degree%compassScale;
> //
> // ---------------------------------------------------------------
> //
> void setup()
> {
> // init
> size(500, 200);
> hdg = createGraphics(360,40);
> } // func 
>  
> void draw() 
> { 
> degree = (int)map(mouseX, 0, 360, 0, 2*compassScale);
> //text(degree,mouseX,mouseY, 11);
> // DISPLAY DEGREES
> hdg.stroke(0);// black
> hdg.fill(0); // black 
> hdg.textAlign(CENTER);
> //text(degree1,180, 11); 
>  
> 
> hdg.beginDraw();
> hdg.background(255);
> 
> // black rect (the whole compass)
> hdg.noFill();
> hdg.stroke(0); //Black
> hdg.rect(0, 0, 359, 39);
>   
> // yellow rect (the display)
>   
> hdg.fill(255,255,2);
> hdg.rect(0, 20, 359, 19);
>   
> // yellow triangle 
>    
> hdg.stroke(0);// black
> hdg.fill(255, 255, 2); // yellow 
>   
> hdg.triangle(180-5, 13, 180+5, 13, 180, 19);
>   
> int degree1 = degree%compassScale;
>   
> println(degree, degree1);
>  
> // DISPLAY DEGREES
> hdg.stroke(0);// black
> hdg.fill(0); // black 
> hdg.textAlign(CENTER);
> hdg.text(degree1,180, 11); 
>   
> // DRAW BLACK DEGREE MARKS
> hdg.stroke(0); // black
> int lengthLine = 0;  
> 
> //for (int i=0; i < 450; i+=5) 
> for (int i=0; i < 360; i+=5) 
> {
>     
> if (i%90==0) { 
> lengthLine=8;
> } 
> else if (i%20==0){
> lengthLine=5;
> }
> else   
> {
> lengthLine=3;
> }
>    
> // 0 North Debug
> if (i==0)
> {  
> lengthLine=-20;
> }
>    
> int off = 180;
> int rd = 360-degree1; //reverse direction    
> int c1 = (rd + i + off)%360; // Removed this to keep it clean
>    
> hdg.line(c1, 21, c1, 21+lengthLine);
>    
> //hdg.fill(0);
> //hdg.text("N", (degree1+180)%360, 38);
> //hdg.text("E", (degree1+270)%360, 38);
> //hdg.text("S", (degree1+360)%360, 38);
> //hdg.text("W", (degree1+450)%360, 38);
> 
> // I suggest moving out of loop!
> hdg.fill(0);
> hdg.text("N", (rd+0 + off)%360, 38); // Trick of the trade!
> hdg.text("E", (rd+90 + off)%360, 38);
> hdg.text("S", (rd+180 + off)%360, 38);
> hdg.text("W", (rd+270 + off)%360, 38);
> }
>   
> // red line in display
> hdg.stroke(255, 2, 2); // red
> hdg.line(180, 21, 180, 39);
>   
> hdg.endDraw();
> image(hdg, 60, 70);
> }
> 
> ```

It now moves N \> E \> S \> W as angle increases.

Sometimes it helps to simplify the code, start from scratch and\or rethink it rather than patch it.

Even some time away helps!

`:)`

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 16, 2026, 4:42am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/16 "2026-03-16T04:42:48Z")

</div>

Hi, going try it on some of the one’s i have here, mpu9250, GY80, gy521, BNO055, I did add

`int heading = 360-(degree)%360;` to get it to go from N to S with the proper heading. I wish i was able to step thru the code. but I haven’t been able to get the debug part of it to work for me. I’ll look at this code.Thanks for the help!

here’s my code so far

```auto
 // LINEAR COMPASS
PGraphics hdg;

float degree1;
int degree = 0;
int heading = 0;

//
// ---------------------------------------------------------------
//
void setup()
{
// init
size(800, 600);
hdg = createGraphics(360,50);
} // func

void draw()
{
degree1=map(mouseX, 0, width, 0, 4*360);
degree=int(degree1%360);

hdg.beginDraw();
hdg.background(255);

// black rect (the whole compass)
hdg.noFill();
hdg.stroke(0); //Black
hdg.rect(0, 0, 359, 49);

// yellow rect (the display)
hdg.fill(255,255,2);
hdg.rect(0, 25, 359, 24);

// yellow triangle

hdg.stroke(0);// black
hdg.fill(255, 255, 2); // yellow

hdg.triangle(180-5, 18, 180+5, 18, 180, 24);

int heading = 360-(degree)%360;

// DISPLAY DEGREES
//if (heading >= 360) heading = 0;
hdg.stroke(0);// black
hdg.fill(0); // black
hdg.textAlign(CENTER);
hdg.textSize(16);
hdg.text(heading,180, 15);

// DRAW BLACK DEGREE MARKS
hdg.stroke(0); // black
int lengthLine = 0;
for (int i=0; i < 360; i+=5)
{
if (i%90==0) {
lengthLine=9;
}
else if(i%45==0){
lengthLine=6;
}
else
{
lengthLine=3;
}
hdg.line((degree+i)%360, 26, (degree+i)%360, 26+lengthLine);
hdg.fill(0);

}
hdg.textSize(14);
hdg.text(“S”, (degree+360)%360, 47);
hdg.text(“N”, (degree+180)%360, 47);
hdg.text(“E”, (degree+270)%360, 47);
hdg.text(“W”, (degree+450)%360, 47);
hdg.textSize(10);
hdg.text(“NW”, (degree+495)%360, 45);
hdg.text(“NE”, (degree+225)%360, 45);
hdg.text(“SE”, (degree+315)%360, 45);
hdg.text(“SW”, (degree+405)%360, 45);
// red line in display
hdg.stroke(255, 2, 2); // red
hdg.line(180, 26, 180, 48);

hdg.endDraw();
image(hdg, 240, 275);

// print(" ",degree);
println(heading,-degree1%360);
}

```

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 16, 2026, 12:40pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/17 "2026-03-16T12:40:43Z")

</div>

> [@philtkp](#):
>
> going try it on some of the one’s i have here, mpu9250, GY80, gy521, BNO055

I remember my first experience with the BNO055!  
The yaw, pitch and roll were a firmware bug and I had to use quaternions and convert to Euler angles!  
That was a challenge I overcame.

> [@rotateZ() not working as expected](https://discourse.processing.org/t/rotatez-not-working-as-expected/843/9):
>
> I got my Adafruit BNO05 sensor! I do get “glitches” when I rotate at larger angles with my code and yours as well. [https://learn.adafruit.com/adafruit-bno055-absolute-orientation-sensor/faqs](https://learn.adafruit.com/adafruit-bno055-absolute-orientation-sensor/faqs) Adafruit states: "The Euler angles coming out of the chip are based on ‘automatic orientation detection’, which has the drawback of not being continuous for all angles and situations. According to Bosch BNO055 Euler angle output should only be used for eCompass, where pitch and roll stay below 45 degree…

You topic has inspired me to revisit some of my projects.

`:)`

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 16, 2026, 2:04pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/18 "2026-03-16T14:04:07Z")

</div>

I have the same one. haven’t tried it out still in it adafruit packaging. I was never able to get the MPU9250 to give me the correct reading. so i mostly bounce back to the GY80 and GY521( Cheap, ive fried a few of these not paying attention) Thanks for the heads up.

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [March 16, 2026, 3:53pm UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/19 "2026-03-16T15:53:32Z")

</div>

Hello again!

I added a very simple compass image to visualize the actual mouse movement.  
I had some code buried away in the forum that I used to make it.  
It helped me! _The mouse movement was needing attention on my end._

This is your code with the image added.  
I moved all of your _PGraphic_ to a function (not included).

> **Code**
>
> ```auto
> // LINEAR COMPASS
> PGraphics hdg;
> 
> PImage compass; // glv added
> 
> float degree1;
> int degree = 0;
> int heading = -90;
> 
> //
> // ---------------------------------------------------------------
> //
> void setup()
> {
> // init
> size(500, 500);
> hdg = createGraphics(360, 50);
> 
> compass = loadImage("compass.png"); // This must be in the sketch data folder
> println(compass.width, compass.height);
> } // func
> 
> void draw()
> {
> background(255);
> 
> degree1=map(mouseX, 0, width, 0, 4*360);
> degree=int(degree1%360);
> 
> push();
> imageMode(CENTER);
> image(compass, width/2, 2*height/3-20);
> pop();
> 
> push();
> translate(width/2, 2*height/3-20);
> rotate(-radians(degree+90));
>   
> strokeWeight(3);
> line(0, 0, 100, 0);
> pop();
> 
> imageMode(CENTER);
> image(hdg, width/2, 100);
> 
> hdg(); // glv edit begin.draw to end.draw moved to a function
> 
> // print(" ",degree);
> //println(heading, -degree1%360);
> }
> 
> ```

 ![compass](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/c/9/c97082940e151569b7285f152af57329a39f4de2.png)

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/8/c/8c8755cd12481f05150c0fe81a9b5d76b36d5fef.png)

You can modify to have mouse move along the compass and update!  
Example:  
_[Vector / Examples / Processing.org](https://processing.org/examples/vectormath.html)_

You text and code is much cleaner in your last example! I noticed.

Have fun!

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 17, 2026, 2:58am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/20 "2026-03-17T02:58:00Z")

</div>

@glv

I was thinking the same thing. this is the compass i was using from another project.

> **CODE**
>
> ```processing
> 
> float yaw = 0.0f;
> float yawOffset = 0.0f;
> float SpanAngle=120;
> 
> int yawDeg = 0;
> int NumberOfScaleMajorDivisions;
> int NumberOfScaleMinorDivisions;
> 
> // Global setup
> void setup() {
> // Setup graphics
> size(1000, 800);  
>   
> }
> void draw() {
> // Reset scene
> background(0);
>  
> yaw = (int)map(mouseX, 0, 360, 0, 360);
> yawDeg = (int)(yaw%360);
>   
> println(yaw, yawDeg);
>   
> pushMatrix();
> translate(width/2, 50);
> 
> drawCompass();
> popMatrix();
> }
> / ********************************************************** /
> /* Draw Compass indicator */
> / ********************************************************** /
> 
> void drawCompass() {
>   
> pushMatrix(); 
>   
> noStroke();
> fill(108, 156, 255); // Fill sky color
> ellipse(-300, 100, 220, 220);
>   
> if((int)yaw >= 1 && (int)yaw <= 180)
> yawDeg = (int)yaw;
> else yawDeg = 360 + (int)yaw;
>   
>    
> // DRAW DEGREES INSIDE COMPASS 
> noFill();
> stroke(255); //Black
> rect(-320, 155, 41, 25);
> fill(0); //Black
> rect(-320, 155, 41, 25);
> textSize(20);
> fill(255,255,255);
> textAlign(CENTER);
> text(yawDeg%360, -300, 175);  
>    
>   
> translate(-300, 100);   
>   
> CompassPointer(); 
>   
> popMatrix();
> pushMatrix();
> /* Draws the circular scale on compass */
> translate(-300, 100); 
>   
> stroke(255);
> strokeWeight(2);
> noFill();
> ellipse(0, 0, 217, 217);
>    
> SpanAngle=180;
> NumberOfScaleMajorDivisions=18;
> NumberOfScaleMinorDivisions=36;  
> CircularScale(); 
> rotate(PI);
> SpanAngle=180;  
>   
> CircularScale();
> rotate(-PI);
>    
> translate(-300, 100);
> textSize(20);
> fill(255,255,255);
> textAlign(CENTER);
> text("W", 165, -92);
> text("E", 430, -92);
> text("N", 300, -230);
> text("S", 300, 42);
> rotate(PI/4);
> textSize(15);
> text("NW",-0, -280);
> text("SE", 275, -280);
> popMatrix();
> rotate(-PI/4);
>   
> text("NE", -145, -135);
> text("SW",-420, -135);
>   
> }
> / *************************************************** /
> /* Draws the compass pointer */
> / *************************************************** / 
> void CompassPointer()
> {
> rotate(radians(yaw));  
> stroke(0);
> //strokeWeight(1);
> fill(255,255,255);
>   
> beginShape();
> vertex(0,-105);
> vertex(12, 100);
> vertex(0, 80);
> vertex(-12, 100);
> endShape(CLOSE);
>   
> ellipse(0, 0, 9, 9);  
> ellipse(0, 0, 3, 3); 
> }
> / ******************************************************** /
> /* Draw cirular scale */
> /* Code from Adrian Fernandez 4-19-2013 */
> / ******************************************************** /
> void CircularScale()
> {
> float GaugeWidth=304;  
> textSize(GaugeWidth/20);
> float StrokeWidth=1;
> float an;
> float DivxPhasorCloser;
> float DivxPhasorDistal;
> float DivyPhasorCloser;
> float DivyPhasorDistal;
> strokeWeight(2*StrokeWidth);
> stroke(255);
> noFill();
>    
> 
> float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
> float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;
> 
> for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
> {
> an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
> DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
> DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
> DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
> DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));  
>      
> line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
> }
> 
> DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
> DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;
> 
> for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
> {
> an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
> DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
> DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
> DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
> DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
> if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
> {
> strokeWeight(5);
> stroke(255);
>       
> line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
> strokeWeight(1);
> stroke(100, 255, 100);
>       
> line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
> }
> else
> {
> strokeWeight(3);
> stroke(255);
> line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
> }
> }
> }
> 
> ```

 ![compass](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/b/3/b37edda9474750c73bdceaa1b9f9bbabf27385e6.jpeg)

---

<div class="post-metadata">

**Author:** ![philtkp](https://avatars.discourse-cdn.com/v4/letter/p/6a8cbe/32.png) [@philtkp](https://discourse.processing.org/u/philtkp)\
**Post date:** [March 24, 2026, 2:37am UTC](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060/21 "2026-03-24T02:37:33Z")

</div>

@glv Got the kinks out of the compass project.

 ![Untitled](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/d/4/d4f41e7d9e5dc164c552c3a3a2a2ba6eff850a3a.png)

Thank you for the help and the sharing the knowledge. now i trying to add an artificial horizontal meter.

having a few issue’s to get through. its a bit out of whack.

 ![Untitled2](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/4/5/454bdc7168063c35be6c4ca2433cb6014fe20fce.png)

[Next page](https://discourse.processing.org/t/linear-compass-display-to-use-with-a-mpu/48060.md?page=2)
