Go Down

Topic: Artificial Horizon+Compass. (Read 4129 times) previous topic - next topic

arduinoadrian

Hi:

This is an Artificial Horizon/Compass combo built with Processing to be used with Arduino for 3 axis position visualization of a static swivel platform. It's not intended for navigation. At this point, the variables are dependent on the mouse position for testing purposes. These are part of the set of instruments I'm building to be used with Arduino. The idea is to have several "off-the-shelf instruments" already built to facilitate the implementation of Arduino projects using a computer.

Here is the video:https://www.youtube.com/watch?v=w5K2QXLH4eo&feature=youtu.be
Perseverance is 90% of the solution. The remaining 10% is more perseverance.

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

arduinoadrian

Hi:

I did a few modifications with respect to what appears in the video, like decreasing the precision of the variables and rotating the Pitch scale instead of the Bank one.

I'd like to see someone adding the code to handle 3 simple pots connected to 3 Arduino analog inputs to have it ready (better if the code can handle 360 deg pots at least for the compass). I don't want to do that now.

I had the CircularScale(); function already written for a previous project and decided to reuse it here instead of going PVectors as the instructions are low level and simple so they can easily be modified for other languages.

Here is the code:

//Artificial Horizon+Compass by Adrian Fernandez 4-19-2013
//Built with Processing 1.5.1
int W=1350; //My Laptop's screen width
int H=690;  //My Laptop's screen height
float Pitch;
float Bank;
float Azimuth;
float ArtificialHoizonMagnificationFactor=0.7;
float CompassMagnificationFactor=0.85;
float SpanAngle=120;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;
PVector v1, v2; //For testing only

void setup()
{
  size(W, H);
  rectMode(CENTER);
  smooth();
  //strokeCap(SQUARE);//Optional
}

void draw()
{
  background(0);
  translate(W/4, H/2.1); 
  MakeAnglesDependentOnMouse();
  Horizon();
  rotate(-Bank);
  PitchScale();
  Axis();
  rotate(Bank);
  Borders();
  Plane();
  ShowAngles();
  Compass();
  ShowAzimuth();
}

void MakeAnglesDependentOnMouse() //For testing only.
{
  v2= new PVector();
  v1= new PVector(W/2, H/2);
  v2.x=mouseX;
  v2.y=mouseY;
  Bank = PVector.angleBetween(v1, v2);
  Pitch=mouseY-H/2;
  Azimuth=(180/PI*10*Bank)%360;
}

void Horizon()
{
  scale(ArtificialHoizonMagnificationFactor);
  noStroke();
  fill(0, 180, 255);
  rect(0, -100, 900, 1000);
  fill(95, 55, 40);
  rotate(-Bank);
  rect(0, 400+Pitch, 900, 800);
  rotate(Bank);
  rotate(-PI-PI/6);
  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24; 
  CircularScale();
  rotate(PI+PI/6);
  rotate(-PI/6); 
  CircularScale();
  rotate(PI/6);
}

void ShowAzimuth()
{
  fill(50);
  noStroke();
  rect(20, 470, 440, 50);
  int Azimuth1=round(Azimuth);
  textAlign(CORNER);
  textSize(35);
  fill(255);
  text("Azimuth:  "+Azimuth1+" Deg", 80, 477, 500, 60);
}

void Compass()
{
  translate(2*W/3, 0);
  scale(CompassMagnificationFactor);
  noFill();
  stroke(100);
  strokeWeight(80);
  ellipse(0, 0, 750, 750);
  strokeWeight(50);
  stroke(50);
  fill(0, 0, 40);
  ellipse(0, 0, 610, 610);
  for (int k=255;k>0;k=k-5)
  {
    noStroke();
    fill(0, 0, 255-k);
    ellipse(0, 0, 2*k, 2*k);
  }
  strokeWeight(20);
  NumberOfScaleMajorDivisions=18;
  NumberOfScaleMinorDivisions=36; 
  SpanAngle=180;
  CircularScale();
  rotate(PI);
  SpanAngle=180;
  CircularScale();
  rotate(-PI);
  fill(255);
  textSize(60);
  textAlign(CENTER);
  text("W", -375, 0, 100, 80);
  text("E", 370, 0, 100, 80);
  text("N", 0, -365, 100, 80);
  text("S", 0, 375, 100, 80);
  textSize(30);
  text("COMPASS-01", 0, -130, 500, 80);
  rotate(PI/4);
  textSize(40);
  text("NW", -370, 0, 100, 50);
  text("SE", 365, 0, 100, 50);
  text("NE", 0, -355, 100, 50);
  text("SW", 0, 365, 100, 50);
  rotate(-PI/4);
  CompassPointer();
}

