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

Showroom Another 6DOF with DC motors and encoders inspired by Fly PT

Discussion in 'DIY Motion Simulator Projects' started by Gabriel the simracer, Jan 2, 2025.

  1. sci666

    sci666 Active Member Gold Contributor

    Joined:
    Mar 18, 2021
    Messages:
    197
    Location:
    Germany
    Balance:
    1,202Coins
    Ratings:
    +72 / 0 / -0
    My Motion Simulator:
    DC motor, Arduino, Motion platform, 6DOF
    :cheers cool :) it helps me a lot fpr programming also, i have another project in parallel for haptic guns for VR :D i used it for python programming from zero on .... i had some fails but after many iterations it works great so far for my prototype - its able to grab gunshot vibrations from openVR and sends it to a haptic device which simulates the recoil :) feels awesome in VR . i have to work on the prototyp and the weight management a bit ;) back to your brake .. so you want to use the brake only when u push an emergency button and not when the actuator just holds its position ? chatgpt suggest to do that if this happens to save energy. but i have no idea to achive that with a normal DC motor which has no internal brake mechanism ..so i would jsut built one without ....
    • Like Like x 1
  2. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino

    It's always great when you finish projects you've started with success!:cheersAs for the brake, initially, I thought about making it work while the actuator is at rest, but considering that activating the electromagnetic brake could cause a delay in the actuator's operation, I abandoned that idea. At the moment, I have all the brakes mechanically disconnected and I'm testing the rig this way. It seems that keeping the rig in a stationary position consumes very little energy, and soon I plan to install all the equipment onto the rig and then test whether the brakes will actually be useful for me.
    • Useful Useful x 1
  3. sci666

    sci666 Active Member Gold Contributor

    Joined:
    Mar 18, 2021
    Messages:
    197
    Location:
    Germany
    Balance:
    1,202Coins
    Ratings:
    +72 / 0 / -0
    My Motion Simulator:
    DC motor, Arduino, Motion platform, 6DOF
    makes sense :) do u use VR for Simracing as well ?
  4. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    Yes, I use Quest 3VR, but that depends which game i play, some of them works great with VR but others better play on triple screens.
  5. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    After a month-long break, I'm back to working on the platform.
    I managed to find someone locally who welded the aluminum top frame for me, and after a few days it was ready for pickup.
    20250317_211356.jpg

    The frame was ceremoniously connected to the actuators. Just in case, I secured the frame with a cargo strap for testing. And mounted few led strips on the bottom frame.
    20250320_100324.jpg
    Now I could test the platform under load for the first time.


    Next, a racing bucket seat was mounted to the frame,
    20250322_234635.jpg

    and then I built a frame for the steering wheel,
    20250408_212204.jpg

    as well as an extension for mounting the monitor.
    20250409_210740.jpg
    At this point, I also managed to build a frame for the pedals, and I was able to mount the basic equipment to the platform.
    20250410_222722.jpg

    And finally the weekend came – the time when I could hook up the VR to test the platform.
    20250412_215643.jpg
    After few hours of tests, everything feels great and need adjusting but seems to work well, so I can continue with more equipment to install on the platform.:)
    • Winner Winner x 2
  6. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    Today's update.
    Almost at the finish line. After fine-tuning the platform settings, I can say today that this project has brought me an incredible amount of joy. There are still a few things left to do, but even now I’m very happy that it’s almost complete. This project took me about 4 months to complete, mostly working in the evenings, with around a one-month break in between. I ran into a few software issues along the way, but I managed to resolve them. I’ll try to describe the final stages of the build soon.
    Best regards.

    • Winner Winner x 2
  7. itsumairu

    itsumairu Active Member

    Joined:
    Dec 13, 2021
    Messages:
    210
    Occupation:
    Psychologist
    Location:
    Indonesia
    Balance:
    447Coins
    Ratings:
    +91 / 2 / -0
    My Motion Simulator:
    2DOF, 3DOF, DC motor, Arduino
    hello.. I am very interested in the setup you created. Could you share the design of the 3D print you made? TIA
  8. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    "Hey, the project you're looking at here is a slightly modified version of the FlyPT project, which provides all the files for 3D printing as well as the dimensions of individual components.
    I only changed the way the motors are controlled, because when I decided to build it, I already had a few DC motors from a previous project, and I had to adapt the motor mounts in the actuators to fit them.
    Also, the motor control is based on encoders, as they are more reliable than multi-turn potentiometers. And I use Arduinos boards.

    Make sure to read the FlyPT thread carefully:
    https://www.xsimulator.net/community/threads/flypt-6dof-brushless-diy-actuators.10799/
    Feel free to reach out if you have any further questions."
    • Like Like x 1
  9. itsumairu

    itsumairu Active Member

    Joined:
    Dec 13, 2021
    Messages:
    210
    Occupation:
    Psychologist
    Location:
    Indonesia
    Balance:
    447Coins
    Ratings:
    +91 / 2 / -0
    My Motion Simulator:
    2DOF, 3DOF, DC motor, Arduino
    sorry to bother you again.
    for the software on arduino uno (SMC3), did you change it?
    and how the end stop switch working? should I change the code on SMC3?
    I really sucks on coding.
  10. Misanthrop

    Misanthrop Member

    Joined:
    Feb 5, 2024
    Messages:
    88
    Balance:
    514Coins
    Ratings:
    +39 / 1 / -0
    My Motion Simulator:
    6DOF
    Your Surge is working the wrong way round. When braking, the seat should move backwards.
    • Like Like x 1
  11. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    Basically, I'm using 3 Arduino boards, each of which controls 2 actuators. The SMC3 code is slightly modified due to interference that occurred during rapid direction changes, which caused the motors to shut off. I've automated the reactivation of the motors when the encoder signals remain within the operating range after shutdown. Apart from that modification, the program is original.

    Additionally, I have 2 Arduino Nanos running a separate program that receives signals from 6 encoders and converts them into 0–5V analog signals using the PW1VA01 DAC converter. They also perform actuator calibration and send the analog signals to the three main Arduino Uno boards. So, when there are no signal disturbances, the main Arduino Unos can run the original SMC3 software.

    These two extra Arduino Nanos were necessary due to the insufficient computing power of the Arduino Uno. FlyPT used two ESP32 Dev Kits in his project—I think two such boards would be perfectly sufficient here as well.

    Talk to ChatGPT to analyze the SMC3 code—it will teach you a lot. It also wrote all the necessary code for me. If it helps you, I can share my Arduino code.
    • Winner Winner x 1
  12. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    In a 6DOF simulator, it's not possible to simulate continuous acceleration (like 1g for 10 seconds) due to the platform's limited range of motion. That's why we use tilt coordination – a sensory trick that simulates acceleration through a subtle tilt of the platform.
    Guidelines for Setting Acceleration and Braking (Surge Axis - Forward/Backward)
    1. Acceleration (Surge Forward):
      • The platform tilts backwards (the user feels pressure into the seat back).

      • It can be preceded by a short forward "kick" (translational impulse).

      • This uses backward tilt along the pitch axis (or a combination of pitch and roll for more complex effects).
    2. Braking (Surge Backward):

      • The platform tilts forward (the user feels being thrown forward, like leaning into the seatbelt).

      • It can be preceded by a short backward jerk.
    See the video to understand more:
    • Winner Winner x 1
  13. itsumairu

    itsumairu Active Member

    Joined:
    Dec 13, 2021
    Messages:
    210
    Occupation:
    Psychologist
    Location:
    Indonesia
    Balance:
    447Coins
    Ratings:
    +91 / 2 / -0
    My Motion Simulator:
    2DOF, 3DOF, DC motor, Arduino
    I'll be glad if you can share your code. especially the use of two extra nanos. TIA
  14. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    Here you have the code for Arduino Nanos:
    Ask Chat GPT to analyze it for you then you know what line do what. All comment in the code are in polish so ask ChatGPT to translate them to language you prefer.
    Code:
    #include <EnableInterrupt.h>
    
    // Ustawienia pinów dla enkoderów i krańcówek
    const int pinA[] = {2, 4, 6};               // Piny A (przerwania)
    const int pinB[] = {3, 5, 7};               // Piny B
    const int analogOut[] = {11, 10, 9};        // Piny wyjściowe PWM
    const int limitSwitchUpper[] = {A0, A1, A2};  // Górne wyłączniki krańcowe
    const int limitSwitchLower[] = {A3, A4, A5};  // Dolne wyłączniki krańcowe
    
    // Pozycje enkoderów
    volatile long positions[3] = {400, 400, 400};
    long maxPosition[3] = {0, 0, 0};   // Dynamicznie ustalane maksymalne pozycje
    long minPosition[3] = {0, 0, 0};   // Dynamicznie ustalane minimalne pozycje
    
    // Przechowywanie ostatnich stanów pinów A i B
    int lastStateA[3] = {LOW, LOW, LOW};
    int lastStateB[3] = {LOW, LOW, LOW};
    
    // Debounce dla krańcówek
    unsigned long lastDebounceTime = 0;
    const int debounceDelay = 50;
    
    // Czas startu programu
    unsigned long startTime;
    
    // Ustawienia PWM
    int pwmValueUp = 110;  // 60% mocy
    int pwmValueDown = 130;  // 40% mocy
    int pwmStop = 123; // 50% - zatrzymanie silnika
    
    // Stan kalibracji
    enum CalibState { MOVING_UP, MOVING_DOWN, CALIBRATED };
    CalibState calibState[3] = {MOVING_UP, MOVING_UP, MOVING_UP};
    
    // Indeks aktualnie kalibrowanego siłownika
    int currentCalibratingIndex = 0;
    
    void setup() {
      Serial.begin(115200);
      delay(500); // Opóźnienie przed startem
    
      startTime = millis(); // Zapisanie czasu startu programu
    
      for (int i = 0; i < 3; i++) {
        pinMode(pinA[i], INPUT);
        pinMode(pinB[i], INPUT);
        pinMode(analogOut[i], OUTPUT);
        pinMode(limitSwitchUpper[i], INPUT_PULLUP);
        pinMode(limitSwitchLower[i], INPUT_PULLUP);
        
        // Aktywacja przerwań dla enkoderów
        enableInterrupt(pinA[i], (i == 0) ? encoderISR0 : (i == 1) ? encoderISR1 : encoderISR2, CHANGE);
        enableInterrupt(pinB[i], (i == 0) ? encoderISR0 : (i == 1) ? encoderISR1 : encoderISR2, CHANGE);
        
        lastStateA[i] = digitalRead(pinA[i]);
        lastStateB[i] = digitalRead(pinB[i]);
      }
    }
    
    void loop() {
      unsigned long currentTime = millis();
      if (currentCalibratingIndex < 3) {
        int i = currentCalibratingIndex;
        bool upperActive = (digitalRead(limitSwitchUpper[i]) == LOW);
        bool lowerActive = (digitalRead(limitSwitchLower[i]) == LOW);
    
        // Obsługa debounce dla krańcówek
        if (currentTime - lastDebounceTime > debounceDelay) {
          switch (calibState[i]) {
            case MOVING_UP:
              analogWrite(analogOut[i], pwmStop); // Zatrzymanie
              if (upperActive) {
                maxPosition[i] = positions[i]; // Zapisywanie maksymalnej pozycji
                analogWrite(analogOut[i], pwmStop); // Zatrzymanie
                delay(500);
                analogWrite(analogOut[i], pwmValueDown); // Przejście do ruchu w dół
                calibState[i] = MOVING_DOWN;
                lastDebounceTime = millis();
              }
              break;
    
            case MOVING_DOWN:
              analogWrite(analogOut[i], pwmValueDown); // Ruch w dół
              if (lowerActive) {
                minPosition[i] = positions[i]; // Zapisywanie minimalnej pozycji
                analogWrite(analogOut[i], pwmValueUp); // Przywrócenie normalnej pracy z ustawioną prędkością w górę
                calibState[i] = CALIBRATED;
                Serial.print("Aktuator ");
                Serial.print(i);
                Serial.println(" zakończył kalibrację.");
                lastDebounceTime = millis();
                currentCalibratingIndex++; // Przejście do kolejnego siłownika
              }
              break;
          }
        }
      } else {
        // Po kalibracji wszystkich siłowników
        for (int i = 0; i < 3; i++) {
          bool upperActive = (digitalRead(limitSwitchUpper[i]) == LOW);
          bool lowerActive = (digitalRead(limitSwitchLower[i]) == LOW);
          
          if (maxPosition[i] > minPosition[i]) {
            int pwmValue = map(positions[i], minPosition[i], maxPosition[i], 26, 230);
            pwmValue = constrain(pwmValue, 26, 230);
            analogWrite(analogOut[i], pwmValue);
          }
          if (upperActive) positions[i] = maxPosition[i];
          else if (lowerActive) positions[i] = minPosition[i];
        }
      }
    }
    
    // ISR dla enkoderów
    void encoderISR0() { handleEncoder(0); }
    void encoderISR1() { handleEncoder(1); }
    void encoderISR2() { handleEncoder(2); }
    
    void handleEncoder(int index) {
      int stateA = digitalRead(pinA[index]);
      int stateB = digitalRead(pinB[index]);
    
      // Dekodowanie kwadraturowe
      if (stateA != lastStateA[index]) {
        positions[index] += (stateA == stateB) ? 1 : -1;
      }
      lastStateA[index] = stateA;
      lastStateB[index] = stateB;
    }
    
    • Winner Winner x 1
  15. itsumairu

    itsumairu Active Member

    Joined:
    Dec 13, 2021
    Messages:
    210
    Occupation:
    Psychologist
    Location:
    Indonesia
    Balance:
    447Coins
    Ratings:
    +91 / 2 / -0
    My Motion Simulator:
    2DOF, 3DOF, DC motor, Arduino
    so how the reliability on the 3d printed slider?
    I really concern for this.
  16. Gabriel the simracer

    Gabriel the simracer Member

    Joined:
    Sep 2, 2023
    Messages:
    36
    Balance:
    - 81Coins
    Ratings:
    +50 / 0 / -0
    My Motion Simulator:
    3DOF, Arduino
    So far, I haven't noticed any issues. In his project, FlyPT removed the guides from the slider in order to avoid having to use bearings on the upper actuator mount. I used the version with guides and was considering whether I should glue the aluminum tubes to the slider, but in the end, I just bolted them on, and so far, there haven't been any problems either.
    • Like Like x 1