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 2DOF Arduino Powered Race Sim

Discussion in 'DIY Motion Simulator Projects' started by ntbutler, Aug 16, 2017.

  1. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    G'day all from down here in Aus!

    Thought I should start documenting my little SIM frame project. I currently race in an Endurance Karting league, so my plan has been to build SIM frames for myself and my mates. I also run an electronics games night for a local youth group each year, which the driving *ahem* "sims" have been a big attraction at, so I've been aiming to build the frames in a way that both my mates and the littler kids can hop in to and adjust to fit.

    The basic design of the frames is meant to be similar to either a kart or an open wheeler racecar, that is, seated relatively low.

    In terms of build plan, my plan has been to build the frame for the driver to sit in, pedals, steering etc, and then at a later date, retro-fot it with a motion component. I've tried to build the frames as cheaply as I can, generally speaking. So far, I've made 4 of these frames for myself and my karting team mates, but none with motion capability, so at the time of writing this, I'm about to start the motion component of my own frame.

    In terms of my SIM gear currently, I have:
    • A cutsom build PC - Windows 8.1 x64, AMD FX-8350 * core CPU, 16GB RAM, 128GB SSD/ 256GB SSD, AMD Radeon R9 200 / HD 7970
    • Logitech G27 Steering Wheel
    • Oculus Rift DK2

    As a nice extra touch, I've recently added Arduino-powered rumble motors to the underside of the G27 pedals, which gives a great bit of extra sensation during racing. Check out the YouTube clip I followed at

    I've also done a bit of work on another little side project, particularly around the kids games night, with the aim of having RGB LED lights around the SIM frames, that light up depending on telemetry from Project Cars. I'll post details of this and the rest of the build below.
    • Like Like x 3
  2. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    OK, so I thought I'd start by adding a couple of my original plans that I drew up in Sketchup.

    Here is my first run at what I was going to aim for:
    sim_v1.png

    The plan shows just a basic 2DOF, Arduino controlled, rear-mounted worm-gear motor and CV joint setup. Importantly for what I was aiming for, the steering wheel position is adjustable both vertically and horizontally. I would have liked to add rotation/tilt on there too, but put that in the too-hard basket for the time being. Similarly, the pedal mount position can also be adjusted. This was achieved using 25x25mm Box Steel slides surrounding the 20x20mm box steel frame.

    Shortly after drawing that up, I saw another YouTube clip that outlined how to modify the G27 pedals so that they can be mounted upside down - link

    After seeing that, I ended up re-doing the sketchup design to incorporate inverted pedals. The below design shows just the moving part of the frame, as to be honest, the macbook air that I was designing this on really didn't like the amount of detail in the first design. I also ended up removing the seat from the design, as each of my mates that I was going to make a frame for wanted to do something different with the seat, so I just left that space completely empty. The pic below is basically exactly what I ended up building 4 times over (minor differences around the pedals mainly). I also added a floor pan for the drivers feet to sit on, which weren't in the pic.

    sim_v2.PNG


    Here's a couple of shots showing the build process when I made the third and fourth frames the same day.

    Two lots of each of the parts to make the frame all cut to size
    steel.JPG

    I had my brother teach me to Tig weld
    weld.JPG

    Here's two of the frames with the welding completed (except a few spot welds for the sheet metal for the pedal mounts and floor pans):
    weld2.JPG

    And spray painting to cover the admittedly crappy welds - hey, I'm only a beginner at this :)
    paint2.JPG

    With all that said and done, here's a couple of shots of my first frame to go to my team mate, then the first revision of my frame (more on this shortly), and then a nice pic of my boss taking the rig for a round at Monza when I recently brought it in to work.
    v1_completed.PNG
    sim2_completed.JPG
    boss.JPG

    In the interest of my computer not crapping out, I'll leave that post here and continue below..
    • Like Like x 1
    Last edited: Aug 17, 2017
  3. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    Cool. So at this point, I've built 4 frames (no motion). I'm about to go ahead and start the motion platform part of the build on my own personal rig. But I'd spoken to my mates and we'd all talked about how we'd really like to be lying back more, a bit like in an Formula 1 cockpit (my mates and I really enjoy the challenge of racing the Project Cars Formula A cars around the Bathurst circuit). So before I start on the motion build, I'd decided I'd modify my frame further to raise the drivers feet.

    So, what I ended up doing was cutting off the pedal supports (making sure not to cut the steering supports or sliders). I then added 45 degree angles that raised up to 220mm from ground level. After taking some time to make sure everything was parallel, level, etc, I welded new horizontal pedal supports that were raised, and with the supports at the end of the steering support, it's actually far more rigid than I expected. I also decided to leave the end open, so that the pedals can slide off. My hope in this is that, even as I design and build the motion part, it will be easy enough to disassemble and fit in the back of my sedan in parts, rather than having to get my hands on a ute/truck to move it anywhere.

    sim_v4.JPG

    With that design, I'm very happy with the feel in the seat, and also the range of adjustment to fit the size of the person in the seat. Having talked with one of my mates just yesterday, one change to this design that I would consider is to do away with much of the steering adjustment, and have a pillar in the centre (between the legs, more like a go kart) for the steering mount. This would make the rig a bit easier to get in and out of, as maneuvering your legs around the horizontal steering support can be a bit of a pain.
    Last edited: Aug 17, 2017
  4. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    At this point, I thought I might expand on the RGB LED light controller that I'd mentioned at the top.

    My original plan was just to have some lights that would get brighter as the driver went faster, and then would turn red when they hit the brake. This was partly a way for myself to get my head around using an Arduino, and once I (eventually) got the lights working, I ended up expanding the project to include a number of "modes", including:
    • Velocity (as mentioned, brighter as speed increased, red for braking, and also flashing red if the car was damaged beyond a certain point)
    • RPM
    • G-force
    • Current flags displaying on track
    • Rainbow mode (because why not, it's RGB after all)
    • Cops (that's right, red/blue flashing lights) :)
    To achieve all of this, I made heavy use of a great GitHub project called PCars by James Muscat - https://github.com/jamesremuscat/pcars. This hooks into the UDP stream from Project Cars, and lets you use Python to do what you want with the telemetry packet.

    With that, I created a little Python script that sent various bits of data to my Arduino Nano over the serial connection. Here's the code for that (note: this is pretty messy code, nothing really finalised at this stage, but proof of concept is working):

    Code:
    from pcars.stream import PCarsStreamReceiver
    from pcars.packet import Packet
    from pcars.packet import TelemetryPacket
    import serial
    import math
    import sys
    
    
    def serial_ports():
        if sys.platform.startswith('win'):
            ports = ['COM%s' % (i + 1) for i in range(256)]
        else:
            raise EnvironmentError('Unsupported platform')
    
        result = []
        for port in ports:
            try:
                s = serial.Serial(port)
                s.close()
                result.append(port)
            except (OSError, serial.SerialException):
                pass
        return result
    
    
    
    maxSpeed = 100 # mSpeed is in m/s. 350kph ~ 100m/s
    maxSendSpeed = 255
    rpmMappingFactor = 0.80
    
    class myTelemListener():
        def __init__(self):
            self.ser = serial.Serial("COM5", 115200, timeout=0)
     
        def handlePacket(self, packet):
         
            #print (isinstance(packet, TelemetryPacket))
            if (isinstance(packet, TelemetryPacket)):
                ## TO DO:
                # - if no current race, then report to serial and exit
                # - pass damage data
                rawMPS = packet["speed"]
                brake = math.ceil(packet["unfilteredBrake"])
                throttle = math.ceil(packet["unfilteredThrottle"])
                engineDamaged = math.ceil(packet["engineDamage"])
                aeroDamaged = math.ceil(packet["aeroDamage"])
                proportionalDamage = engineDamaged + aeroDamaged
                for tyre in packet["tyres"]:
                    proportionalDamage += tyre["suspensionDamage"] + tyre["brakeDamage"]
                rpm = packet["rpm"]
                if (rpm < packet["maxRpm"] * rpmMappingFactor):
                    rpm = 25
                else:
                    rpm = rpm - packet["maxRpm"] * rpmMappingFactor
                try:
                    rpm = math.ceil((rpm/(packet["maxRpm"]*(1-rpmMappingFactor)))*255)
                except:
                    rpm = 0
                gforceX = int(((abs(packet["localAccelerationX"] / 9.8))/6)*255)
                #gforceY = int(((abs(packet["localAccelerationY"] / 9.8))/6)*255) ##Vertical G's - probably ignore for now
                gforceZ = int(((abs(packet["localAccelerationZ"] / 9.8))/6)*255)
                highestFlag = packet["highestFlag"]
                maxGforce = max(gforceX,gforceZ)
                if (maxGforce > 255):
                    maxGforce = 255
                #print ("Damage: " + str(proportionalDamage) + "\t gX: " + str(gforceX) + "\t gY: " + str(gforceY) + "\t gZ: " + str(gforceZ))
    
                proportionalSpeed = (rawMPS/maxSpeed)*maxSendSpeed
                carSpeed = int(proportionalSpeed)
                serwriteval = "b" + format(brake, '03d') + "s" + format(carSpeed, '03d') + "t" + format(throttle, '03d') + "d" + format(proportionalDamage, '03d') + "r" + format(rpm, '03d') + "g" + format(maxGforce, '03d') + "f" + str(highestFlag) + "+"
                print (serwriteval)
                newVar = bytearray(serwriteval, "utf_8")
                if (self.ser.out_waiting >= 0): #there is still stuff that the arduino hasn't picked up
                    #print("PYTHON \t\t" + str(newVar))
                    self.ser.write(newVar)
                    self.ser.flush()
                #if (self.ser.inWaiting):
                    #print ("ARDUINO \tbytearray(" + str(self.ser.readline()) + "\n")
                else:
                    pass #discard it for now and give the arduino a chance to read
    
    def Main():
        pcarsStream = PCarsStreamReceiver()
        myListener = myTelemListener()
        pcarsStream.addListener(myListener)
        pcarsStream.run()
         
    if __name__ == '__main__':
        Main()

    And on the Arduino side, I wrote the following sketch that reads the serial data, parses it, and will play with the lights according to the current "mode", as outlined above.

    Code:
    /*  Global variables setup */
    /*** 7 seg display pins */
    const int SEG_A = 4;
    const int SEG_B = 13;
    const int SEG_C = 11;
    const int SEG_D = 10;
    const int SEG_E = 9;
    const int SEG_F = 7;
    const int SEG_G = 8;
    const int SEG_DP = 12;
    
    //PWM & other Pin Mappings
    const int MOSFET_PIN_BLUE = 3;  //blue MOSFET gate
    const int MOSFET_PIN_GREEN = 5; //green MOSFET gate
    const int MOSFET_PIN_RED = 6;   //red MOSFET gate
    const int ONBOARD_LED = 13;     //used for testing
    const int IN_SWITCH = 2;        //push button for switching modes
    
    //Telemetry variables
    String incomingSerial = "";
    int brake = 0;
    int speed_val = 0;
    int throttle_val = 0;
    int damaged_val = 0;
    int rpm_val = 0;
    int gforce_val = 0;
    int track_flag = 0;
    
    //Light and mode variables
    int speed_light_val = 0;
    float pulse_light_val = 10;
    float pulse_delta = 0.05;
    int EORlight = 0;
    int button_mode = 1;
    int current_lights_mode = 0;
    float HSVstep = 0;
    float copper_step = 0;
    
    //Light fade and flash sequences
    const uint8_t copper_sequence[180] ={
      1, 1, 1, 0, 1, 1, 0, 1, 0, 1,
      2, 2, 2, 2, 0, 0, 2, 0, 2, 2,
      1, 1, 1, 0, 2, 2, 1, 1, 0, 0,
      2, 2, 2, 0, 1, 1, 2, 2, 0, 0,
      1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
      2, 2, 0, 2, 0, 0, 2, 0, 2, 2,
      1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
      1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
      1, 0, 1, 0, 2, 2, 0, 2, 0, 1,
      1, 1, 1, 0, 1, 0, 0, 2, 2, 2,
      0, 1, 2, 0, 2, 1, 0, 2, 0, 0,
      1, 0, 0, 2, 0, 2, 2, 0, 1, 2,
      2, 2, 0, 2, 2, 2, 0, 1, 1, 1,
      0, 1, 1, 0, 1, 0, 2, 0, 1, 2,
      1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
      1, 1, 2, 2, 1, 1, 2, 2, 1, 2,
      0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
      0, 2, 0, 2, 0, 2, 0, 2, 0, 2};
    const uint8_t lights[360]={
      0,   0,   0,   0,   0,   1,   1,   2,
      2,   3,   4,   5,   6,   7,   8,   9,
    11,  12,  13,  15,  17,  18,  20,  22,
    24,  26,  28,  30,  32,  35,  37,  39,
    42,  44,  47,  49,  52,  55,  58,  60,
    63,  66,  69,  72,  75,  78,  81,  85,
    88,  91,  94,  97, 101, 104, 107, 111,
    114, 117, 121, 124, 127, 131, 134, 137,
    141, 144, 147, 150, 154, 157, 160, 163,
    167, 170, 173, 176, 179, 182, 185, 188,
    191, 194, 197, 200, 202, 205, 208, 210,
    213, 215, 217, 220, 222, 224, 226, 229,
    231, 232, 234, 236, 238, 239, 241, 242,
    244, 245, 246, 248, 249, 250, 251, 251,
    252, 253, 253, 254, 254, 255, 255, 255,
    255, 255, 255, 255, 254, 254, 253, 253,
    252, 251, 251, 250, 249, 248, 246, 245,
    244, 242, 241, 239, 238, 236, 234, 232,
    231, 229, 226, 224, 222, 220, 217, 215,
    213, 210, 208, 205, 202, 200, 197, 194,
    191, 188, 185, 182, 179, 176, 173, 170,
    167, 163, 160, 157, 154, 150, 147, 144,
    141, 137, 134, 131, 127, 124, 121, 117,
    114, 111, 107, 104, 101,  97,  94,  91,
    88,  85,  81,  78,  75,  72,  69,  66,
    63,  60,  58,  55,  52,  49,  47,  44,
    42,  39,  37,  35,  32,  30,  28,  26,
    24,  22,  20,  18,  17,  15,  13,  12,
    11,   9,   8,   7,   6,   5,   4,   3,
      2,   2,   1,   1,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0};
    
    /***********************
    * Lights fade through the HSV rainbow spectrum - independant of any telemetry data
    */
    void rainbow_step(){
      HSVstep = (HSVstep + 0.01);
      if (HSVstep >= 360){
          HSVstep = 0;
      }
      analogWrite(MOSFET_PIN_BLUE, lights[(int(HSVstep)+240)%360]);
      analogWrite(MOSFET_PIN_GREEN, lights[int(HSVstep)]);
      analogWrite(MOSFET_PIN_RED, lights[(int(HSVstep)+120)%360]);
    }
    
    /***********************
    * Lights flash red and blue - independant of any telemetry data
    */
    void cops(){
      copper_step += 0.005;
      if (copper_step > 180){
        copper_step = 0;
      }
      Serial.println(copper_step);
      analogWrite(MOSFET_PIN_BLUE, 255*(copper_sequence[int(copper_step)] == 1));
      analogWrite(MOSFET_PIN_GREEN, 0);
      analogWrite(MOSFET_PIN_RED,  255*(copper_sequence[int(copper_step)] == 2));
    }
    
    /***********************
    * Lights pulse red along with the current brake pedal value
    *    Precond: - brake must be 0-255
    */
    void brake_lights(){
      analogWrite(MOSFET_PIN_GREEN, 0);
      analogWrite(MOSFET_PIN_BLUE, 0);
      analogWrite(MOSFET_PIN_RED, brake);
    }
    
    /***********************
    * Lights pulse red if the car is damaged
    *    Precond: - only happens when function called - function doesn't look at damaged state
    */
    void damaged_lights(){
      //DAMAGED!!! Pulse red light
      pulse_light_val += pulse_delta;
      //quick data check
      if (pulse_light_val < 0){
        pulse_delta*= -1;
        pulse_light_val = 0;
      }
      else if (pulse_light_val > 255){
        pulse_delta*= -1;
        pulse_light_val = 255;
      }
      analogWrite(MOSFET_PIN_GREEN, 0);
      analogWrite(MOSFET_PIN_BLUE, 0);
      analogWrite(MOSFET_PIN_RED, pulse_light_val);
    }
    
    /***********************
    * Lights glow depending on the current car speed
    *    Precond: - speed_val must be 0-255
    *             - damaged_val must be 0-255
    */
    void velocity_lights(){
      if (brake < 30) {
        if (damaged_val < 15){    //If there isn't significant damage, light up like normal
          if (speed_val <= 80){
            analogWrite(MOSFET_PIN_BLUE, speed_val);
            analogWrite(MOSFET_PIN_GREEN, speed_val/2);
            analogWrite(MOSFET_PIN_RED, 0);
          }
          else if (speed_val <= 160) {
            analogWrite(MOSFET_PIN_BLUE, speed_val);
            analogWrite(MOSFET_PIN_GREEN, 40 + int((speed_val%80)*1.5));
            analogWrite(MOSFET_PIN_RED, (speed_val/2)%80);
          }
          else {
            pulse_light_val += pulse_delta;
            //quick data check
            if (pulse_light_val < 40){
              pulse_delta*= -1;
              pulse_light_val = 40;
            }
            else if (pulse_light_val > 255){
              pulse_delta*= -1;
              pulse_light_val = 255;
            }
            analogWrite(MOSFET_PIN_BLUE, pulse_light_val);
            analogWrite(MOSFET_PIN_GREEN, pulse_light_val);
            analogWrite(MOSFET_PIN_RED, pulse_light_val);
          }
        }
        else{ 
          damaged_lights();
        }
      }
      else {
        brake_lights();
      }
    }
    
    /***********************
    * Lights glow depending on the current engine RPM
    *    Precond: - rpm_val must be 0-255
    *             - damaged_val must be 0-255
    */
    void rpm_lights(){
      if (brake < 30) {
        if (damaged_val < 15){    //If there isn't significant damage, light up like normal
          analogWrite(MOSFET_PIN_BLUE, rpm_val);
          analogWrite(MOSFET_PIN_GREEN, rpm_val);
          analogWrite(MOSFET_PIN_RED, 0);
        }
       else{ 
          damaged_lights();
        }
      }
      else {
        brake_lights();
      }
    }
    
    /***********************
    * Lights glow depending on the current g-forces experienced
    *    Precond: - gforce_val must be 0-255
    *             - damaged_val must be 0-255
    */
    void gforce_lights(){
      if (damaged_val < 15){    //If there isn't significant damage, light up like normal
        analogWrite(MOSFET_PIN_BLUE, gforce_val);
        analogWrite(MOSFET_PIN_GREEN, gforce_val);
        analogWrite(MOSFET_PIN_RED, 0);
      }
      else{ 
        damaged_lights();
      }
    }
    
    
    /*******************
    * Lights display the current displayed track flags
    *    If there are no flags, cycle through RGB at this stage
    */
    void flag_lights(){
      switch (track_flag){
        case 0: //no flag. Display anything?
          pulse_light_val += pulse_delta;
          //quick data check
          if (pulse_light_val < 0){
            pulse_delta*= -1;
            pulse_light_val = 0;
            EORlight = (EORlight + 1)%3;
          }
          else if (pulse_light_val > 255){
            pulse_delta*= -1;
            pulse_light_val = 255;
          }
          analogWrite(MOSFET_PIN_GREEN, pulse_light_val*(EORlight == 0));
          analogWrite(MOSFET_PIN_BLUE, pulse_light_val*(EORlight == 1));
          analogWrite(MOSFET_PIN_RED, pulse_light_val*(EORlight == 2));
          break;
        case 1: //GREEN
          analogWrite(MOSFET_PIN_GREEN, 255);
          analogWrite(MOSFET_PIN_BLUE, 0);
          analogWrite(MOSFET_PIN_RED, 0);
          break;
        case 2: //BLUE
          analogWrite(MOSFET_PIN_GREEN, 0);
          analogWrite(MOSFET_PIN_BLUE, 255);
          analogWrite(MOSFET_PIN_RED, 0);
          break;
        case 3: //WHITE (approaching slow car)
          analogWrite(MOSFET_PIN_GREEN, 255);
          analogWrite(MOSFET_PIN_BLUE, 255);
          analogWrite(MOSFET_PIN_RED, 255);
          break;
        case 4: //YELLOW
          analogWrite(MOSFET_PIN_GREEN, 255);
          analogWrite(MOSFET_PIN_BLUE, 0);
          analogWrite(MOSFET_PIN_RED, 255);
          break;
        case 5: //DOUBLE YELLOW
            pulse_light_val += (pulse_delta*2);
            //quick data check
            if (pulse_light_val < 0){
              pulse_delta*= -1;
              pulse_light_val = 0;
            }
            else if (pulse_light_val > 255){
              pulse_delta*= -1;
              pulse_light_val = 255;
            }
          analogWrite(MOSFET_PIN_GREEN, pulse_light_val);
          analogWrite(MOSFET_PIN_BLUE, 0);
          analogWrite(MOSFET_PIN_RED, pulse_light_val);
          break;
        case 6: //BLACK (light up red I guess)
            pulse_light_val += (pulse_delta*3);
            //quick data check
            if (pulse_light_val < 0){
              pulse_delta*= -1;
              pulse_light_val = 0;
            }
            else if (pulse_light_val > 255){
              pulse_delta*= -1;
              pulse_light_val = 255;
            }
          analogWrite(MOSFET_PIN_GREEN, 0);
          analogWrite(MOSFET_PIN_BLUE, 0);
          analogWrite(MOSFET_PIN_RED, pulse_light_val);
          break;
        case 7: //CHEQUERED - go nuts?
            pulse_light_val += (pulse_delta*5);
            //quick data check
            if (pulse_light_val < 0){
              pulse_delta*= -1;
              pulse_light_val = 0;
              EORlight = (EORlight + 1)%3;
            }
            else if (pulse_light_val > 255){
              pulse_delta*= -1;
              pulse_light_val = 255;
            }
          analogWrite(MOSFET_PIN_GREEN, pulse_light_val*(EORlight == 0));
          analogWrite(MOSFET_PIN_BLUE, pulse_light_val*(EORlight == 1));
          analogWrite(MOSFET_PIN_RED, pulse_light_val*(EORlight == 2));
          break;
      }
    }
    
    void lights_off(){
      analogWrite(MOSFET_PIN_GREEN, 0);
      analogWrite(MOSFET_PIN_BLUE, 0);
      analogWrite(MOSFET_PIN_RED, 0);
    }
    
    /***********
    * Call the specific light up function we want.
    *  Input: Integer - colour mode to load
    */
    void do_lights(int mode){
      switch (mode){
        case 0:
          lights_off();
          break;
        case 1:              // Speed with damage
          velocity_lights();
          break;
        case 2:              // RPM with damage
          rpm_lights();
          break;
        case 3:              //Gforce with damage
          gforce_lights();
          break;
        case 4:              //Track flags
          flag_lights();
          break;
        case 5:              //Fade through rainbow (no telemetry needed)
          rainbow_step();
          break;
        case 6:              //Reb-blue flashing (no telemetry needed)
          cops();
          break;
      }
    }
    
    void set7segDisplay(int num){
      //set all off, and turn on the ones needed
      digitalWrite(SEG_A,LOW);
      digitalWrite(SEG_B,LOW);
      digitalWrite(SEG_C,LOW);
      digitalWrite(SEG_D,LOW);
      digitalWrite(SEG_E,LOW);
      digitalWrite(SEG_F,LOW);
      digitalWrite(SEG_G,LOW);
       //Conditions for displaying segment a
       if(num!=1 && num != 4)
      digitalWrite(SEG_A,HIGH);
    
       //Conditions for displaying segment b
       if(num != 5 && num != 6)
      digitalWrite(SEG_B,HIGH);
    
       //Conditions for displaying segment c
       if(num !=2)
       digitalWrite(SEG_C,HIGH);
    
       //Conditions for displaying segment d
       if(num != 1 && num !=4 && num !=7)
       digitalWrite(SEG_D,HIGH);
    
       //Conditions for displaying segment e
       if(num == 2 || num ==6 || num == 8 || num==0)
       digitalWrite(SEG_E,HIGH);
    
       //Conditions for displaying segment f
       if(num != 1 && num !=2 && num!=3 && num !=7)
       digitalWrite(SEG_F,HIGH);
       if (num!=0 && num!=1 && num !=7)
       digitalWrite(SEG_G,HIGH);
    
    }
    
    /*************
    * Momentary push button checker.
    *    Check for state change, and cycle through light modes when button released
    */
    void checkButtonPush(){
      // Check Digital pin to see if it's pressed.
      if ((digitalRead(IN_SWITCH) == LOW) && (button_mode == 1)){
          button_mode = 0; // Button is pressed.
         delay(100); //small delay to account for button bounce.
      }
      else if ((digitalRead(IN_SWITCH) == HIGH) && (button_mode == 0)){
        button_mode = 1; // Button is released.
        current_lights_mode = (current_lights_mode+1)%7;
        set7segDisplay(current_lights_mode);
        delay(100); //small delay to account for button bounce.
      }
    }
    
    /*************
    *   Set up pin modes, and set up the 7seg display
    */
    void setup() {
      Serial.begin(115200);
      pinMode(ONBOARD_LED, OUTPUT);       //not really needed - only for testing..
      pinMode(MOSFET_PIN_GREEN, OUTPUT);  //PWM pins
      pinMode(MOSFET_PIN_BLUE, OUTPUT);
      pinMode(MOSFET_PIN_RED, OUTPUT);
      pinMode(IN_SWITCH,INPUT);           //Push button switch (momentary)
      pinMode(SEG_A, OUTPUT);             //7seg display output pins
      pinMode(SEG_B, OUTPUT);
      pinMode(SEG_C, OUTPUT);
      pinMode(SEG_D, OUTPUT);
      pinMode(SEG_E, OUTPUT);
      pinMode(SEG_F, OUTPUT);
      pinMode(SEG_G, OUTPUT);
      pinMode(SEG_DP, OUTPUT);
      current_lights_mode = 0;
      set7segDisplay(current_lights_mode);
    }
    
    void loop() {
      /****************
       * Basic Program Flow:
       *  1. If there's new serial data, read and parse it
       *  2. Do a bit of bounds checking
       *  3. Play with the pretty lights
       */
      checkButtonPush();
    
      //STEP 1:
      if (Serial){                                      // Only bother doing anything if we have a serial connection
        if (Serial.available() > 0) {                   // OK,something came across serial
          incomingSerial = Serial.readStringUntil('+'); // read in everything until we see a "+" terminator
          /***********
           * Parse the data. We expect it in the current form:
           *    "b###s###t###d###r###g###+"
           *   = brake (0-255) speed (0-255) throttle (0-255) damaged (0-???) rpm (0-255) gForce (0-255)
           */
          if (incomingSerial[0] == 'b' && incomingSerial[4] == 's' && incomingSerial[8] == 't' && incomingSerial[12] == 'd' && incomingSerial[16] == 'r'  && incomingSerial[20] == 'g'  && incomingSerial[24] == 'f'){
            brake = (incomingSerial[1] - 48)*100 + (incomingSerial[2] - 48)*10 + (incomingSerial[3] - 48);
            speed_val = (incomingSerial[5] - 48)*100 + (incomingSerial[6] - 48)*10 + (incomingSerial[7] - 48);
            throttle_val = (incomingSerial[9] - 48)*100 + (incomingSerial[10] - 48)*10 + (incomingSerial[11] - 48);
            damaged_val = (incomingSerial[13] - 48)*100 + (incomingSerial[14] - 48)*10 + (incomingSerial[15] - 48);
            rpm_val =  (incomingSerial[17] - 48)*100 + (incomingSerial[18] - 48)*10 + (incomingSerial[19] - 48);
            gforce_val =  (incomingSerial[21] - 48)*100 + (incomingSerial[22] - 48)*10 + (incomingSerial[23] - 48);
            track_flag = (incomingSerial[25] - 48);
          }
        }
    
        //STEP 2:
        //quick data check
        if (speed_val < 0){
          speed_val = 0;
        }
        else if (speed_val > 255){
          speed_val = 255;
        }
        if (brake < 0){
          brake = 0;
        }
        else if (brake > 255){
          brake = 255;
        }
    
        //STEP 3:
        do_lights(current_lights_mode);
    
      }
      else { //No serial connection - best to do nothing?
       lights_off();
      }
    }

    The upshot of this is a pretty nifty, if I do say so myself, little light show. I then thought I'd have a go at trying to make a couple of these, so I can throw one to each of my mates if they want, or at least put one on each of the SIM rigs for the kids games night. To do this, I thought I'd have a shot at creating my own PCB for this (waaaaaaay overkill I know, but why not eh?).

    Attached are a couple of pictures of the progress. Unfortunately I pulled apart the breadboard I had the working prototype on, so no pics of that, but the general idea of it is that 3 of the PWM pins on the Nano drive 3 MOSFETs, supplying a modulated 12V signal to the 12V LED strips. I ended up 3D printing an enclosure for one - still need to alter a bit of the code to accommodate re-assigning of a couple of the pins, but not a bad first run IMHO.
    pcb1.JPG

    pcb3.JPG
    pcb4.JPG
    IMG_4437.JPG
    • Like Like x 2
    Last edited: Aug 17, 2017
  5. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    I thought I should add a couple of notes and pointers for some of the things that I've learned.

    1. As I have an Oculus Rift (DK2), I had originally designed and built this frame with that in mind. What that has meant though is that, for my mates who I've built this for, this rig unfortunately has a number of drawbacks, such as:
      1. No mount for an LCD monitor (note, not a problem for the kids night as I use projectors, but that's not really practical for my mates)
      2. No mount for keyboard or mouse controls
    2. For myself as well, I mainly use Project Cars, which has excellent VR support at this stage, so I've not needed keyboard/mouse controls. However with the recent release on steam of Kart Racing Pro, I've noticed that the VR menu controls are not as universal as I expected across the games, so I've found myself now having to think about adding some sort of keyboard or mouse mount, which I really hadn't planned for
    3. In the Sim_v4.jpg (hopefully embedded here this time), I have greatly reduced the amount of sheet metal that was in the original design. The pedals actually mount now on two strips of 20mm wide steel flat bar, and the floor pan is only about a quater of the size that the original one was. This has cut the weight of the whole rig WAAAAAY down.
      [​IMG]
    4. After having created the LED controller, adding the pedal rumble feature, etc, I'm finding that my computer is quickly running out of USB ports (2 taken for the Rift setup, 1 for the G27, keyboard, mouse, LED controller, rumble controller, soon to be 1 for SimTools). My plan now is to buy a powered USB3 HUB, and have this mounted underneath the tilt frame. If this is correctly located, it should be fast enough to handle a number of inputs/outputs through one cable to the desktop PC, and will give hopefully enough ports to give me keyboard and mouse input on the rig too.

    Also, if anyone knows if it's possible to go back and edit previous posts, please let me know :) - I was hoping to go back and fix up my earlier posts by embedding the pics where they were supposed to go, but I'm not having much luck..

    Cheers!
  6. noorbeast

    noorbeast VR Tassie Devil Staff Member Moderator Race Director

    Joined:
    Jul 13, 2014
    Messages:
    20,555
    Occupation:
    Innovative tech specialist for NGOs
    Location:
    St Helens, Tasmania, Australia
    Balance:
    145,148Coins
    Ratings:
    +10,780 / 52 / -2
    My Motion Simulator:
    3DOF, DC motor, JRK
    Yes you can edit your own posts, see here: https://www.xsimulator.net/community/faq/edit-your-own-posts.235/
  7. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    • Like Like x 1
  8. Ned

    Ned Member

    Joined:
    Jul 22, 2017
    Messages:
    63
    Occupation:
    fixed operations manager
    Location:
    melbourne
    Balance:
    714Coins
    Ratings:
    +31 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    Hello ntbutler your project is looking very good, you obviously look like you know what you are doing. I am also from Aus and also trying to build my own 2dof, the building and welding is no problem but I am struggling with the computer side of things it would be good if you were local to myself Victoria Mooroolbark as we could help each other where needed. I am sure your sim will be running well before mine, well done it looks awesome regards Ned ha ha sim.jpg
  9. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    G'day Ned!
    I'm in Sydney area, but happy to help out if I can. I'll be welding the frame this weekend, so starting the computer stuff in the next week, so happy to share anything I learn or to help out if you have questions.

    Where's your SIM build up to at this point? What sorts of gremlins are in the electronics?
  10. Ned

    Ned Member

    Joined:
    Jul 22, 2017
    Messages:
    63
    Occupation:
    fixed operations manager
    Location:
    melbourne
    Balance:
    714Coins
    Ratings:
    +31 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    Well Mr ntbutler you may regret asking that last question ha ha. Gremlins you ask, well I have downloaded Racingmats code for the Arduino UNO and input it to the Arduino board, with Arduino open on the computer if I press upload my sim jumps into action, but when I try and use sim tools to control it or to manually activate it or drive it, it sits motion less it has got me buggered but is more than likely my own fault as I am not a computer person. any help would be appreciated regards Ned
  11. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    Haha, no problem - my life is IT support, so happy to give it a go.
    As mentioned, I haven't yet got to the electronics part, but after this weekend I'll try to get stuck in and document it as well as possible.
  12. Ned

    Ned Member

    Joined:
    Jul 22, 2017
    Messages:
    63
    Occupation:
    fixed operations manager
    Location:
    melbourne
    Balance:
    714Coins
    Ratings:
    +31 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    That would be awesome step by step every detail, photos, Arduino codes used etc. Regards Ned
  13. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    So regretfully one of the motors I had ordered was DOA, and my motor supply shop is glacially slow at doing anything other than taking money. So the kids games night has come and gone for this year, without the motion rig operational.

    With that in mind, we powered on anyway and at least had some fun. Here's a couple of pics of some of the older kids enjoying the night. Hopefully next time we will have a collection of these rigs going - 2 doing driving sims, and one as an oculus-powered rollercoaster (No Limits 2) sim.

    DSC_0004.jpg DSC_0014.jpg
    DSC_0015.jpg
    • Like Like x 2
  14. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    Alrighty Mr Ned, looks like we're in a similar boat with the Arduino code from RacingMat. I've got everything wired up now, and I'm having some weird behaviour with testing.

    Basically, I'm just testing 1 pot/motor to make sure it's behaving properly. When I turn the pot one way, it kicks into gear pretty quickly. However, when i turn it the other way, it spins slowly for a second, then stops. I can turn the pot all the way to it's limit, and the motor just sits still. At that point I can't get it to do anything for a bit, then it comes back alive again.?

    I altered the code a bit in the motorMotion() function so I could read out what the actualPos, targetPos, gap and pwm variables were set at. From what I can see, the values are all being read properly by the arduino - everything there looks as expected.

    One thing I have done differently to the tutorial from RacingMat is that I've ended up having to stack my moto monster shield on top of my arduino (let's not get bogged down in who blew up what circuitry late one night...). My <ahem> replacement moto monster shield is not stacked, which means all pins are mapped 1-1 with the arduino. (A0 - A0, D1 - D1, etc)

    After doing a bit of digging through the Sparkfun documentation on the Moto Monster Shield,
    I found that pins A0 and A1 actually appear to be used for diagnostic outputs from the moto monster shield
    Screen Shot 2017-10-01 at 10.15.01 pm.png
    Screen Shot 2017-10-02 at 11.10.19 am.png

    So, what I think I need to do now is change up the code again so I can use A4 and A5 as the potentiometer inputs. Haven't had a chance to do this yet (currently it's stored elsewhere, so I'll get on that in the coming days).

    Anyway, that's where I'm currently stuck at. Have you, or anyone else, had any luck with RacingMat's arduino setup?
  15. noorbeast

    noorbeast VR Tassie Devil Staff Member Moderator Race Director

    Joined:
    Jul 13, 2014
    Messages:
    20,555
    Occupation:
    Innovative tech specialist for NGOs
    Location:
    St Helens, Tasmania, Australia
    Balance:
    145,148Coins
    Ratings:
    +10,780 / 52 / -2
    My Motion Simulator:
    3DOF, DC motor, JRK
    Last edited: Oct 2, 2017
  16. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    @noorbeast - yes they are wiper motors - thanks for pointing me to that article!

    I've been over and isolated both motors. Oddly enough, I still noticed some weird behaviour after isolating the motors, so I spent a bit of time looking deeper at what the Arduino was seeing (inputs from the pots and pwm signal strength, etc).

    Despite having linear pots, I noticed that the values that the arduino was seeing werent behaving exactly linearly as I turned the pot between max/min values. Also noticed that the pot didn't seem to be giving a steady signal (it was flicking between two values, say 512/513 etc). At this point, I decided to go with my hunch about the A0/A1 pins being used for other stuff.

    I de-soldered the pot wires from A0/A1 and soldered them instead to A4/A5. I then updated the pin numbers in the code, uploaded and tried again and everything seems to be running SOOO much smoother!

    I still need to test this further, but I haven't yet figured out the whole heatsink situation for the moto monster. Once that's sorted, I'll finish the testing and let you know how it all goes.

    I'd be interested if anyone has any pics for their own cooling solution. :)

    Cheers!
  17. noorbeast

    noorbeast VR Tassie Devil Staff Member Moderator Race Director

    Joined:
    Jul 13, 2014
    Messages:
    20,555
    Occupation:
    Innovative tech specialist for NGOs
    Location:
    St Helens, Tasmania, Australia
    Balance:
    145,148Coins
    Ratings:
    +10,780 / 52 / -2
    My Motion Simulator:
    3DOF, DC motor, JRK
  18. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    Hmm, looks like I may have spoken too soon. I've for a cooling solution in place, so I've been running the basic tests again, and looks like I have a problem somewhere in the arduino/moto monster setup.

    I've confirmed that the motor chassis' are isolated. I've also confirmed that the motors will turn at the same speed both ways when I connect them directly to a 12V power source.

    So I've been looking again at what is happening on the arduino. RacingMat's code doesn't actually initialise the cspins or the enpins, so I have initialised them as inputs and tried to see what is happening.

    What I've managed to determine is that everything seems to work just fine when the motor is being driven in the "Reverse" (RV or 2) direction. I wrote a bit of diagnostic output which (truncated version), you can see below. Basically, diagnosing just one motor (#1), the potentiometer position (pos) is read fine, gap/pwm/direction values are calculated OK, and good current sense values are read (it appears the EN/DIAG pin is always high).

    Code:
    mot1    pos512    tar512    gap0    pwm195    dir0    cs0    en1018 ---
    mot1    pos536    tar512    gap24    pwm195    dir2    cs725    en1018 ---
    mot1    pos540    tar512    gap28    pwm195    dir2    cs743    en1018 ---
    mot1    pos564    tar512    gap52    pwm215    dir2    cs619    en1018 ---
    mot1    pos566    tar512    gap54    pwm215    dir2    cs681    en1018 ---
    mot1    pos592    tar512    gap80    pwm235    dir2    cs666    en1018 ---
    mot1    pos596    tar512    gap84    pwm235    dir2    cs560    en1018 ---
    mot1    pos615    tar512    gap103    pwm255    dir2    cs590    en1017 ---
    mot1    pos617    tar512    gap105    pwm255    dir2    cs660    en1016 ---
    mot1    pos627    tar512    gap115    pwm255    dir2    cs629    en1017 ---
    
    However, everything seems to break down when the arduino tried to drive the motors in the "Forward" (FW or 1) direction. Below is a couple of seconds of capture. Basically, even though the arduino is correctly calculating everything and trying to drive the motor in the Forward direction, it is not seeing any current being fed from the moto monster for quite a while. Eventually it does kick in a bit of current, but that fades off pretty quickly. This is really weird as the same sort of thing appeard to be happening on my other moto monster shield, so I just don't know at this point.

    Code:
    mot1    pos493    tar512    gap19    pwm0    dir0    cs0    en1017 ---
    mot1    pos489    tar512    gap23    pwm195    dir1    cs0    en1018 ---
    mot1    pos486    tar512    gap26    pwm195    dir1    cs0    en1017 ---
    mot1    pos481    tar512    gap31    pwm195    dir1    cs0    en1017 ---
    mot1    pos478    tar512    gap34    pwm195    dir1    cs0    en1017 ---
    mot1    pos474    tar512    gap38    pwm195    dir1    cs0    en1018 ---
    mot1    pos471    tar512    gap41    pwm195    dir1    cs0    en1017 ---
    mot1    pos467    tar512    gap45    pwm195    dir1    cs0    en1017 ---
    mot1    pos465    tar512    gap47    pwm195    dir1    cs0    en1018 ---
    mot1    pos462    tar512    gap50    pwm195    dir1    cs0    en1018 ---
    mot1    pos459    tar512    gap53    pwm215    dir1    cs0    en1018 ---
    mot1    pos456    tar512    gap56    pwm215    dir1    cs0    en1017 ---
    mot1    pos454    tar512    gap58    pwm215    dir1    cs0    en1018 ---
    mot1    pos450    tar512    gap62    pwm215    dir1    cs0    en1018 ---
    mot1    pos448    tar512    gap64    pwm215    dir1    cs0    en1017 ---
    mot1    pos445    tar512    gap67    pwm215    dir1    cs0    en1017 ---
    mot1    pos442    tar512    gap70    pwm215    dir1    cs0    en1018 ---
    mot1    pos440    tar512    gap72    pwm215    dir1    cs0    en1018 ---
    mot1    pos437    tar512    gap75    pwm215    dir1    cs0    en1018 ---
    mot1    pos434    tar512    gap78    pwm235    dir1    cs0    en1017 ---
    mot1    pos431    tar512    gap81    pwm235    dir1    cs0    en1017 ---
    mot1    pos430    tar512    gap82    pwm235    dir1    cs0    en1017 ---
    mot1    pos426    tar512    gap86    pwm235    dir1    cs0    en1018 ---
    mot1    pos424    tar512    gap88    pwm235    dir1    cs0    en1018 ---
    mot1    pos421    tar512    gap91    pwm235    dir1    cs0    en1017 ---
    mot1    pos418    tar512    gap94    pwm235    dir1    cs0    en1018 ---
    mot1    pos416    tar512    gap96    pwm235    dir1    cs0    en1017 ---
    mot1    pos414    tar512    gap98    pwm235    dir1    cs0    en1018 ---
    mot1    pos410    tar512    gap102    pwm255    dir1    cs0    en1018 ---
    mot1    pos407    tar512    gap105    pwm255    dir1    cs0    en1017 ---
    mot1    pos403    tar512    gap109    pwm255    dir1    cs0    en1018 ---
    mot1    pos401    tar512    gap111    pwm255    dir1    cs0    en1017 ---
    mot1    pos398    tar512    gap114    pwm255    dir1    cs0    en1018 ---
    mot1    pos395    tar512    gap117    pwm255    dir1    cs0    en1017 ---
    mot1    pos392    tar512    gap120    pwm255    dir1    cs0    en1017 ---
    mot1    pos389    tar512    gap123    pwm255    dir1    cs0    en1018 ---
    mot1    pos386    tar512    gap126    pwm255    dir1    cs0    en1017 ---
    mot1    pos383    tar512    gap129    pwm255    dir1    cs0    en1018 ---
    mot1    pos380    tar512    gap132    pwm255    dir1    cs0    en1018 ---
    mot1    pos377    tar512    gap135    pwm255    dir1    cs0    en1017 ---
    mot1    pos379    tar512    gap133    pwm255    dir1    cs0    en1018 ---
    mot1    pos372    tar512    gap140    pwm255    dir1    cs0    en1017 ---
    mot1    pos369    tar512    gap143    pwm255    dir1    cs0    en1017 ---
    mot1    pos366    tar512    gap146    pwm255    dir1    cs0    en1018 ---
    mot1    pos363    tar512    gap149    pwm255    dir1    cs0    en1017 ---
    mot1    pos361    tar512    gap151    pwm255    dir1    cs0    en1017 ---
    mot1    pos358    tar512    gap154    pwm255    dir1    cs0    en1017 ---
    mot1    pos355    tar512    gap157    pwm255    dir1    cs0    en1017 ---
    mot1    pos353    tar512    gap159    pwm255    dir1    cs0    en1017 ---
    mot1    pos350    tar512    gap162    pwm255    dir1    cs0    en1017 ---
    mot1    pos347    tar512    gap165    pwm255    dir1    cs0    en1017 ---
    mot1    pos345    tar512    gap167    pwm255    dir1    cs0    en1017 ---
    mot1    pos341    tar512    gap171    pwm255    dir1    cs0    en1017 ---
    mot1    pos337    tar512    gap175    pwm255    dir1    cs0    en1017 ---
    mot1    pos335    tar512    gap177    pwm255    dir1    cs0    en1017 ---
    mot1    pos337    tar512    gap175    pwm255    dir1    cs0    en1018 ---
    mot1    pos329    tar512    gap183    pwm255    dir1    cs0    en1017 ---
    mot1    pos326    tar512    gap186    pwm255    dir1    cs0    en1017 ---
    mot1    pos323    tar512    gap189    pwm255    dir1    cs0    en1018 ---
    mot1    pos320    tar512    gap192    pwm255    dir1    cs0    en1018 ---
    mot1    pos318    tar512    gap194    pwm255    dir1    cs0    en1017 ---
    mot1    pos316    tar512    gap196    pwm255    dir1    cs0    en1017 ---
    mot1    pos313    tar512    gap199    pwm255    dir1    cs0    en1017 ---
    mot1    pos312    tar512    gap200    pwm255    dir1    cs0    en1017 ---
    mot1    pos309    tar512    gap203    pwm255    dir1    cs0    en1017 ---
    mot1    pos305    tar512    gap207    pwm255    dir1    cs0    en1017 ---
    mot1    pos302    tar512    gap210    pwm255    dir1    cs0    en1017 ---
    mot1    pos300    tar512    gap212    pwm255    dir1    cs0    en1017 ---
    mot1    pos299    tar512    gap213    pwm255    dir1    cs0    en1017 ---
    mot1    pos295    tar512    gap217    pwm255    dir1    cs0    en1017 ---
    mot1    pos292    tar512    gap220    pwm255    dir1    cs0    en1017 ---
    mot1    pos289    tar512    gap223    pwm255    dir1    cs0    en1017 ---
    mot1    pos287    tar512    gap225    pwm255    dir1    cs0    en1017 ---
    mot1    pos284    tar512    gap228    pwm255    dir1    cs0    en1018 ---
    mot1    pos280    tar512    gap232    pwm255    dir1    cs0    en1017 ---
    mot1    pos278    tar512    gap234    pwm255    dir1    cs0    en1018 ---
    mot1    pos275    tar512    gap237    pwm255    dir1    cs0    en1017 ---
    mot1    pos272    tar512    gap240    pwm255    dir1    cs0    en1017 ---
    mot1    pos269    tar512    gap243    pwm255    dir1    cs0    en1017 ---
    mot1    pos266    tar512    gap246    pwm255    dir1    cs0    en1017 ---
    mot1    pos263    tar512    gap249    pwm255    dir1    cs0    en1017 ---
    mot1    pos262    tar512    gap250    pwm255    dir1    cs0    en1017 ---
    mot1    pos258    tar512    gap254    pwm255    dir1    cs0    en1017 ---
    mot1    pos255    tar512    gap257    pwm255    dir1    cs0    en1017 ---
    mot1    pos252    tar512    gap260    pwm255    dir1    cs0    en1017 ---
    mot1    pos250    tar512    gap262    pwm255    dir1    cs0    en1017 ---
    mot1    pos250    tar512    gap262    pwm255    dir1    cs0    en1017 ---
    mot1    pos243    tar512    gap269    pwm255    dir1    cs0    en1017 ---
    mot1    pos241    tar512    gap271    pwm255    dir1    cs0    en1017 ---
    mot1    pos238    tar512    gap274    pwm255    dir1    cs0    en1017 ---
    mot1    pos235    tar512    gap277    pwm255    dir1    cs0    en1017 ---
    mot1    pos232    tar512    gap280    pwm255    dir1    cs0    en1018 ---
    mot1    pos234    tar512    gap278    pwm255    dir1    cs0    en1018 ---
    mot1    pos227    tar512    gap285    pwm255    dir1    cs0    en1017 ---
    mot1    pos226    tar512    gap286    pwm255    dir1    cs0    en1017 ---
    mot1    pos224    tar512    gap288    pwm255    dir1    cs0    en1017 ---
    mot1    pos221    tar512    gap291    pwm255    dir1    cs0    en1017 ---
    mot1    pos220    tar512    gap292    pwm255    dir1    cs0    en1018 ---
    mot1    pos217    tar512    gap295    pwm255    dir1    cs0    en1017 ---
    mot1    pos213    tar512    gap299    pwm255    dir1    cs0    en1018 ---
    mot1    pos212    tar512    gap300    pwm255    dir1    cs0    en1017 ---
    mot1    pos214    tar512    gap298    pwm255    dir1    cs23    en1017 ---
    mot1    pos209    tar512    gap303    pwm255    dir1    cs0    en1017 ---
    mot1    pos209    tar512    gap303    pwm255    dir1    cs0    en1017 ---
    mot1    pos206    tar512    gap306    pwm255    dir1    cs0    en1018 ---
    mot1    pos204    tar512    gap308    pwm255    dir1    cs0    en1017 ---
    mot1    pos201    tar512    gap311    pwm255    dir1    cs0    en1017 ---
    mot1    pos199    tar512    gap313    pwm255    dir1    cs0    en1017 ---
    mot1    pos197    tar512    gap315    pwm255    dir1    cs0    en1017 ---
    mot1    pos195    tar512    gap317    pwm255    dir1    cs0    en1017 ---
    mot1    pos193    tar512    gap319    pwm255    dir1    cs0    en1017 ---
    mot1    pos191    tar512    gap321    pwm255    dir1    cs0    en1018 ---
    mot1    pos190    tar512    gap322    pwm255    dir1    cs0    en1018 ---
    mot1    pos189    tar512    gap323    pwm255    dir1    cs0    en1018 ---
    mot1    pos188    tar512    gap324    pwm255    dir1    cs0    en1018 ---
    mot1    pos188    tar512    gap324    pwm255    dir1    cs0    en1018 ---
    mot1    pos188    tar512    gap324    pwm255    dir1    cs0    en1018 ---
    mot1    pos188    tar512    gap324    pwm255    dir1    cs0    en1018 ---
    mot1    pos188    tar512    gap324    pwm255    dir1    cs0    en1018 ---
    mot1    pos187    tar512    gap325    pwm255    dir1    cs0    en1018 ---
    mot1    pos188    tar512    gap324    pwm255    dir1    cs0    en1018 ---
    mot1    pos189    tar512    gap323    pwm255    dir1    cs0    en1017 ---
    mot1    pos190    tar512    gap322    pwm255    dir1    cs0    en1018 ---
    mot1    pos194    tar512    gap318    pwm255    dir1    cs0    en1018 ---
    mot1    pos194    tar512    gap318    pwm255    dir1    cs0    en1018 ---
    mot1    pos198    tar512    gap314    pwm255    dir1    cs0    en1017 ---
    mot1    pos201    tar512    gap311    pwm255    dir1    cs0    en1018 ---
    mot1    pos205    tar512    gap307    pwm255    dir1    cs0    en1018 ---
    mot1    pos210    tar512    gap302    pwm255    dir1    cs0    en1018 ---
    mot1    pos215    tar512    gap297    pwm255    dir1    cs0    en1017 ---
    mot1    pos221    tar512    gap291    pwm255    dir1    cs0    en1018 ---
    mot1    pos229    tar512    gap283    pwm255    dir1    cs0    en1018 ---
    mot1    pos236    tar512    gap276    pwm255    dir1    cs0    en1018 ---
    mot1    pos243    tar512    gap269    pwm255    dir1    cs0    en1017 ---
    mot1    pos251    tar512    gap261    pwm255    dir1    cs0    en1018 ---
    mot1    pos261    tar512    gap251    pwm255    dir1    cs0    en1018 ---
    mot1    pos269    tar512    gap243    pwm255    dir1    cs0    en1018 ---
    mot1    pos277    tar512    gap235    pwm255    dir1    cs0    en1017 ---
    mot1    pos286    tar512    gap226    pwm255    dir1    cs0    en1018 ---
    mot1    pos293    tar512    gap219    pwm255    dir1    cs0    en1018 ---
    mot1    pos309    tar512    gap203    pwm255    dir1    cs0    en1018 ---
    mot1    pos310    tar512    gap202    pwm255    dir1    cs0    en1017 ---
    mot1    pos319    tar512    gap193    pwm255    dir1    cs0    en1018 ---
    mot1    pos327    tar512    gap185    pwm255    dir1    cs0    en1018 ---
    mot1    pos333    tar512    gap179    pwm255    dir1    cs0    en1018 ---
    mot1    pos342    tar512    gap170    pwm255    dir1    cs0    en1018 ---
    mot1    pos349    tar512    gap163    pwm255    dir1    cs0    en1018 ---
    mot1    pos357    tar512    gap155    pwm255    dir1    cs0    en1018 ---
    mot1    pos363    tar512    gap149    pwm255    dir1    cs0    en1018 ---
    mot1    pos370    tar512    gap142    pwm255    dir1    cs0    en1018 ---
    mot1    pos375    tar512    gap137    pwm255    dir1    cs0    en1018 ---
    mot1    pos382    tar512    gap130    pwm255    dir1    cs0    en1018 ---
    mot1    pos387    tar512    gap125    pwm255    dir1    cs0    en1018 ---
    mot1    pos392    tar512    gap120    pwm255    dir1    cs0    en1017 ---
    mot1    pos398    tar512    gap114    pwm255    dir1    cs0    en1018 ---
    mot1    pos402    tar512    gap110    pwm255    dir1    cs0    en1017 ---
    mot1    pos406    tar512    gap106    pwm255    dir1    cs0    en1018 ---
    mot1    pos414    tar512    gap98    pwm235    dir1    cs42    en1017 ---
    mot1    pos415    tar512    gap97    pwm235    dir1    cs13    en1018 ---
    mot1    pos419    tar512    gap93    pwm235    dir1    cs48    en1018 ---
    mot1    pos423    tar512    gap89    pwm235    dir1    cs107    en1018 ---
    mot1    pos429    tar512    gap83    pwm235    dir1    cs43    en1019 ---
    mot1    pos434    tar512    gap78    pwm235    dir1    cs14    en1018 ---
    mot1    pos435    tar512    gap77    pwm235    dir1    cs49    en1018 ---
    mot1    pos439    tar512    gap73    pwm215    dir1    cs21    en1018 ---
    mot1    pos442    tar512    gap70    pwm215    dir1    cs74    en1018 ---
    mot1    pos445    tar512    gap67    pwm215    dir1    cs25    en1018 ---
    mot1    pos450    tar512    gap62    pwm215    dir1    cs81    en1018 ---
    mot1    pos455    tar512    gap57    pwm215    dir1    cs28    en1018 ---
    mot1    pos458    tar512    gap54    pwm215    dir1    cs74    en1018 ---
    mot1    pos461    tar512    gap51    pwm215    dir1    cs29    en1018 ---
    mot1    pos464    tar512    gap48    pwm195    dir1    cs82    en1018 ---
    mot1    pos467    tar512    gap45    pwm195    dir1    cs39    en1018 ---
    mot1    pos471    tar512    gap41    pwm195    dir1    cs54    en1018 ---
    mot1    pos474    tar512    gap38    pwm195    dir1    cs45    en1018 ---
    mot1    pos478    tar512    gap34    pwm195    dir1    cs36    en1018 ---
    mot1    pos480    tar512    gap32    pwm195    dir1    cs44    en1018 ---
    mot1    pos484    tar512    gap28    pwm195    dir1    cs38    en1017 ---
    mot1    pos489    tar512    gap23    pwm195    dir1    cs47    en1018 ---
    mot1    pos492    tar512    gap20    pwm0    dir0    cs0    en1018 ---
    mot1    pos495    tar512    gap17    pwm0    dir0    cs0    en1018 ---
    mot1    pos498    tar512    gap14    pwm0    dir0    cs0    en1018 ---
    mot1    pos501    tar512    gap11    pwm0    dir0    cs0    en1018 ---
    
    I'll keep digging and will check out some other posts, but if anyone has any ideas I'd be very appreciative of any thoughts you may have.

    Cheers!
  19. SeatTime

    SeatTime Well-Known Member

    Joined:
    Dec 27, 2013
    Messages:
    2,574
    Occupation:
    Retired
    Location:
    Brisbane Australia
    Balance:
    28,370Coins
    Ratings:
    +2,844 / 39 / -0
    My Motion Simulator:
    AC motor, Motion platform
    I'm a bit late to this conversation hope you have your current issue sorted - but for what you were building, just moving the seat, would have actually been better and allot less load on the motor and drivers/power supplies. Food for thought... a bit late I know :).
  20. ntbutler

    ntbutler New Member

    Joined:
    Aug 15, 2017
    Messages:
    20
    Location:
    Australia
    Balance:
    263Coins
    Ratings:
    +11 / 0 / -0
    My Motion Simulator:
    2DOF, Arduino
    I see your point - I'm planning on making another one at some point that will operate more for the No Limits 2 roller coaster sim, so i'll do that for that sim. This time around I thought it would be more important to have the pedals/steering wheel move along with the seat.

    That said, I haven't even connected the seat stuff to the motors yet - all this testing is without any load whatsoever..