void CompassPointer()
{
  rotate(PI+radians(Azimuth)); 
  stroke(0);
  strokeWeight(4);
  fill(100, 255, 100);
  triangle(-20, -210, 20, -210, 0, 270);
  triangle(-15, 210, 15, 210, 0, 270);
  ellipse(0, 0, 45, 45);   
  fill(0, 0, 50);
  noStroke();
  ellipse(0, 0, 10, 10);
  triangle(-20, -213, 20, -213, 0, -190);
  triangle(-15, -215, 15, -215, 0, -200);
  rotate(-PI-radians(Azimuth));
}

void Plane()
{
  fill(0);
  strokeWeight(1);
  stroke(0, 255, 0);
  triangle(-20, 0, 20, 0, 0, 25);
  rect(110, 0, 140, 20);
  rect(-110, 0, 140, 20);
}

void CircularScale()
{
  float GaugeWidth=800; 
  textSize(GaugeWidth/30);
  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(15);
      stroke(0);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      strokeWeight(8);
      stroke(100, 255, 100);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      strokeWeight(3);
      stroke(255);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}

void Axis()
{
  stroke(255, 0, 0);
  strokeWeight(3);
  line(-115, 0, 115, 0);
  line(0, 280, 0, -280);
  fill(100, 255, 100);
  stroke(0);
  triangle(0, -285, -10, -255, 10, -255);
  triangle(0, 285, -10, 255, 10, 255);
}

void ShowAngles()
{
  textSize(30);
  fill(50);
  noStroke();
  rect(-150, 400, 280, 40);
  rect(150, 400, 280, 40);
  fill(255);
  Pitch=Pitch/5;
  int Pitch1=round(Pitch);
  Bank=Bank*180/PI;
  int Bank1=round(Bank);
  text("Pitch:  "+Pitch1+" Deg", -20, 411, 500, 60);
  text("Bank:  "+Bank1+" Deg", 280, 411, 500, 60);
}

void Borders()
{
  noFill();
  stroke(0);
  strokeWeight(400);
  rect(0, 0, 1100, 1100);
  strokeWeight(200);
  ellipse(0, 0, 1000, 1000);
  fill(0);
  noStroke();
  rect(4*W/5, 0, W, 2*H);
  rect(-4*W/5, 0, W, 2*H);
}

void PitchScale()

  stroke(255);
  fill(255);
  strokeWeight(3);
  textSize(24);
  textAlign(CENTER);
  for (int i=-4;i<5;i++)
  { 
    if ((i==0)==false)
    {
      line(110, 50*i, -110, 50*i);
    } 
    text(""+i*10, 140, 50*i, 100, 30);
    text(""+i*10, -140, 50*i, 100, 30);
  }
  textAlign(CORNER);
  strokeWeight(2);
  for (int i=-9;i<10;i++)
  { 
    if ((i==0)==false)
    {   
      line(25, 25*i, -25, 25*i);
    }
  }
}
Perseverance is 90% of the solution. The remaining 10% is more perseverance.

robtillaart

Thanks for sharing!

The code looks well structured!

(Please use code tags next time it is the # button (second row 3rd from right) above the text editor,
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

kellyluu

Hi! i'm doing a similar project but i have to use Visual Basics to display the pitch, yaw and roll readings. can you pls help me with this?

thanks in advance

cheers!

arduinoadrian

Sorry, I don't know Visual Basic; but maybe you can try to just rewrite the code using VB instructions. Actually most of them are low level and compatible with other languages. Perhaps someone here knows VB and can do that.
Perseverance is 90% of the solution. The remaining 10% is more perseverance.

Go Up