Results 1 to 8 of 8
  1. #1
    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

    My Cessna 172RG Elevator Trim and Auto Pilot Servo

    As promised, here's an overview of my Elevator Trim control.

    I should be more accurate and say Auto Pilot "Stepper Motor" I found the stepper motor much easier to code and control. With the engine audio up at a realistic level you don't notice it much, however, the stepped movement is a bit noisy.

    When I bought the fuselage I scored several extra parts to include the trim wheel. Cessna uses a standard chain size for their trim wheel linkage so ordering the chain and additional sprockets was easy. I got them and some steel shaft, bearings in pillow blocks and shaft couplings from McMaster Carr. The aluminum stock used for the motor and potentiometer mounts is 2" L Channel cut to the width of the center console and mounted using zip crews.

    20150202_215129.jpg 20150202_220143.jpg
    Sorry the pics are sideways. I've tried everything including rotating the originals but when I upload them they come out sideways???

    I used an Arduino Uno and a Seeed Studios V1 Motor Control shield to drive it. I chose the that Motor Control because it seemed to have one of the largest heat sinks. Their V2 also has a large heat sink but, it didn't lend itself to attaching a cooling fan as the V1. I still need to build a current limiter circuit for it. If I hook it up to a regulated 12V supply it will happily suck up 3Amps to drive the trim wheel and, in addition to pumping out crazy amounts of heat it also causes excessive vibration and noise as the trim wheel turns. I'm presently running it off my bench supply which has current limiting. By throttling it to about 1.2 amps it still develops enough torque to operate the trim wheel but with considerably less heat and noise. So now of course I need to build a current limiter that I can hook up to my sim pit power supply and install permanently in the Sim Pit.

    You'll see the Uno and Motor Shield to the right of the Mega and Proto Shield. To the right of that is is another uno/motor shield that runs the Whiskey Compass. I'll post info on that later after I get some good pics of it.
    400px-Smotoshield2.jpg20150127_082627.jpg

    Here are a couple videos of the setup in operation.

    Operated Manually:
    https://www.facebook.com/video.php?v=420928518067018

    Operated via the Auto Pilot:
    https://www.facebook.com/video.php?v=420928888066981

    And, here's the code:

    I still have several tweaks and improvements I want to make. But, for now it's functional so I'm on to the next thing...

    Code:
    // Stepper Motor Library
    #include AccelStepper eTrimStpr(AccelStepper::FULL4WIRE,8,11,12,13);
    
    //Servo Motor libraries because I am using a few I/O pins on this Arduino card for some extra functions, the flap position and outside air temp thermometer.
    
    #include 
    Servo flapServo;
    Servo tempServo;
    
    
    // I needed a function to scale values with decimal precision.  The MAP function is limited to integer values so I wrote my own. Here are the variables for it.
     
    int eTrimStpr_Scaler = 20;
    const float trmMpFrMin = 0.0;
    const float trmMpFrMax = 920.0;
    const float trmMpToMin = 100.0 * eTrimStpr_Scaler;
    const float trmMpToMax = -100.0 * eTrimStpr_Scaler;
    const float trmMpToDelta = 30;
    
    
    const int eTrimStprEnblA = 9;
    const int eTrimStprEnblB = 10;
    
    
    const int flpSrvDgOut = 5;
    const int tmpSrvDgOut = 6;
    
    
    boolean eTrimStprClbrt = HIGH;
    //boolean eTrimStprClbrt = LOW;
    int AP_Engaged = 0;
    int AP_AltLock = 0;
    
    
    String ExtVal;
    int ExtInt; 
    int CodeIn;
    
    
    int FSXTrimPstn = 0;
    int FSXTrimPstnLast = 1;
    int stpToPstn = 0;
    int eTrimPotPstn;
    float eTrimPotMap = 0.00;
    float eTrimPotMapLast = 1.00;
    
    
    int flpPstn = 0;
    int flpPstnLast = 0;
    
    
    int ambntTemp = 0;
    int ambntTempLast = 0;
    int ambntTempAdjst = +15;
    
    
    void setup(){
    
    
      pinMode(AP_AltLock,OUTPUT);
      digitalWrite(AP_AltLock, LOW);
    
    
      pinMode(eTrimStprEnblA,OUTPUT);
      pinMode(eTrimStprEnblB,OUTPUT);
      digitalWrite(eTrimStprEnblA, LOW);
      digitalWrite(eTrimStprEnblB, LOW);
    
    
      eTrimStpr.setMaxSpeed(400);
      eTrimStpr.setAcceleration(100);
    
    
      flapServo.attach(flpSrvDgOut);
      tempServo.attach(tmpSrvDgOut);
    
    
      Serial.begin(115200);
    }
    
    
    void loop() {
    
    
      {
        OTHER();
      }
      {
        SIMCONNECT();
      }
      {
        ENCODERS();
      }
    
    
      if (Serial.available()) { 
        CodeIn = getChar();
        if (CodeIn == '=') {
          EQUALS();
        } 
        if (CodeIn == '<') {
          LESSTHAN();
        }
        if (CodeIn == '?') {
          QUESTION();
        }
        if (CodeIn == '/') {
          SLASH();
        }
      }
    }
    
    
    void OTHER(){
    
    
      TRIM_POT_MAP(); // My mapping function
    
    
      if((AP_Engaged == 1 && AP_AltLock == 1) || eTrimStprClbrt == HIGH){  //Check status of Auto Pilot controls and enable the Stepper Motor if needed
        digitalWrite(eTrimStprEnblA, HIGH);
        digitalWrite(eTrimStprEnblB, HIGH);
        eTrimStpr.run();
      }
      else{
        digitalWrite(eTrimStprEnblA, LOW);
        digitalWrite(eTrimStprEnblB, LOW);
      }
    
    
    
    // If AP is off then sense the position of the trim wheel via the potentiometer.
    
    
      if(AP_AltLock == 0 && eTrimStprClbrt == LOW){
    
    // An almost equals function to limit excessive chatter of the trim sim connect feed  if the pot is between trim values
    // If the trim control has moved then send the appropriate number of trim steps to FSX via the Link2FS Si Connect functionality
    
    
        if(!almostEqual(eTrimPotMap,eTrimPotMapLast ,trmMpToDelta)){  
          if(eTrimPotMap > FSXTrimPstn){
            int IncSteps = (eTrimPotMap - eTrimPotMapLast) / eTrimStpr_Scaler;
           for(int fCnt=0;fCnt < IncSteps;fCnt++){
              Serial.println("C18"); //UP
              delay(10);
            }
          }
          else if(eTrimPotMap < FSXTrimPstn){
            int IncSteps = (eTrimPotMapLast - eTrimPotMap) / eTrimStpr_Scaler;
            for(int fCnt=0;fCnt < IncSteps;fCnt++){
              Serial.println("C19"); //DOWN
              delay(10);
            }
          }
          eTrimPotMapLast = eTrimPotMap;
          eTrimStpr.setCurrentPosition(eTrimPotMap * eTrimStpr_Scaler);
        }
    
    
    
    
      }
    }
    void SIMCONNECT(){
    
    
    }
    void ENCODERS(){
    
    
    }
    void EQUALS(){
    
    
      CodeIn = getChar();
    
    
      switch(CodeIn) {
    
    
      case 'a':
        GetString(1);
        AP_Engaged = ExtVal.toInt();
        if(AP_Engaged == 1){
        }
        else{
        }
        break;
    
    
      case 'k':
        GetString(1);
        AP_AltLock = ExtVal.toInt();
        if(AP_AltLock == 1){
        }
        else{
        }
        break;
    
    
      }  
    }
    void QUESTION(){     
      CodeIn = getChar();
      switch(CodeIn) {
        case 'c':            // Outside Air Temp Reading and servo motor control
        GetString(4);
        ambntTemp = ExtVal.toInt();
        if(ambntTemp != ambntTempLast){
          int srvoPstn = map(ambntTemp+ambntTempAdjst,-32,+58,+177,+10);
          tempServo.write(srvoPstn);
          ambntTempLast = ambntTemp;
        }
        break;
      }
    }
    void SLASH(){
    
    
    }
    
    
    void LESSTHAN(){
    
    
      CodeIn = getChar();
    
    
      switch(CodeIn) {
        
        case 'G':  // Flap Postion Indicator code
        GetString(3);
        flpPstn = ExtVal.toInt();
        if(flpPstn != flpPstnLast){
          int srvoPstn = map(flpPstn,0,100,127,42);
         flapServo.write(srvoPstn);
         flpPstnLast = flpPstn;
        }
        
        break;
    
    
      case 'H':  //Reads Trim position info from  FSX
        GetString(4);
        FSXTrimPstn = ExtVal.toInt() * eTrimStpr_Scaler;
        if(eTrimStprClbrt == HIGH){
          Calibrate_TrimPstnStpr();  //Run Trim Position Calibration function
        }
    
    
        if(FSXTrimPstn != FSXTrimPstnLast && eTrimStprClbrt == LOW){
          stpToPstn = (FSXTrimPstn - eTrimPotMap);
          eTrimStpr.move(stpToPstn);
        }
        else{
          if(eTrimPotMap != FSXTrimPstn){
            FineTuneStepper();
          }
        }
    
    
    
        FSXTrimPstnLast = FSXTrimPstn;
    
    
        break;
      }
    }
    
    
    
    
    void Calibrate_TrimPstnStpr(){
    
    
      //MOVEStepper();
      SyncStepper();
      SyncStepper();
      FineTuneStepper();
      
      TRIM_POT_MAP();
      FSXTrimPstnLast = FSXTrimPstn;
      FSXTrimPstnLast = eTrimPotMap;
      eTrimPotMapLast = eTrimPotMap;
      eTrimStprClbrt = LOW;
    }
    void SyncStepper(){
      
      TRIM_POT_MAP();
    
    
      eTrimStpr.setCurrentPosition(eTrimPotMap);
    
    
    stpToPstn = (FSXTrimPstn);
    
    
      digitalWrite(eTrimStprEnblA, HIGH);
      digitalWrite(eTrimStprEnblB, HIGH);
      eTrimStpr.moveTo(stpToPstn);
      while(eTrimStpr.currentPosition() != stpToPstn){
        eTrimStpr.run();
      }
      digitalWrite(eTrimStprEnblA, LOW);
      digitalWrite(eTrimStprEnblB, LOW);
      
    }
    
    
    void FineTuneStepper(){
    
    
      TRIM_POT_MAP();
      eTrimStpr.setCurrentPosition(eTrimPotMap);
    
    
    }
    
    
    
    
    boolean almostEqual(float a, float b, float DELTA) {
        return abs(a - b) <= DELTA;
      }
    char getChar()
    {
      while(Serial.available() == 0);
      return((char)Serial.read());
    }
    void GetString(int ChrCnt){
    
    
      ExtVal = "";                    // Clear Display Value Variable
      for(int fCnt=0;fCnt < ChrCnt;fCnt++){  // For Loop to retrieve extraction
        ExtVal += getChar();
        delay(10);
      }
    }
    
    
    void TRIM_POT_MAP(){
      
      eTrimPotPstn = analogRead(A1);
      eTrimPotMap = trmMpToMin +(eTrimPotPstn * ((trmMpToMax - trmMpToMin)/(trmMpFrMax - trmMpFrMin)));
      
    }
    Having mentioned the two additional servo motors I figure I should put a couple pics up.

    2012-11-21_00-26-31_342.jpg10885134_414726338687236_698576714425908078_n.jpg1510891_414726282020575_3632236000550445006_n.jpg
    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

  2. Likes Jim NZ liked this post
  3. #2
    500+ This must be a daytime job Jim NZ's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    764
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    This is great stuff Tom ,,, interesting how you actually done that.

    I'm going to have to have a check for updating the 'Noteable threads' ,,, this will be one.

    Keep at it Tom and thanks for sharing ,, Jim
    www.jimspage.co.nz/intro.htm
    All this and Liz still loves me ! !

  4. #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: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    Jim, Thanks!

    There are a couple improvements I would like to make in the code/functionality. I wonder if you have any thoughts on how I might accomplish the following:

    As you can see in my code, at present I read changes in the potentiometer and based on the amount of change send a corresponding number of trim up (C1 or trim down (C19) Sim Connect inputs to FSX. This works ok, but doesn't always track as accurately as I'd like.

    I would prefer to send an absolute position, a "set" value to FSX rather than increment it. Is this possible through Link2FS?

    If not directly I wonder if it's time for me to dive into the "Experts" section. I use FSUIPC quite a bit and dable in LUA code so I have a basic understanding of offsets and such.

    Your thoughts?

    Thanks!
    Tom G.
    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

  5. #4
    500+ This must be a daytime job Jim NZ's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    764
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    Yes Tom ,, your in luck ,, you can set the elevator trim directly using C62 ,, easy done.

    I am a bit curious tho ,,, is the position indicator worked off the handwheel (mechanically) or is it an entirely separate thing ???

    Cheers ,, Jim
    www.jimspage.co.nz/intro.htm
    All this and Liz still loves me ! !

  6. Thanks Tom_G_2010 thanked for this post
    Likes Tom_G_2010 liked this post
  7. #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: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    Jim,

    Just to be sure I cover both, there's a position indicator that the pilot can see when turning the trim wheel, and the position sensor I added to feed info to the Arduino. I'll go over both here in case I misunderstood your question.

    The trim wheel and the position indicator are linked mechanically and original Cessna parts. Cessna cuts a spiral groove across one side of the trim wheel and the position indicator rides in it like the tone arm of a record player as the record plays. It doesn't show in the pics or videos because it is on the opposite side of the trim wheel.

    For position sensor for the sim I am using a 10 turn 10k potentiometer which works out well given that the trim wheel has about 9.8 turns of rotation. If you look at the pics or video you'll notice the pot on a forward mounting bracket.

    The pot and stepper motor are mechanically linked via a chain drive. I was able to purchase sprockets for each that matched the size of the sprocket Cessna puts on the trim wheel so it all maintains a 1:1 ratio.

    Not sure how I missed C62 but glad to hear it's available. I'll be playing with some code tweaks to see if it works better than the current code. I'll post an update if I manage to make an improvement.


    Thanks!
    Tom G.

    PS: Just to repeat what I've said on more than a few occasions. Thanks for all that you've done for myself and the entire Sim Community. I can't imagine being able to accomplish all this without Link2FSMulti and your support!
    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. #6
    500+ This must be a daytime job Jim NZ's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    764
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    Ahhh I thought that might be the case Tom when I seen that 10 turn pot ,,, makes sense.
    Nice set-up.

    Thanks also for the kudos Tom ,, in actual fact the success of everything really goes to Guys like yourself and the other Guys that help in the forum ,,, without every-ones input we wouldn't have anything so my big thanks to all you Guys in return.

    Of course there is always the exception ,, at the moment there is a bit unrest in the Canadian division so I've had to get the old TU-95 out and head out that way ,, my theory being ,, to get in and out before they get their piper-cubs off the tundra.

    Back soon ,, Jim
    www.jimspage.co.nz/intro.htm
    All this and Liz still loves me ! !

  9. #7
    New Member
    Join Date
    Apr 2013
    Location
    United States
    Posts
    2
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    Hi Tom,

    Wow, great work on the autopilot trim wheel! I am working on something similar myself using an Arduino Uno, Seeed stepper driver, and a fairly large stepper motor from Sparkfun. I am running the motor driver at 5.5VDC and the motor runs pretty clean without noise and draws 1.76A peak.

    I tried to play around with your code a little but, but without an electrical reference, I am not sure exactly how you have wired your arduino to the stepper and trim wheel feedback potentiometer. Would you be willing to share some of these details with me? What other software is needed to get this to work with FSX? When compiling, I have issues with "eTrimStpr" and wondering if maybe I am missing a library.

    Are there any parts you are still trying to source for your simulator?

  10. #8
    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: My Cessna 172RG Elevator Trim and Auto Pilot Servo

    rrecce,

    Just a quick reply while stopping for lunch. I'll see if I have any wiring diagrams over the weekend. I may not since (as scary as this is) most of the wiring details are stored in my tiny little brain.

    In short though, beyond the mechanical hardware like chain, sprockets, shaft and, bearings it's fairly straight forward. The motor shield is piggy backed on the Uno and wired according to the shields documentation. I'm powering it with a current limited supply running at about the same range you mention and picking up position data via a 10 turn pot into an analog input of the Uno.
    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