1. 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!
  2. 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
  3. 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 2DOF simulator - proof of concept model

Discussion in 'DIY Motion Simulator Projects' started by Iain Dodds, Oct 17, 2020.

  1. Iain Dodds

    Iain Dodds New Member

    Joined:
    Oct 7, 2020
    Messages:
    3
    Occupation:
    N/A
    Location:
    Michigan USA
    Balance:
    38Coins
    Ratings:
    +3 / 1 / -0
    My Motion Simulator:
    2DOF, Arduino, Motion platform
    I am in the process of build a 2DOF platform at scale to learn about simulator rig configurations, building and software.

    Started off with buying some simple core parts off of amazon.

    Bill of Material.
    • Hobbypark Metal Aluminum Long 25T Servo Horn Single Sided Steering Arm M3 Threads for RC Car Truck Off Road Buggy Accessories (Blue)
    horn.jpg
    • 2 Sets 20KG RC Digital Servo - Large Torque High Speed Full Metal Gear - Waterproof 180 Degree Servo Motor with 25T Servo Horn for RC Robotic Arm Model DIY Baja Car 1/10 Scale Crawler Truck
    servo.jpg
    • 10PCS ShareGoo Aluminum M3 Tie Rod End Ball Joint Link Ball Head Holder for Tamiya HSP Traxxas Axial SCX10 1/10 RC Car Truck Buggy Crawler
    ball-ends.jpg
    • ZXHAO 10mm/0.39" to 10mm/0.39" Inner Dia Rotatable Universal Steering Shaft U Joint Coupler
    coupler.jpg
    • uxcell M3 x 100mm 0.5mm Pitch 304 Stainless Steel Fully Threaded Rods Hardware 10 Pcs
    rods.jpg
    • Standard Servo Mounting Bracket/Protector (Silver Finish)
    servo-bracket.jpg
    • MakerBeam XL Regular Starter Kit Clear Anodized Including Beams (15x15mm), Brackets, Nuts and Bolts
    maker-xl-kit.jpg


    Software & Control

    Modified example Arduino code to work with Adafruit 16-Channel 12-bit PWM/Servo Shield - I2C interface.


    Initial Testing
    Video to come soon.....
  2. Ads Master

    Ads Master

    Balance:
    Coins
    Ratings:
    +0 / 0 / -0
  3. Iain Dodds

    Iain Dodds New Member

    Joined:
    Oct 7, 2020
    Messages:
    3
    Occupation:
    N/A
    Location:
    Michigan USA
    Balance:
    38Coins
    Ratings:
    +3 / 1 / -0
    My Motion Simulator:
    2DOF, Arduino, Motion platform
    • Like Like x 2
    • Old Old x 1
  4. ivan jack

    ivan jack New Member

    Joined:
    Mar 10, 2019
    Messages:
    3
    Balance:
    8Coins
    Ratings:
    +1 / 0 / -0
    My Motion Simulator:
    2DOF, 3DOF
    very nice ! Can you share the code please? I'm trying to do the same , but with stepper motors and adafruit v2.3
    • Like Like x 1
  5. noorbeast

    noorbeast VR Tassie Devil Staff Member Moderator Race Director

    Joined:
    Jul 13, 2014
    Messages:
    15,539
    Occupation:
    Innovative tech specialist for NGOs
    Location:
    St Helens, Tasmania, Australia
    Balance:
    113,929Coins
    Ratings:
    +9,125 / 46 / -2
    My Motion Simulator:
    3DOF, DC motor, JRK
  6. ivan jack

    ivan jack New Member

    Joined:
    Mar 10, 2019
    Messages:
    3
    Balance:
    8Coins
    Ratings:
    +1 / 0 / -0
    My Motion Simulator:
    2DOF, 3DOF
  7. Iain Dodds

    Iain Dodds New Member

    Joined:
    Oct 7, 2020
    Messages:
    3
    Occupation:
    N/A
    Location:
    Michigan USA
    Balance:
    38Coins
    Ratings:
    +3 / 1 / -0
    My Motion Simulator:
    2DOF, Arduino, Motion platform
    Here's my modified version of the code to make it work with the adafruit pwm hat.
    I commented out the portions from the original example so you can see where and how it was modified.

    Code:
    //********************************************************************************************
    // RC Model Servo
    // Original code By EAOROBBIE (Robert Lindsay)
    // Completely mangled by aarondc
    // PWM mod by Iain Dodds
    // For free use for Sim Tool Motion Software
    //********************************************************************************************
    
    #include <Wire.h>
    #include <Adafruit_PWMServoDriver.h>
    
    Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
    #define SERVOMIN  80// This is the 'minimum' pulse length count (out of 4096)
    #define SERVOMAX  850 // This is the 'maximum' pulse length count (out of 4096)
    #define USMIN  600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
    #define USMAX  2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
    #define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates
    
    uint8_t centerdegrees = 45;
    
    //#define DEBUG 1                                    // comment out this line to remove debuggin Serial.print lines
    const int kActuatorCount = 2;                       // how many Actuators we are handling
    
    // the letters ("names") sent from Sim Tools to identify each actuator
    // NB: the order of the letters here determines the order of the remaining constants kPins and kActuatorScale
    const char kActuatorName[kActuatorCount] = { 'R', 'L' };
    //const int kPins[kActuatorCount] = {4, 5};                       // pins to which the Actuators are attached
    const int kActuatorScale[kActuatorCount][2] = { { 0, 90 } ,    // Right Actuator scaling
                                                    { 90, 0 }      // Left side Actuator scaling
                                                   };     
    const char kEOL = '~';                              // End of Line - the delimiter for our acutator values
    const int kMaxCharCount = 3;                        // some insurance...
    //Servo actuatorSet[kActuatorCount];                  // our array of Actuators
    int actuatorSet[kActuatorCount] = {4, 5};
    
    int actuatorPosition[kActuatorCount] = {90, 90};    // current Actuator positions, initialised to 90
    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!!
    
    // 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 };   
    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);
        
        // put your setup code here, to run once:
        pwm.begin();
        pwm.setOscillatorFrequency(27000000);
        pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates
     
    
        double setpulselen = map(centerdegrees, 0, 180, SERVOMIN, SERVOMAX);
        pwm.setPWM(4, 0, setpulselen);
        pwm.setPWM(5, 0, setpulselen);
        delay(1000);
        
        
        Serial.begin(9600); // opens serial port at a baud rate of 9600
        Serial.println("Init Complete"); 
    }
     
    void loop()
    {
    
    }
    
    void serialEventRun(void) {
      if (Serial.available()) serialEvent();
    }
    
    
    // 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
                    // scale the new position so the value is between 0 and 179
                    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;
                }
            }
        }
    }
    
    
    double pulselen;
    // write the current Actuator position to the passed in Actuator
    void updateActuator(int thisActuator) {
        //Serial.print("actuatorSet[thisActuator]");
        //Serial.println(actuatorSet[thisActuator]);
        //Serial.print("actuatorPosition[thisActuator]");
        //Serial.println(actuatorPosition[thisActuator]);
    
      
        pulselen = map(actuatorPosition[thisActuator], 0, 180, SERVOMIN, SERVOMAX);
        pwm.setPWM(actuatorSet[thisActuator], 0, pulselen);
        
        //actuatorSet[thisActuator].write(actuatorPosition[thisActuator]);
    }
    • Useful Useful x 1
  8. noorbeast

    noorbeast VR Tassie Devil Staff Member Moderator Race Director

    Joined:
    Jul 13, 2014
    Messages:
    15,539
    Occupation:
    Innovative tech specialist for NGOs
    Location:
    St Helens, Tasmania, Australia
    Balance:
    113,929Coins
    Ratings:
    +9,125 / 46 / -2
    My Motion Simulator:
    3DOF, DC motor, JRK
    Nice one, added to the FAQs here, with credit to yourself: https://www.xsimulator.net/community/faq/build-a-working-model-to-test-your-design-ideas.216/