Results 1 to 8 of 8
  1. #1
    New Member
    Join Date
    Feb 2016
    Location
    Pakistan
    Posts
    3
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    gauges with 360 degree rotation

    Hi Jim,
    Your program is quite helpful and it really bridge the hardware and software gap. But i am having trouble running gauges that have more than 180 degree rotation because of servo limitation. 360 degree servo are available but they are continuous rotation in which we can control the speed not position. After lot of research i am able to find that a gear arrangement of 1:2 can be used to convert 180 to 360.

    Is there is any other ways because i have no knowledge of gears and they are not readily available in market?
    thanks

  2. #2
    150+ Forum Groupie BuzziBi's Avatar
    Join Date
    Mar 2013
    Location
    Norway
    Posts
    275
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    Look in the Notable threads

    for compass. Steve is using stepermotor and 360 degrees potentiometer.
    Life was hard, but then came Windows 7.
    Now we can fly! --------
    --------

  3. #3
    300+ Forum Addict Tom_G_2010's Avatar
    Join Date
    Mar 2011
    Location
    Central Mass
    Posts
    437
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    I have had great success with an AS5045 Rotary Encoder. It's basically a hal effects sensor that, when used with a diametrically polarized magnet gives you position data to within a 1/2 degree. I picked mine up on a breakout board for $20 US and they include a neodymium magnet disc with it. I mounted the magnet on the end of my compass shaft and it works great.

    http://www.madscientisthut.com/Shopp...tary%20Encoder
    https://www.facebook.com/mycessnasim PC: Intel Core i7 Haswell @ 3.8GHz, 8Gb Ram, Win 7 64Bit, dual SSDs, GeFroce 780 SIM: FSX w/Aclrtn Pk, FSUIPC4, ASN, UTX, GEX, REX 4

  4. #4
    150+ Forum Groupie BuzziBi's Avatar
    Join Date
    Mar 2013
    Location
    Norway
    Posts
    275
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    I would have loved to see how you gor this to work. In the code I mean
    Life was hard, but then came Windows 7.
    Now we can fly! --------
    --------

  5. #5
    300+ Forum Addict Tom_G_2010's Avatar
    Join Date
    Mar 2011
    Location
    Central Mass
    Posts
    437
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    Quote Originally Posted by BuzziBi View Post
    I would have loved to see how you gor this to work. In the code I mean
    I'm at work now so I don't have the code handy, but I'll be glad to post a copy this weekend when I'm home working on the sim. I just replaced my original stepper motor driven compass with a servo motor drive. I'll be sure to post some pics as well.
    https://www.facebook.com/mycessnasim PC: Intel Core i7 Haswell @ 3.8GHz, 8Gb Ram, Win 7 64Bit, dual SSDs, GeFroce 780 SIM: FSX w/Aclrtn Pk, FSUIPC4, ASN, UTX, GEX, REX 4

  6. Likes BuzziBi liked this post
  7. #6
    300+ Forum Addict Tom_G_2010's Avatar
    Join Date
    Mar 2011
    Location
    Central Mass
    Posts
    437
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    Quote Originally Posted by BuzziBi View Post
    I would have loved to see how you gor this to work. In the code I mean
    So here's the compass:



    The compass housing and compass rose are the real deal. I purchased a compass off eBay. The servo motor mount that sits below the instrument panel is of my own design and 3D printed as is the bracket that holds the sensor over the compass rose. The magnet that the sensor reads is glued in place on top of the compass rose.

    And, here's the code for my compass. There is a library for the position encoder but, I was having trouble getting it to pick up position data fast enough to keep up with the servo speed. I found the raw code for the sensor on their forum and that works fantastic.

    You'll also see an array variable that's 2x360 and eats up enough memory that I am running this on a Mega because an Uno didn't have enough memory. There are other ways to solve that but for now this is what's working.

    Code:
    const int ledPin = 13; //LED connected to digital pin 13
    const int clockPin = 7; //output to clock on sensor
    const int CSnPin = 6; //output to chip select on sensor
    const int inputPin = 2; //read input from sensor
    
    
    #include 
    Servo WetCmpServo;
    
    //Variables needed for sensor raw code
    
    
    int inputstream = 0; //one bit read from pin
    long packeddata = 0; //two bytes concatenated from inputstream
    long ShaftPstn = 0; //holds processed angle value
    long ShaftPstnLast = 0;
    long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info
    long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info
    long statusbits; //holds status/error information
    int DECn; //bit holding decreasing magnet field error data
    int INCn; //bit holding increasing magnet field error data
    int OCF; //bit holding startup-valid bit
    int COF; //bit holding cordic DSP processing error data
    int LIN; //bit holding magnet field displacement error data
    int debug = 0; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES
    int shortdelay = 100; // this is the microseconds of delay in the data clock
    int longdelay = 10; // this is the milliseconds between readings
    
    
    //Variables for wet compass
    
    int Heading = 359;
    int Heading_Last = 180;
    const int HdgOffSetUp = -75;  //added to overcome my accidentally gluing the magnet into the compass rose 75 degrees off North
    const int HdgOffSetDn = -77;
    int HdgOffSet;
    int HdgDelta;
    const int MaxHdgDelta = 180;  //Used to deal with the math when crossing from 1 to 359 or 359 to 1
    const int HdgTlrnc = 2;
    
    
    // The array below allows for correction of sensor errors caused if it's off center beyond tolerance and for inserting realistic compass correction errors
    
    
    int HdgCrtn [2][360] = {
      {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,
      45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,
      90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
      135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
      180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
      225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,
      270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,
      320,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359},
      
      {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,
      45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,
      90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
      135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
      180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
      225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,
      270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,
      320,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359}
      };
    
    
    //Servo speed control variables
    
    
    const int ServoStop = 91;
    const int MinRun = 5;
    const int MaxRun = 85;
    const int RunCCW = +10;
    const int RunCW = -10;
    
    //The usual variables used with Link2FS Multi
    
    
    int CodeIn;
    int ExtInt;
    int ExtCnt = 0;
    String HdgExt = "";
    String SpdExt = "";
    int SrvSpdTst = ServoStop;
     
    void setup()
    {
    
    
      WetCmpServo.attach(9);  // attaches the servo on pin 9 to the servo object
    
    
      pinMode(ledPin, OUTPUT); // visual signal of I/O to chip
      pinMode(clockPin, OUTPUT); // SCK
      pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer
      pinMode(inputPin, INPUT); // SDA
      
      Serial.begin(115200);
    }
    
    
    void loop()
    {
    
    
      
      Get_Heading();
      Get_ShaftPosition();
      delay(10);
      
    }

    Code:
    void Get_Heading() {
    
    
      if (Serial.available()) {
        CodeIn = getChar();
        if (CodeIn == '<') {
          CodeIn = getChar();
          if (CodeIn == 'J') {
            HdgTime = millis();
            HdgExt = "";
            for (ExtCnt = 0; ExtCnt < 3; ExtCnt++) {
              HdgExt += getChar();
            }
    
    
            Heading = HdgExt.toInt();
    
    
            if (Heading != Heading_Last) {
    
    
              HdgDelta = Heading - Heading_Last;
    
    
              Heading_Last = Heading;
    
    
    
    // code to deal with corssing 0 degrees
    
    
              if (HdgDelta > MaxHdgDelta || HdgDelta < -MaxHdgDelta) {
    
                if (HdgDelta > 0) {
                  HdgOffSet = HdgOffSetDn;
                }
                else if (HdgDelta < 0) {
                  HdgOffSet = HdgOffSetUp;
                }
                else {
                  HdgOffSet = 0; //Error
                }
              }
              else {                                 // not crosing zero
    
                if (HdgDelta > 0) {
                  HdgOffSet = HdgOffSetUp;
                }
                else if (HdgDelta < 0) {
                  HdgOffSet = HdgOffSetDn;
                }
                else {
                  HdgOffSet = 0;  // No change
                }
              }
    
    
              Heading = Heading + HdgOffSet;
    
    
              if (Heading > 359) {
                Heading = Heading - 360;
    
    
    
    
              }
              else if (Heading < 0) {
                Heading = Heading + 360;
    
    
              }
    
    
              Heading = HdgCrtn [1][Heading];  //Adjusts heading based on array variable
    
    
              Activate_Servo();
              delay(10);
    
    
            } // END THE NO CHANGE IF HERE
    
    
          }
        }
      }
    }
    
    
    char getChar() {
      while (Serial.available() == 0);
      return ((char)Serial.read());
    }


    Code:
    void Activate_Servo() {
      
      int SrvoDelta = 0;
      
      SrvoDelta = abs(Heading - ShaftPstn);
    
    
    
    
      if (ShaftPstn <  Heading - HdgTlrnc && SrvoDelta < MaxHdgDelta) {
    //    CCW Normal
        while (Heading <  ShaftPstn - HdgTlrnc || Heading >  ShaftPstn + HdgTlrnc) {
    //  Run Servo
          WetCmpServo.write(ServoStop + RunCCW);
          Get_ShaftPosition();
        }
        WetCmpServo.write(ServoStop);
      }
    
    
      else if (ShaftPstn >  Heading - HdgTlrnc && SrvoDelta > MaxHdgDelta) {
    //  CW Inverse
        while (Heading <  ShaftPstn - HdgTlrnc || Heading >  ShaftPstn + HdgTlrnc) {
          WetCmpServo.write(ServoStop + RunCCW);
          Get_ShaftPosition();
        }
        WetCmpServo.write(ServoStop);
      }
    
    
      else if (ShaftPstn >  Heading - HdgTlrnc && SrvoDelta < MaxHdgDelta) {
    //  CW Normal
        while (Heading <  ShaftPstn - HdgTlrnc || Heading >  ShaftPstn + HdgTlrnc) {
          WetCmpServo.write(ServoStop + RunCW);
          Get_ShaftPosition();
        }
        WetCmpServo.write(ServoStop);
      }
    
    
      else if (ShaftPstn <  Heading - HdgTlrnc && SrvoDelta > MaxHdgDelta) {
    //  CW Inverse
        while (Heading <  ShaftPstn - HdgTlrnc || Heading >  ShaftPstn + HdgTlrnc) {
          WetCmpServo.write(ServoStop + RunCW);
          Get_ShaftPosition();
        }
        WetCmpServo.write(ServoStop);
      }
      else{
        WetCmpServo.write(ServoStop);
      }


    This next chunk of code is, as I mentioned above, not my code but was posted on the Mad Scientist Hut forum where I purchased the sensor
    Code:
    
    int Get_ShaftPosition(){
      
    // CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high
    // again, data will appear on sda
      digitalWrite(CSnPin, HIGH); // CSn high
      digitalWrite(clockPin, HIGH); // CLK high
      delay(longdelay);// time between readings
      digitalWrite(ledPin, HIGH); // signal start of transfer with LED
      digitalWrite(CSnPin, LOW); // CSn low: start of transfer
      delayMicroseconds(shortdelay); // delay for chip initialization
      digitalWrite(clockPin, LOW); // CLK goes low: start clocking
      delayMicroseconds(shortdelay); // hold low
      for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin
      {
        digitalWrite(clockPin, HIGH); //clock goes high
        delayMicroseconds(shortdelay); // 
        inputstream =digitalRead(inputPin); // read one bit of data from pin
    //Serial.print(inputstream, DEC);
        packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value
        digitalWrite(clockPin, LOW);
        delayMicroseconds(shortdelay); // end of one clock cycle
      }
    // end of entire clock cycle
    //Serial.println(" ");
      digitalWrite(ledPin, LOW); // signal end of transmission
    // lots of diagnostics for verifying bitwise operations
    //Serial.print("packed:");
    //Serial.println(packeddata,DEC);
    //Serial.print("pack bin: ");
    //Serial.println(packeddata,BIN);
      ShaftPstn = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle.
    //Serial.print("mask: ");
    //Serial.println(anglemask, BIN);
    //Serial.print("bin ShaftPstn:");
    //Serial.println(ShaftPstn, BIN);
    //Serial.print("ShaftPstn: ");
    //Serial.println(ShaftPstn, DEC);
      ShaftPstn = (ShaftPstn >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
    //Serial.print("angleshft:");
    //Serial.println(ShaftPstn, BIN);
    //Serial.print("angledec: ");
    //Serial.println(ShaftPstn, DEC);
      ShaftPstn = ShaftPstn * 0.3515; // angle * (360/1024) == actual degrees
    //if (ShaftPstn != ShaftPstnLast){
    //  Serial.print("ShaftPstn: "); // and, finally, print it.
    //  Serial.println(ShaftPstn, DEC);
    //  ShaftPstnLast = ShaftPstn;
    //}
      return ShaftPstn;
    //Serial.println("--------------------");
    //Serial.print("raw: "); // this was the prefix for the bit-by-bit diag output inside the loop.
      if (debug)
      {
        statusbits = packeddata & statusmask;
        DECn = statusbits & 2; // goes high if magnet moved away from IC
        INCn = statusbits & 4; // goes high if magnet moved towards IC
        LIN = statusbits & 8; // goes high for linearity alarm
        COF = statusbits & 16; // goes high for cordic overflow: data invalid
        OCF = statusbits & 32; // this is 1 when the chip startup is finished.
        if (DECn && INCn) { Serial.println("magnet moved out of range"); }
        else
        {
          if (DECn) { Serial.println("magnet moved away from chip"); }
          if (INCn) { Serial.println("magnet moved towards chip"); }
        }
        if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); }
        if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); }
      }
    
    
      packeddata = 0; // reset both variables to zero so they don't just accumulate
      ShaftPstn = 0;
    
    
    }
    And that is how I have my compass working...
    Attached Images Attached Images
    https://www.facebook.com/mycessnasim PC: Intel Core i7 Haswell @ 3.8GHz, 8Gb Ram, Win 7 64Bit, dual SSDs, GeFroce 780 SIM: FSX w/Aclrtn Pk, FSUIPC4, ASN, UTX, GEX, REX 4

  8. #7
    150+ Forum Groupie BuzziBi's Avatar
    Join Date
    Mar 2013
    Location
    Norway
    Posts
    275
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    Unfortunately, I have my sim packed in boxes because of refurbishment of the room. Perhaps we are moving, so it might be a long time until it comes back up But I can not wait to try this. I will save this setup for later. I am following your escapades on facebook. Your sim has been incredible. Thank you for sharing.
    Life was hard, but then came Windows 7.
    Now we can fly! --------
    --------

  9. #8
    Our new friend needs to reach 10 posts to get to the next flight level
    Join Date
    Apr 2015
    Location
    UK
    Posts
    9
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: gauges with 360 degree rotation

    Guys, I am very keen to have a go with the AS5045 and this sketch. However, I am getting the following errors when compiling the sketch: (AS5045_Compass)



    AS5045_Compass.ino: In function 'void loop()':
    AS5045_Compass:111: error: 'Get_Heading' was not declared in this scope
    AS5045_Compass.ino: In function 'void Activate_Servo()':
    AS5045_Compass:169: error: a function-definition is not allowed here before '{' token
    AS5045_Compass:241: error: expected '}' at end of input
    'Get_Heading' was not declared in this scope

    Any help anyone?
    Thanks
    Jannie