Results 1 to 4 of 4
  1. #1
    25+ Posting Member



    Join Date
    Nov 2010
    Location
    The Netherlands
    Posts
    26
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    MD-11 Pedestal with Autotrottle servos

    Hi Everyone,

    I would like to share my arduino sketch for the TQ and pedestal i built.
    It includes working autothrottles and a working spoiler lever upon touchdown or during RTO.
    Also there are 6 16x2 displays (connected to one UNO using i2c backpacks)
    All my inputs are through Leo Bodnar cards. (was already using these before i discovered arduino)

    The pedestal and autopilot panel are painted now, so the look a lot better now.
    The plan was to include some OLED displays into the autopilot panel, but that is on hold now.
    The PMDG MD-11 is hard to work with. The speed and altitude info from simconnect is not in sync with what is displayed in the sim.
    Is there anyone who might have a some idea how to extract that info in an other way????

    One other problem is the throttles in the PMDG-md11 are constantly moving (jittering even). My servo's follow every movement, so that looks and feels bad.
    Does anybody have an idea to dampen the servo movement a bit, by adding some code???

    FYI, the throttle servo's a are always active. There is a rubber dampner between the servo connector and the lever. So when i move the lever on the TQ, the lever in the sim moves, then the servo moves, to follow throttle lever angle.
    When the autothrottle is active, the input from the lever is ignored by the sim, and the servo's just follow the lever angle from the sim (as set by the autothrottle)
    One downside so far, the 20 USD servo's are a bit noisy. The more expensive high torque servo for the spoiler is a lot quiter, so i'll maybe replace them.

    Hopefully this helps someone with their project as well.

    Kind regards en good luck building everyone!!
    Below is the mentioned code.


    Code:
    
    
    
    //#include 
    #include 
    #include  
    #include ;
    #define RELAY1 6
    
    
    int Data;
    int CodeIn;// used on all serial reads
    int backlightled = 5; //PWM pin used for Brightnes on LCD (I2C)screens (controlled by light sensor)
    int brightness = 255; //Sets brightness
    int LDR=A0; //Light sensor on analog pin0
    int LDRValue = 0; //Starting point for light senseor.
    int oldspoil;
    int pos = 0;    // variable to store the servo position (obsolete when using microseconds)
    
    
    Servo ATServo1;
    Servo ATServo2;
    Servo ATServo3;
    Servo ATServo4;
    Servo SpoilServo;
    
    
    LiquidCrystal_I2C lcdCOM1(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    LiquidCrystal_I2C lcdNAV1(0x26 , 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    LiquidCrystal_I2C lcdNAV2(0x22, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    LiquidCrystal_I2C lcdADF1(0x23, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    LiquidCrystal_I2C lcdADF2(0x24, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    LiquidCrystal_I2C lcdXPDR(0x25, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    
    
    String COM1a, COM1s, NAV1a, NAV1s, NAV2a, NAV2s, ADF1a, ADF1s, ADF2a, ADF2s, XPDR,ATstate,ALT;
    
    
    String AT1;
    String AT2;
    String AT3;
    String AT4;
    String Spoil;
    
    
    
    
    void setup() 
    {
    
    
      analogWrite(backlightled, 255); //sets (I2C) LCD's at max brightness to start with(may not be nessecary)
    //  delay(2000);
    
    
      lcdCOM1.begin(16, 2);
    //  lcdCOM1.clear();
    //  lcdCOM1.print("## COM1 PANEL ##");
    //  delay(2000);
      lcdCOM1.clear();
      lcdCOM1.setCursor(1,2);
      lcdCOM1.print("ACT  COM1  SBY");
      
      lcdNAV1.begin(16, 2);
    //  lcdNAV1.clear();
    //  lcdNAV1.print("## NAV1 PANEL ##");
    //  delay(2000);
      lcdNAV1.clear();
      lcdNAV1.setCursor(1,2);
      lcdNAV1.print("ACT  NAV1  SBY");
      
      lcdNAV2.begin(16, 2);
    //  lcdNAV2.clear();
    //  lcdNAV2.print("## NAV2 PANEL ##");
    //  delay(2000);
      lcdNAV2.clear();
      lcdNAV2.setCursor(1,2);
      lcdNAV2.print("ACT  NAV2  SBY");
      
      lcdADF1.begin(16, 2);
    //  lcdADF1.clear();
    //  lcdADF1.print("## ADF1 PANEL ##");
    //  delay(2000);
      lcdADF1.clear();
      lcdADF1.setCursor(1,2);
      lcdADF1.print("ACT  ADF1  SBY");
      
      lcdADF2.begin(16, 2);
    //  lcdADF2.clear();
    //  lcdADF2.print("## ADF2 PANEL ##");
    //  delay(2000);
      lcdADF2.clear();
      lcdADF2.setCursor(1,2);
      lcdADF2.print("ACT  ADF2  SBY");
      
      lcdXPDR.begin(16, 2);
    //  lcdXPDR.clear();
    // lcdXPDR.print("## XPDR PANEL ##");
    //  delay(2000);
      lcdXPDR.clear();
      lcdXPDR.setCursor(1,2);
      lcdXPDR.print("     XPDR     ");
      
      ATServo1.attach(8); //attaching servo to pin 8 
      ATServo2.attach(9);
      ATServo3.attach(10);
      ATServo4.attach(11);
      SpoilServo.attach(2);
      
      ATServo1.writeMicroseconds (1500);
      ATServo2.writeMicroseconds (1490);
      ATServo3.writeMicroseconds (1325);
      ATServo4.writeMicroseconds (1500);
      SpoilServo.write (2);
    
    
    
    
      pinMode(RELAY1, OUTPUT);
      digitalWrite(RELAY1, HIGH);
      pinMode(backlightled, OUTPUT); //defines backlight led as an output.
      int oldspoil = 0;
    
    
    Serial.begin(115200);  
     
    
    
    }
    
    
    void loop() {
    
    
    LDRValue = analogRead(LDR); //gets light intensity
    brightness = (LDRValue/4)+50; // roughly creates values between 50 and 250
    brightness = constrain (brightness, 1, 255); //limits values to usable lcd brightness values
    analogWrite (backlightled, brightness); //Writes bightness
    //Serial.println(brightness); //used for finding actual LDR values 
      
      if (Serial.available()) {
        CodeIn = getChar();
        if (CodeIn == '=') {EQUALS();} // The first identifier is "="
        if (CodeIn == '<') {LESSTHAN();}// The first identifier is "<"
        if (CodeIn == '?') {QUESTION();}// The first identifier is "?"
        if (CodeIn == '/') {SLASH();}// The first identifier is "/" (Annunciators)
        if (CodeIn == '#') {HASH();} //The first identifier is "#" (experts simconnect extractions)  
    }//end of serial read bit
    }//end of void loop
    
    
    char getChar()// Get a character from the serial buffer
    {
      while(Serial.available() == 0);// wait for data
      return((char)Serial.read());// Thanks Doug
    }
    
    
    void EQUALS(){
      CodeIn = getChar(); // Get the second identifier
      switch(CodeIn) {// Now lets find what to do with it
       case 'A': // COM1 active frq
          delay (11);
          COM1a = "";
          COM1a += getChar();
          COM1a += getChar();
          COM1a += getChar();
          COM1a += getChar();
          COM1a += getChar();
          COM1a += getChar();
             lcdCOM1.setCursor(0, 0);
         //   delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdCOM1.print(COM1a);    
        break;
      case 'B': // COM1 standby frq
          delay (11);
          COM1s = "";
          COM1s += getChar();
          COM1s += getChar();
          COM1s += getChar();
          COM1s += getChar();
          COM1s += getChar();
          COM1s += getChar();
             lcdCOM1.setCursor(10, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdCOM1.print(COM1s);    
        break;
        
        case 'E': // NAV1 active frq
          delay (11);
          NAV1a = "";
          NAV1a += getChar();
          NAV1a += getChar();
          NAV1a += getChar();
          NAV1a += getChar();
          NAV1a += getChar();
          NAV1a += getChar();
             lcdNAV1.setCursor(0, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdNAV1.print(NAV1a);    
        break;
        
          case 'F': // NAV1 standby frq
          delay (11);
          NAV1s = "";
          NAV1s += getChar();
          NAV1s += getChar();
          NAV1s += getChar();
          NAV1s += getChar();
          NAV1s += getChar();
          NAV1s += getChar();
             lcdNAV1.setCursor(10, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdNAV1.print(NAV1s);    
        break;
        
     case 'G': // NAV2 active frq
          delay (11);
          NAV2a = "";
          NAV2a += getChar();
          NAV2a += getChar();
          NAV2a += getChar();
          NAV2a += getChar();
          NAV2a += getChar();
          NAV2a += getChar();
             lcdNAV2.setCursor(0, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdNAV2.print(NAV2a);    
        break;
        
          case 'H': // NAV2 standby frq
          delay (11);
          NAV2s = "";
          NAV2s += getChar();
          NAV2s += getChar();
          NAV2s += getChar();
          NAV2s += getChar();
          NAV2s += getChar();
          NAV2s += getChar();
             lcdNAV2.setCursor(10, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdNAV2.print(NAV2s);    
        break;
    
    
     case 'I': // NAV2 active frq
          delay (11);
          ADF1a = "";
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
             lcdADF1.setCursor(0, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdADF1.print(ADF1a);    
        break;
     
     case 'J': // NAV2 active frq
          delay (11);
          XPDR = "";
          XPDR += getChar();
          XPDR += getChar();
          XPDR += getChar();
          XPDR += getChar();
       //   XPDR += getChar();
       //   XPDR += getChar();
             lcdXPDR.setCursor(6, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdXPDR.print(XPDR);    
        break;
     
      case 'c': // TESTING ALT HDG ETC!!!!!!!!!!!!!!!!!!
          delay (11);
          ALT = "";
          ALT += getChar();
          ALT += getChar();
          ALT += getChar();
          ALT += getChar();
          ALT += getChar();
       //   XPDR += getChar();
            // lcdXPDR.clearLine(2);
             lcdXPDR.setCursor(1, 2);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
           lcdXPDR.print ("       ");
           lcdXPDR.setCursor(1, 2);
            lcdXPDR.print(ALT);    
        break; 
      
      case 'u': // AUTOTHROTTLE STATE
          delay (11);
          ATstate = "";
          ATstate += getChar();
    //      ATstate += getChar();
         int ATstateInt = ATstate.toInt(); // convert it to an integer 
         if (ATstateInt >0) {
      digitalWrite(RELAY1, LOW);
         }
       else {
      digitalWrite(RELAY1,HIGH);
       }  
    
    
        break;
      
        }//end of case switch
      }// end of void equals
    
    
    void LESSTHAN(){    // The first identifier was "<"
    CodeIn = getChar(); // Get another character
      switch(CodeIn) {// Now lets find what to do with it
        case 'A'://Found the second identifier
           //Do something
        break;
         
        case 'B':
     
        break;
          
          }//end of case method  
    if (CodeIn == 'j'){
          delay (1);
          Spoil = "";
          Spoil += getChar();
          Spoil += getChar();
          Spoil += getChar(); 
          int SpoilInt = Spoil.toInt(); // convert it to an integer.
    
    
                   lcdXPDR.setCursor(0, 0);
                   lcdXPDR.print(oldspoil);
                   lcdXPDR.setCursor(0, 6);
                   lcdXPDR.print(SpoilInt);
    
    
    
    
     if ((SpoilInt >= 99) && (oldspoil < SpoilInt)){ 
          delay (500); //possible solution with safety switch on lever
          SpoilServo.write (180);
          delay (400);
          SpoilServo.write (2);
          }
     else if ((SpoilInt < 10) && (oldspoil == 100)){
       
       lcdXPDR.setCursor(3, 0);
       lcdXPDR.print("RET");
       delay (3000);
       lcdXPDR.setCursor(3, 0);
       lcdXPDR.print("---");
      
     }
          oldspoil = SpoilInt;
    } // end of if
    
    
       }//end of lessthan
    
    
    void QUESTION(){    // The first identifier was "?"
    //do something
    }// end of question
    
    
    void SLASH(){    // The first identifier was "/" (Annunciator)
      //Do something
    }
    
    
    void HASH(){
      CodeIn = getChar();
      switch(CodeIn) {
        case 'E':
        delay (11);
          ADF1a = "";
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
          ADF1a += getChar();
             lcdADF1.setCursor(0, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdADF1.print(ADF1a);    
      break;
     
    case 'F':
        delay (11);
          ADF1s = "";
          ADF1s += getChar();
          ADF1s += getChar();
          ADF1s += getChar();
          ADF1s += getChar();
          ADF1s += getChar();
          ADF1s += getChar();
             lcdADF1.setCursor(10, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdADF1.print(ADF1s);    
      break;
     
        case 'G':
        delay (11);
          ADF2a = "";
          ADF2a += getChar();
          ADF2a += getChar();
          ADF2a += getChar();
          ADF2a += getChar();
          ADF2a += getChar();
          ADF2a += getChar();
             lcdADF2.setCursor(0, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdADF2.print(ADF2a);    
      break;
     
    case 'H':
        delay (11);
          ADF2s = "";
          ADF2s += getChar();
          ADF2s += getChar();
          ADF2s += getChar();
          ADF2s += getChar();
          ADF2s += getChar();
          ADF2s += getChar();
             lcdADF2.setCursor(10, 0);
          //  delay (11);//My LCD seems to need his (disabled by Ferry)
            lcdADF2.print(ADF2s);    
      break;
    
    
      } //end of case switch
    
    
    if (CodeIn == 'A'){
    delay (1);
          AT1 = "";
          AT1 += getChar();
          AT1 += getChar();
          AT1 += getChar();
          AT1 += getChar();
         int AT1Int = AT1.toInt()*-1; // convert it to an integer 
          AT1Int = (AT1Int + 1810);// Manual correction to suit servo zero. (VALUE 1890 for pushrod at 4cm)
          AT1Int = constrain(AT1Int, +1020, +1810);//constrain/limit the integer. (VALUE +1020, +1890 for pushrod at 4cm)
          ATServo1.writeMicroseconds(AT1Int);
    }
    
    
    if (CodeIn == 'B'){
        delay (1);
          AT2 = "";
          AT2 += getChar();
          AT2 += getChar();
          AT2 += getChar();
          AT2 += getChar();
         int AT2Int = AT2.toInt()*-1; // convert it to an integer 
          AT2Int = (AT2Int + 1795);// Manual correction to suit servo zero.(VALUE 1845 for pushrod at 4cm)
          AT2Int = constrain(AT2Int, +1030, +1795);//constrain/limit the integer (VALUE +1000, +1845 for pushrod at 4cm)
          ATServo2.writeMicroseconds(AT2Int);
    }
    
    
    if (CodeIn == 'C'){
        delay (1);
          AT3 = "";
          AT3 += getChar();
          AT3 += getChar();
          AT3 += getChar();
          AT3 += getChar();
         int AT3Int = AT3.toInt(); // convert it to an integer 
          AT3Int = (AT3Int + 1000);// Manual correction to suit servo zero. (VALUE 950 for pushrod at 4cm (servohorn offset))
          AT3Int = constrain(AT3Int, +1010, +1820);//constrain/limit the integer. (VALUE +950, +1850 for pushrod at 4cm(with servohorn offset)
          ATServo3.writeMicroseconds(AT3Int);
    }
    if (CodeIn == 'D'){
        delay (1);
          AT4 = "";
          AT4 += getChar();
          AT4 += getChar();
          AT4 += getChar();
          AT4 += getChar();
         int AT4Int = AT4.toInt()*-1; // convert it to an integer 
          AT4Int = (AT4Int + 1785);// Manual correction to suit servo zero. (VALUE 1885 for pushrod at 4cm)
          AT4Int = constrain(AT4Int, +1025, +1785);//constrain/limit the integer. (VALUE +1025, +1885 for pushrod at 4cm)
          ATServo4.writeMicroseconds(AT4Int);
    } // end of if...
    } // end of {HASH}
    Attached Images Attached Images
    Last edited by Navajo31; 05-26-2015 at 04:08 AM. Reason: added photos

  2. Thanks henriquesantos thanked for this post
    Likes henriquesantos liked this post
  3. #2
    300+ Forum Addict Shawn's Avatar
    Join Date
    Mar 2008
    Location
    Kamloops, British Columbia
    Posts
    443
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: MD-11 Pedestal with Autotrottle servos

    Really nice work, well done and thanks for sharing.

    Shawn

  4. #3
    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: MD-11 Pedestal with Autotrottle servos

    Is this line (blue) to make a empty space before the altitude? If so.
    I think you will get problems on displaying because the lcd can not update fast enough in the loop.
    Code:
    lcdXPDR.setCursor(1, 2);
    lcdXPDR.print ("       ");
    lcdXPDR.setCursor(1, 2);
    lcdXPDR.print(ALT);
    So you can write it like this, and avoid writing on same place twice in the loop:
    Code:
    lcdXPDR.setCursor(1, 2); //Start the print on second line place to. (Leave 1 empty space.)
    lcdXPDR.print ("       "); //Print 7 empty places (from place 2) Start altitude print on place 9
    lcdXPDR.print(ALT);
    Or like this:
    Code:
    lcdXPDR.setCursor(1, 0); // Here you start the print on second line place 0.
    lcdXPDR.print ("        ") // And add 8 empty spaces
    lcdXPDR.print(ALT); // And start the altitude print on place 9
    You will still get the space, followd by the altitude on line 2.

    UUPS! EDIT: Greate work! Fun to see youre result
    Life was hard, but then came Windows 7.
    Now we can fly! --------
    --------

  5. #4
    25+ Posting Member



    Join Date
    Nov 2010
    Location
    The Netherlands
    Posts
    26
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: MD-11 Pedestal with Autotrottle servos

    Hi guys, thanks for the compliments.

    @ buzzibi,
    Thanks for checking the code,and im sorry to have wasted your time :S :S
    That was some experimental code, that i forgot to take out before posting.
    Sorry.........

    I will use your tips in the future