1. Do not share user accounts! Any account that is shared by another person will be blocked and closed. This means: we will close not only the account that is shared, but also the main account of the user who uses another person's account. We have the ability to detect account sharing, so please do not try to cheat the system. This action will take place on 04/18/2023. Read all forum rules.
    Dismiss Notice
  2. For downloading SimTools plugins you need a Download Package. Get it with virtual coins that you receive for forum activity or Buy Download Package - We have a zero Spam tolerance so read our forum rules first.

    Buy Now a Download Plan!
  3. Do not try to cheat our system and do not post an unnecessary amount of useless posts only to earn credits here. We have a zero spam tolerance policy and this will cause a ban of your user account. Otherwise we wish you a pleasant stay here! Read the forum rules
  4. We have a few rules which you need to read and accept before posting anything here! Following these rules will keep the forum clean and your stay pleasant. Do not follow these rules can lead to permanent exclusion from this website: Read the forum rules.
    Are you a company? Read our company rules

DIY RC Seat mover code issue

Discussion in 'DIY Motion Simulator Projects' started by J4S0N, Oct 16, 2022.

  1. J4S0N

    J4S0N New Member

    Joined:
    Jul 23, 2022
    Messages:
    5
    Balance:
    - 123Coins
    Ratings:
    +3 / 0 / -0
    Hi !

    Before attempting to build a full scale 2DOF seatmover, i wanted to try with the RC version first. I have an Arduino Leonardo Board as well as two small SG90 servomotors. Eventually I will switch to an Arduino Nano or Pro Micro for the big project.

    1665945776383.jpg 1665945776362.jpg

    I followed @eaorobbie's build :
    https://www.xsimulator.net/community/threads/rc-model-for-motion-simulation.4600/

    And tried to use his new code:
    https://www.xsimulator.net/community/marketplace/rc-model-code-for-arduino-uno-2dof-expandable.89/

    Simtools connects to LFS and display the virtual axis output but there is no output to the servos
    I then tried with the post's original code and it is now working, well partially, once the servos have to go past around 40% of the axis they start moving erratically to their maximums. I can limit the amount of axis used but if two movement are used, once the sum goes past a certain value it moves erratically again.

    Capture d’écran 2022-10-16 214715.jpg Capture d’écran 2022-10-16 214741.jpg

    I would like to make full use o the axis instead of having to limit them so if anyone could help me either make the new code work or solve the issue with the old code it would be awesome !

    Thank you to anyone who would pass by.
  2. Jumping Coin

    Jumping Coin Member Gold Contributor

    Joined:
    Aug 7, 2020
    Messages:
    93
    Balance:
    470Coins
    Ratings:
    +54 / 0 / -0
    Hi @J4S0N,

    Are you setting the range past 180 degrees?

    Not sure if this is helpful, but I made some minor edits to @aeorobbie's code to make it easier to modify, especially for G-seats where you might or might not want an actuator to respond to both sides of a DOF (i.e. acceleration and deceleration).

    Here goes. Best of luck!

    Code:
    /************************************************/
    // Title:    Pneumatic G-Seat using 4 servos (L, R, T, B); Office Chair Spin using 1 servo (S)
    // Function: For use with Simtools software, apply sway, surge, heave, traction loss
    // Code adapted from: https://www.xsimulator.net/community/threads/low-cost-2dof-3dof-6dof-motion-simulator-dof-reality.8570/page-43#post-166682,
    // which had been adapted from https://www.xsimulator.net/community/threads/rc-model-for-motion-simulation.4600/
    //
    /************************************************/
    /*
    Values for interface:
      Interface Type : Serial
      Comport : is at every individual
      BitsPerSec : 9600
      Data Bits : 8
      Parity : None
      Stop Bits : 1
      Bit Range : 8
      Output Type : Decimal
      Interface Output : L<Axis1a>~R<Axis2a>~T<Axis3a>~B<Axis4a>~S<Axis5a>~
      Output Rate : 10ms
    Pins:
      4 = Left   (L)
      5 = Right  (R)
      6 = Top    (T)
      7 = Bottom (B)
      8 = Spin   (S)
    */
    #include <Servo.h>
    /*******************************************************************************************
    Users may need to modify the below section. See variables:
        kActuatorCount
        kPins
        kActuatorName
        kPosAndNeg[kActuatorCount]
        kActuatorScale
    Please ensure that kActuatorCount matches the number of elements in the other variables in this section.
    *******************************************************************************************/
    // number of servos
    const int kActuatorCount = 5;
    // Initials for servos, must match Interface Output specified in GUI
    const char kActuatorName[kActuatorCount] = { 'L', //Left
                                                 'R', //Right
                                                 'T', //Top
                                                 'B', //Bottom
                                                 'S'  //Spin
                                               };
    //Pin locations on Arduino board
    const int kPins[kActuatorCount] = {4, 5, 6, 7, 8};
    /*kPosAndNeg allows you to specify whether a given servo will respond to only one side of a DOF, i.e. -100 to 0 or 0 to 100 (kPosAndNeg[i] = 0); or full range of a DOF, i.e -100 to 100 (kPosAndNeg[i] = 1).
     For example, if you only want the actuator to operate only on acceleration and not the braking for surge, then set kPosAndNeg[i] = 0
     If you want the actuator to activate across the whole range of acceleration and braking for surge, set kPosAndNeg[i] = 1
    */
    const int kPosAndNeg[kActuatorCount] = {0, 0, 0, 1, 1};
    //safe position aka starting position.  For G-seat, I want servos as open as possible for safety reasons.
    int actuatorPosition[kActuatorCount]={0, 0, 0, 0, 55};
    //Set range of position (i.e. servo range from 0 to 180)
    const int kActuatorScale[kActuatorCount][2] = {
                                                      {0, 180},
                                                      {0, 180},
                                                      {0, 180},
                                                      {0, 180},
                                                      {0, 110} //limit spin scale to ensure uniformity for left and right based on position relative to seat
                                                  };     
    /********************************************************************************************
    End of modification section.  No need to modify anything below for g-seat or servo-based simulators
    ********************************************************************************************/
    Servo actuatorSet[kActuatorCount];                  // our array of Actuators
    const char kEOL = '~';                              // End of Line - the delimiter for our acutator values
    const int kMaxCharCount = 3;                        // some insurance...
    // set up some states for our state machine
    // psReadActuator = next character from serial port tells us the Actuator
    // psReadValue = next 3 characters from serial port tells us the value
    enum TPortState
    {
      psReadActuator,
      psReadValue
    };   
    int currentActuator;                                // keep track of the current Actuator being read in from serial port
    int valueCharCount = 0;                             // how many value characters have we read (must be less than kMaxCharCount!!
    TPortState currentState = psReadActuator;
    void setup()
    {
        // attach the Actuators to the pins
        for (int i = 0; i < kActuatorCount; i++)
            actuatorSet[i].attach(kPins[i]);
        // initialise actuator position
        for (int i = 0; i < kActuatorCount; i++)
            updateActuator(i);
        
        Serial.begin(9600); // opens serial port at a baud rate of 9600
    }
    /*************************************************/
    void loop()
    {
    }
    /**************************************************/
    // write the current Actuator position to the passed in Actuator
    void updateActuator(int thisActuator) {
        int safePos;
        safePos=actuatorPosition[thisActuator];
        actuatorSet[thisActuator].write(safePos);
    }
    // this code only runs when we have serial data available. ie (Serial.available() > 0).
    void serialEvent() {
        char tmpChar;
        int tmpValue;
     
        while (Serial.available()) {
            // if we're waiting for a Actuator name, grab it here
            if (currentState == psReadActuator) {
                tmpChar = Serial.read();
                // look for our actuator in the array of actuator names we set up
                #ifdef DEBUG           
                  Serial.print("read in ");           
                  Serial.println(tmpChar);           
                #endif
                for (int i = 0; i < kActuatorCount; i++) {
                    if (tmpChar == kActuatorName[i]) {
                        #ifdef DEBUG           
                            Serial.print("which is actuator ");           
                            Serial.println(i);           
                        #endif
                        currentActuator = i;                        // remember which actuator we found
                        currentState = psReadValue;                 // start looking for the Actuator position
                        actuatorPosition[currentActuator] = 0;      // initialise the new position
                        valueCharCount = 0;                         // initialise number of value chars read in
                        break;
                    }
                }
            }
          
            // if we're ready to read in the current Actuator's position data
            if (currentState == psReadValue) {
                while ((valueCharCount < kMaxCharCount) && Serial.available()) {
                    tmpValue = Serial.read();
                    if (tmpValue != kEOL) {
                        tmpValue = tmpValue - 48;
                        if ((tmpValue < 0) || (tmpValue > 9)) tmpValue = 0;
                        actuatorPosition[currentActuator] = actuatorPosition[currentActuator] * 10 + tmpValue;
                        valueCharCount++;
                    }
                    else break;
                }
              
                // if we've read the value delimiter, update the Actuator and start looking for the next Actuator name
                if (tmpValue == kEOL || valueCharCount == kMaxCharCount) {
     
                    #ifdef DEBUG           
                        Serial.print("read in ");           
                        Serial.println(actuatorPosition[currentActuator]);           
                    #endif
     
                    //if kPosAndNeg[i] == 0, then apply servo to only one side of a DOF (i.e -100 to 0 or 0 to 100)
                    if (kPosAndNeg[currentActuator] == 0)
                    {
                        //No -ve on G-seat : 90 = middle
                        if (actuatorPosition[currentActuator]<127)
                        {
                            actuatorPosition[currentActuator]=127;
                        }
                        // scale the new position
                        // Range is now 0 - 255
                        // Maps between min and max
                        actuatorPosition[currentActuator] = map(actuatorPosition[currentActuator], 127, 255, kActuatorScale[currentActuator][0], kActuatorScale[currentActuator][1]);
                    }
                    //else kPosAndNeg[i] == 1, so apply servo to full range of DOF (i.e. -100 to 100).
                    else
                    {
                        actuatorPosition[currentActuator] = map(actuatorPosition[currentActuator], 0, 255, kActuatorScale[currentActuator][0], kActuatorScale[currentActuator][1]);
                    }
                  
                    #ifdef DEBUG           
                        Serial.print("scaled to ");           
                        Serial.println(actuatorPosition[currentActuator]);           
                    #endif
     
                    updateActuator(currentActuator);
                    currentState = psReadActuator;
                }
            }
        }
    }
    • Useful Useful x 1
  3. J4S0N

    J4S0N New Member

    Joined:
    Jul 23, 2022
    Messages:
    5
    Balance:
    - 123Coins
    Ratings:
    +3 / 0 / -0
    Hi @Jumping Coin ,

    Thank you for your time, I tried to inject your code adapted for my 2 servos but sadly there is no output when testing. Somehow, my rig only works with 1 code.

    I will dig into it a bit more but at some point I will just try with an IBT2, a small motor and SMC3.