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

Lesson SimTools v3 - 3D Wind Dash Example (with Arduino Sketch)

Discussion in 'Tutorials and Tips by the Developer' started by yobuddy, Jun 19, 2023.

  1. Mirko

    Mirko New Member

    Joined:
    Jan 31, 2026
    Messages:
    3
    Balance:
    29Coins
    Ratings:
    +1 / 0 / -0
    My Motion Simulator:
    2DOF, DC motor
    I wonder, if the 3d-fan can get combined with the SMC3 ("Simulator Motor Controller for 3 Motors"), so going for one Arduino only?
    And I haven'T been able to get to the Dash Setup in SimTools. Where can I find that entry-point? Any Plugin to be installed first? In "Interface Setup" I have only 6x Motion Setup.
  2. noorbeast

    noorbeast VR Tassie Devil Staff Member Moderator Race Director

    Joined:
    Jul 13, 2014
    Messages:
    22,022
    Occupation:
    Innovative tech specialist for NGOs
    Location:
    Tasmania, Australia
    Balance:
    153,728Coins
    Ratings:
    +11,148 / 57 / -2
    My Motion Simulator:
    3DOF, DC motor, JRK
    See page 108 of the SimTools manual re Dash setup: https://simtools.us/wp-content/uploads/2024/02/SimTools-v3.pdf
  3. _cOdaC_

    _cOdaC_ Member

    Joined:
    Dec 20, 2023
    Messages:
    63
    Balance:
    325Coins
    Ratings:
    +9 / 0 / -0
    My Motion Simulator:
    3DOF, DC motor, Arduino
    For everybody struggling as hard as me to get this thing running, I hope this helps.
    I'm using this 3D print and this fan.
    Whatever fan you are using, for this solution, please make sure you use a fan with two cables (red/black; not 4 cables for example).
    Furthermore, I'm using this Adafruit Motorshield v2.3 and an Arduino Uno.
    As you are supposed to use an additional power supply, I chose a 12V, 3A power supply. Make sure that the length of the cable is sufficient.

    Attach one Fan to M1 on the motorshield (red cable) and GND (black cable), attach the other fan on M3 (Yes, M3, not M2, as this way you are using two seperate chips on the motorshield) with the red cable and GND with the black cable.
    The power supply that I have uses a cable adapter with plus and minus pole. So I don't need to cut any cables. You can simply put the power plug into the adapter. From that adapter attach a short red cable to the plus pole and a black cable to the minus pole. From those two cables go to the two-pin on the side of the motorshield and attach the red cable to the plus pole and the black cable to the minus pole.
    Screenshot 2026-02-06 111349.png
    Later on you can simply attach the adapter onto the bottom of the top of the Arduino case.
    Don't forget to attach the motorshield on top of the arduino uno.

    In Arduin IDE, install the Adafruit_Motorshield library.
    I'm using a slightly modified version of the code based on the post of @offman
    This is the code I use:
    Code:
    // Arduino code to achieve wind simulation with the Adafruit Motor Shield V2
    // Supports right,left and traditional serial speed output from GameDash (R000, L000, S000)
    // Wire fans to M1 (Left) and M3 (Right)
    //
    // Based on your working version + adopted logic for independent L/R targets.
    
    #include <Wire.h>
    #include <Adafruit_MotorShield.h>
    
    #define FALSE 0
    #define TRUE  1
    #define BOTH  0
    #define LEFT  1
    #define RIGHT 2
    
    #define Idlespeed 0
    #define MIN_RUN_SPEED 80   // typischer Bereich 70–110
    #define START_KICK_SPEED 255
    #define START_KICK_MS 600
    
    int bufferArray[4];
    int whichFan = BOTH;
    
    // --- NEW: independent targets ---
    int leftSpeed  = 0;
    int rightSpeed = 0;
    
    // --- NEW: per-fan last speed for start-kick detection ---
    int lastLeftSpeed  = 0;
    int lastRightSpeed = 0;
    
    // Create the motor shield object with the default I2C address
    Adafruit_MotorShield AFMS = Adafruit_MotorShield();
    
    // Set port M1 for Motor 1 (Left fan)
    Adafruit_DCMotor *Motor1 = AFMS.getMotor(1);
    // Set port M3 for Motor 3 (Right fan)
    Adafruit_DCMotor *Motor3 = AFMS.getMotor(3);
    
    void setup()
    {
      AFMS.begin();
      Serial.begin(9600);
    
      // Start silent (Idlespeed=0)
      Motor1->setSpeed(0); Motor1->run(RELEASE);
      Motor3->setSpeed(0); Motor3->run(RELEASE);
    }
    
    void loop()
    {
      // Read one full command (S/L/R + 3 digits) and update targets
      ReadDataAndUpdateTargets();
    
      // Apply per-fan MIN_RUN_SPEED (only when >0)
      int applyLeft  = leftSpeed;
      int applyRight = rightSpeed;
    
      if (applyLeft  > 0 && applyLeft  < MIN_RUN_SPEED) applyLeft  = MIN_RUN_SPEED;
      if (applyRight > 0 && applyRight < MIN_RUN_SPEED) applyRight = MIN_RUN_SPEED;
    
      // ---- LEFT FAN (M1) ----
      if (applyLeft == 0)
      {
        Motor1->setSpeed(0);
        Motor1->run(RELEASE);
      }
      else
      {
        // Start-Kick only when coming from stop
        if (lastLeftSpeed == 0)
        {
          Motor1->run(FORWARD);
          Motor1->setSpeed(START_KICK_SPEED);
          delay(START_KICK_MS);
        }
        Motor1->run(FORWARD);
        Motor1->setSpeed(applyLeft);
      }
    
      // ---- RIGHT FAN (M3) ----
      if (applyRight == 0)
      {
        Motor3->setSpeed(0);
        Motor3->run(RELEASE);
      }
      else
      {
        // Start-Kick only when coming from stop
        if (lastRightSpeed == 0)
        {
          Motor3->run(FORWARD);
          Motor3->setSpeed(START_KICK_SPEED);
          delay(START_KICK_MS);
        }
        Motor3->run(FORWARD);
        Motor3->setSpeed(applyRight);
      }
    
      // Update last speeds (use the actually applied ones)
      lastLeftSpeed  = applyLeft;
      lastRightSpeed = applyRight;
    }
    
    void ReadDataAndUpdateTargets()
    {
      // We need 4 characters - the command followed by three digits
      bool haveCommand = FALSE;
      bool haveStart   = FALSE;
    
      while (haveCommand == FALSE)
      {
        // Valid command always starts with S, L, or R
        while (haveStart == FALSE)
        {
          while (Serial.available() == 0);   // wait for data
          bufferArray[0] = Serial.read();
    
          if (bufferArray[0] == 'S')
          {
            whichFan = BOTH;
            haveStart = TRUE;
          }
          else if (bufferArray[0] == 'L')
          {
            whichFan = LEFT;
            haveStart = TRUE;
          }
          else if (bufferArray[0] == 'R')
          {
            whichFan = RIGHT;
            haveStart = TRUE;
          }
        }
    
        // Read three digits
        for (int i = 1; i < 4; i++)
        {
          while (Serial.available() == 0);
          bufferArray[i] = Serial.read();
        }
    
        // Validate digits
        if (isDigit(bufferArray[1]) && isDigit(bufferArray[2]) && isDigit(bufferArray[3]))
        {
          haveCommand = TRUE;
        }
        else
        {
          // resync
          haveStart = FALSE;
        }
      }
    
      int spd = ((bufferArray[1] - '0') * 100) +
                ((bufferArray[2] - '0') * 10)  +
                ((bufferArray[3] - '0') * 1);
    
      if (spd > 255) spd = 255;
      if (spd < Idlespeed) spd = Idlespeed; // Idlespeed is 0
    
      // --- Adopted logic: update targets instead of one global Speed ---
      if (whichFan == BOTH)
      {
        leftSpeed  = spd;
        rightSpeed = spd;
      }
      else if (whichFan == LEFT)
      {
        leftSpeed = spd;
      }
      else if (whichFan == RIGHT)
      {
        rightSpeed = spd;
      }
    }
    
    I have not finally tested it, I tried to add a left / right handling on the fans, I don't know if it actually works.

    Upload this sketch to your Arduino Uno.

    Now lets get to the SimTools settings:
    Screenshot 2026-02-06 112035.png Screenshot 2026-02-06 112054.png Screenshot 2026-02-06 112107.png Screenshot 2026-02-06 112120.png Screenshot 2026-02-06 112133.png

    The settings are still not perfectly set up (for my point of view). But at least this is a working setup and the rest is fine tuning.

    Hope that helps, have fun.
    • Informative Informative x 1