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 FlyPT - 6DOF Brushless DIY Actuators

Discussion in 'DIY Motion Simulator Projects' started by pmvcda, Aug 29, 2017.

  1. Gadget999

    Gadget999 Well-Known Member

    Joined:
    Dec 27, 2015
    Messages:
    1,936
    Location:
    London
    Balance:
    11,844Coins
    Ratings:
    +474 / 9 / -0
    My Motion Simulator:
    2DOF, DC motor, Arduino, 6DOF
    this is a really nicely built rig, are you an engineer ?

    do the actuators have enough speed for a car driving sim ?
  2. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    Yes (mechanical) an yes...
    Last yes, it's almost 300mm/s.
    • Like Like x 2
  3. Gadget999

    Gadget999 Well-Known Member

    Joined:
    Dec 27, 2015
    Messages:
    1,936
    Location:
    London
    Balance:
    11,844Coins
    Ratings:
    +474 / 9 / -0
    My Motion Simulator:
    2DOF, DC motor, Arduino, 6DOF
    its a great rig - cant wait to see a video of it in action.
  4. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    Take a look at the first page in this thread, or last page for the last video.
  5. Flymen

    Flymen Flymen Gold Contributor

    Joined:
    May 19, 2018
    Messages:
    336
    Location:
    Montreal, Canada
    Balance:
    2,423Coins
    Ratings:
    +191 / 2 / -0
    My Motion Simulator:
    DC motor, 6DOF
    IMG_0823.JPG
    yes,I,M happy for you . with this drive , you can control your power with this Pot . like my mine I have 3 pot ajustement ! 1-current limit( current limit I need ) 2-ref gain( input power control : 15 v to 3 volt) 3-off set ( i can control each side with less or more force ) .
    • Like Like x 1
  6. Spit40

    Spit40 VR Flyer

    Joined:
    Nov 3, 2016
    Messages:
    341
    Location:
    United Kingdom
    Balance:
    2,883Coins
    Ratings:
    +198 / 3 / -0
    My Motion Simulator:
    3DOF
    Just looking at your SimTools mappings. They're all mapped to absolute angles, no Extra1,2,3.

    Do you derive the accelerations in your interface? If so I may have a problem with Aerofly FS2 as the plugin for that has a broken Roll DOF. I always use Extra2.
  7. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    In my interface, you see the pose of my rig.
    What I get from simtools are axis.
    In a pure conversion, I have only 1DOf per axis, so let's say I put in axis 1 100%sway, I will get only sway. My interface interprets axis 1 as sway. axis 2 as surge and so on...
    But I can put in axis1, for example 50%sway 10%Extra1 25%Surge for example. That mix is sent to my interface and she looks at it as just physical sway.
    If I want sway to be affected by Extra1, I just have to add it in simtools.
    I can limit the range of sway. Simtools sends values from 0 to 4095 and they are converted to the range I specified in the interface. For example -100mm to 100mm.
    It's more basic than it looks.
    I don't know if I have explained well...

    Maybe I will add some extra features to the interface, like:
    -Different centre of rotation for each of the 6DOF. For example traction loss rotating around a point in front and the other DOF rotating around another centre point.
    Or in a two seat car you are not at the centre of the car.
    -Since we receive all info from simtools, maybe make the mix in the interface and allow those centres to be in different places for each of the 9 values (6DOF plus the 3 extras)
  8. Spit40

    Spit40 VR Flyer

    Joined:
    Nov 3, 2016
    Messages:
    341
    Location:
    United Kingdom
    Balance:
    2,883Coins
    Ratings:
    +198 / 3 / -0
    My Motion Simulator:
    3DOF
    Thank you – yes I follow. Your diagram showed only the options of setting 100% absolute DOFs but i understand that any normal DOF supported by the plug-in is possible.
  9. xiatian

    xiatian Member

    Joined:
    Sep 5, 2017
    Messages:
    78
    Location:
    Xi'an, China
    Balance:
    262Coins
    Ratings:
    +28 / 0 / -0
    My Motion Simulator:
    2DOF
    Hello: pmvcda
    I plan to use your Arduino UNO code to control the actuator. Since the motor mounting hole is not reasonable, I want to install the motor in reverse. If so, the motor will rotate clockwise when searching for the minimum value. Can I change the direction? I need you to give me some help.
    This is the location I plan to install.

    Attached Files:

    • zxq.jpg
      zxq.jpg
      File size:
      76.7 KB
      Views:
      571
  10. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    That's been some time I made the code.
    There's some constants called UP and DOWN, I think you just need to reverse them to change rotation direction:
    Code:
    #define UP HIGH // Define to set up direction as HIGH
    #define DOWN LOW // Define to se down direction as LOW
  11. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    Well, I thought I could share the software I made to interface with the Hexapod.

    So here's my FlyPT Hexapod Interface (still some bugs and tests).
    FlyPT.jpg

    What is it?
    It's an interface between SimTools and the 6DOF rig.
    It allows the calculation of actuators lengths, to obtain a determined pose.
    It also calculates the speed of each actuator, so they all reach destination at the same time.
    You can apply filters in the pose components and in the actuators.
    You can change the ranges and invert the pose components.
    There's a 3D visualiser and a graphic visualiser for each actuator.
    All parameters can be changed in real time.
    It's made to work with linear actuators.

    How to setup?
    First of all, install the FlyPT_InterfacePlugin.dll plugin in SimTools.
    For that, just drop the dll in the SimTools Plugin Updater.
    This type of interface, creates a memory map wit 16bit values that are read and recognised by the FlyPT Hexapod Interface.
    interface.jpg
    Select that interface and press save.

    In the axis assignments put those values:
    axis.jpg
    The FlyPT Hexapod Interface, uses axis 1 to 6 as sway, surge, heave, Yaw, Roll and Pitch.
    You can for example, add in DOF2 Yaw for Axis4a with 20 value and make Extra1 with 80 to compose the resulting yaw.

    Open LFS for testing.

    Now run the FlyPT Hexapod Interface. (download bellow)
    Connect with SimTools to receive data and see the result.
    You can also play with the sliders.

    Serial is working, but for that you need specific code I will share for the boards.
    I made some recent updates to allow more or less boards and make it more universal.

    Known problems:
    I'm in doubt if heave should be vertical or perpendicular to the top plane (with rotations)....
    In this file, it's perpendicular.
    Some bugs...

    Attached Files:

    • Winner Winner x 3
    • Creative Creative x 1
  12. SilentChill

    SilentChill Problem Maker

    Joined:
    Jul 19, 2014
    Messages:
    2,643
    Occupation:
    Railway Maintenance
    Location:
    Morecambe, Lancashire, England
    Balance:
    20,560Coins
    Ratings:
    +3,488 / 34 / -0
    My Motion Simulator:
    DC motor, Arduino, Motion platform, 6DOF
    Wow that amazing !!! Been waiting years for someone to implement a proper 6DOF interface for us ardunio users.

    Thanks again for ya work Nd I will be testing it as soon as I get home, nice early Xmas prezzie :D
    • Like Like x 1
    • Winner Winner x 1
  13. SilentChill

    SilentChill Problem Maker

    Joined:
    Jul 19, 2014
    Messages:
    2,643
    Occupation:
    Railway Maintenance
    Location:
    Morecambe, Lancashire, England
    Balance:
    20,560Coins
    Ratings:
    +3,488 / 34 / -0
    My Motion Simulator:
    DC motor, Arduino, Motion platform, 6DOF
    Hi @pmvcda I have it all setup and installed hexapod utility is receiving all the data from simtools and everything is moving in the animation as it should however my actuators are not moving. I've set the com ports and set them to 500000 as they were when they were in the interface setup before I put your interface in there. Everything says its connected but no movement at all

    Is there something I'm missing ? I'm using SMC3 Sabertooth
  14. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    Hi,

    The current serial output is made for a specific ESP32 code that should be compatible with Arduino.
    But since your controllers are different from mine, part of the code will be different.
    If you can share the code on your Arduinos, I will try to make a compatible version.
    Here's what I'm using right now (but will not work for you):
    Code:
    // ============================================================================================================================
    // DIY 6DOF MOTION SIM BY THE FLYPT
    // ============================================================================================================================
    // SimTools2 ESP32 code to control actuators
    // Actuators use brushless motors controlled by BLDC8015A drivers
    // Position is obtained from internall hall sensors
    // This code is made to handle 3 actuators in one board
    // To use with the FlyPT interface you need two boards with the same code for 6 actuators
    // This code is made to receive position and speed from the FlyPT interface
    // And also send current position to the FlyPT interface
    
    
    
    
    // ============================================================================================================================
    // COMUNICATION ARCHITECTURE
    // ============================================================================================================================
    // Simtools2 --> FlyPT Interface <--> ESP32
    
    // Messages received from the FlyPT interface:
    //
    // 0 127 127 127 H L S H L S H L S --> Pretended position where H and L are high and low byte of the 16 bit value of position and S is the 8 bit value of speed
    // 0 127 127 125 --> Calibrate minimums / Go to minimums positions
    // 0 127 127 127 --> Calibrate maximums
    
    // Messages sent to the FlyPT interface:
    //
    // 0 127 127 127 H L H L H L --> Current position where H and L are high and low byte of the 16 bit value
    // 0 127 127 128 H L H L H L --> Range of the actuators, sent after calibration
    
    
    
    
    // ============================================================================================================================
    // DEFINES
    // ============================================================================================================================
    #define NUMBER_ACTUATORS 3      // Number of actuators (3 for each ESP32 DEVKIT board)
    #define SERIAL_SPEED 115200     // Define to set up the serial speed comunication
    #define CALIBRATION_SPEED 100   // Speed used to search for minimum and maximum values
    #define UP HIGH                 // Define to set up direction as HIGH
    #define DOWN LOW                // Define to set down direction as LOW
    #define PWM_RESOLUTION 8        // PWM for speed is a 8bit value 0 to 255
    #define PWM_FREQUENCY 1000      // PWM frequency
    #define CMD_NONE 0              // No command
    #define CMD_MINIMUM 8355709     // Command to move to minimum (value is a word with 4 bytes: 0 127 127 125 = 8355709
    #define CMD_POSITION 8355711    // Command to move to a pretended position (value is a word with 4 bytes: 0 127 127 127 = 8355711
    #define CMD_MAXIMUM 8355713     // Command to move to maximum (value is a word with 4 bytes: 0 127 127 129 = 8355713
    
    #define LIMITS_PIN 0            // Pin to capture position from pot wich defines the limits
    #define HALL_1_PIN 1            // Pin used for hall 1 interrupt
    #define HALL_2_PIN 2            // Pin used for hall 2 interrupt
    #define HALL_3_PIN 3            // Pin used for hall 3 interrupt
    #define LAST_ANGLE 4            // Last angle that was detected
    #define LAST_SUM 5              // Last sum to know last direction it took
    #define DIRECTION_PIN 6         // Pin to se direction
    #define SPEED_PIN 7             // Pin to set speed with PWM
    #define PWM_CHANNEL 8           // Channel used to generate PWM
    #define RANGE 9                 // Maximum position
    #define CURRENT_POSITION 10     // Current position
    #define PRETENDED_POSITION 11   // Pretended position
    #define SPEED 12                // Speed of motor rotation
    #define FOUND 13                // For help. Used for example in actuator calibration
    
                                    // ======================
                                    // Actuators information:
                                    // ======================
                                    // 0  - LIMITS_PIN          - Pin to capture position from pot
                                    // 1  - HALL_1_PIN          - Pin used for hall 1 interrupt
                                    // 2  - HALL_2_PIN          - Pin used for hall 2 interrupt
                                    // 3  - HALL_3_PIN          - Pin used for hall 3 interrupt
                                    // 4  - LAST_ANGLE          - Last angle that was detected
                                    // 5  - LAST_SUM            - Last sum to know last direction it took
                                    // 6  - DIRECTION_PIN       - Pin to set direction
                                    // 7  - SPEED_PIN           - Pin to set speed with PWM
                                    // 8  - PWM_CHANNEL         - Channel used to generate PWM
                                    // 9  - RANGE               - -RANGE = Minimum position +RANGE = Maximum position
                                    // 10 - CURRENT_POSITION    - Current position
                                    // 11 - PRETENDED_POSITION  - Pretended position
                                    // 12 - SPEED               - Speed of motor
                                    // 13 - FOUND               - Used as help for calibraion
                                    //
                                    //----00--01--02--03--04--05--06--07--08--09--10--11--12--13----//
    static int actuator[3][20] = {  {      4, 27, 26, 25,  5,  0, 32, 33,  0,  0,  0,  0,  0,  0     },   // Actuator 0
                                    {     36, 35, 34, 39,  5,  0, 18,  5,  1,  0,  0,  0,  0,  0     },   // Actuator 1
                                    {     15, 23, 22, 21,  5,  0, 19, 17,  2,  0,  0,  0,  0,  0     } }; // Actuator 2
    
    static long command=0;  // Current command received from serial
    
    // Maps to get increment off position from comparing previous hall sensor state with current state
    // Vertical, the new value, horizontal, the old one
    // Stores for 0 and 7, althought they should not ocurr, digital read might get them. They are ignored with zero change.
    // State sequence going up
    // 5=101
    // 1=001
    // 3=011
    // 2=010
    // 6=110
    // 4=100
    // First index of array for new state, second for old state ([new][old])
    static int incrementUp[8][8] =      { { 0,  0,  0,  0,  0,  0,  0, 0},
                                          { 0,  0, -2, -1,  2,  1,  3, 0},
                                          { 0,  2,  0,  1, -2,  3, -1, 0},
                                          { 0,  1, -1,  0,  3,  2, -2, 0},
                                          { 0, -2,  2,  3,  0, -1,  1, 0},
                                          { 0, -1,  3, -2,  1,  0,  2, 0},
                                          { 0,  3,  1,  2, -1, -2,  0, 0},
                                          { 0,  0,  0,  0,  0,  0,  0, 0} };
                              
    static int incrementDown[8][8] =    { { 0,  0,  0,  0,  0,  0,  0, 0},
                                          { 0,  0, -2, -1,  2,  1, -3, 0},
                                          { 0,  2,  0,  1, -2, -3, -1, 0},
                                          { 0,  1, -1,  0, -3,  2, -2, 0},
                                          { 0, -2,  2, -3,  0, -1,  1, 0},
                                          { 0, -1, -3, -2,  1,  0,  2, 0},
                                          { 0, -3,  1,  2, -1, -2,  0, 0},
                                          { 0,  0,  0,  0,  0,  0,  0, 0} };
    
    // Handle for the thread that updates the actuators positions
    TaskHandle_t taskUpdatePositionsHandle;
    
    // Semaphore for data handling between threads
    SemaphoreHandle_t semaphore = xSemaphoreCreateMutex();
    
    
    
                                                            
    // ============================================================================================================================
    // INITIALIZATION
    // ============================================================================================================================
    void setup()
    {
      // Initialize pins
      for(int n=0;n<NUMBER_ACTUATORS;n++)
      {
        // Initialize pins
        pinMode(actuator[n][LIMITS_PIN], INPUT_PULLDOWN);
        pinMode(actuator[n][HALL_1_PIN], INPUT_PULLDOWN);
        pinMode(actuator[n][HALL_2_PIN], INPUT_PULLDOWN);
        pinMode(actuator[n][HALL_3_PIN], INPUT_PULLDOWN);
        pinMode(actuator[n][DIRECTION_PIN], OUTPUT);
        pinMode(actuator[n][SPEED_PIN], OUTPUT);
        digitalWrite(actuator[n][SPEED_PIN], LOW); // At reset pins are with HIGH, make them LOW as soon as we can
     
        // Setup PWM
        ledcSetup(actuator[n][PWM_CHANNEL], PWM_FREQUENCY, PWM_RESOLUTION);
        ledcAttachPin(actuator[n][SPEED_PIN], actuator[n][PWM_CHANNEL]);
        ledcWrite(actuator[n][PWM_CHANNEL], 0);
      }
    
      // Create thread that gets position from hall sensors to run in the core 0
      // It will run in paralell with the main loop that uses core 1 by default 
      xTaskCreatePinnedToCore(
        TaskUpdatePositions,          // Task function
        "UpdatePositions",            // Name           
        10000,                        // Stack size
        NULL,                         // Task input parameter
        1,                            // Priority of the task
        &taskUpdatePositionsHandle,   // Task handle
        0);                           // Core
    
      // Setup communication
      Serial.begin(SERIAL_SPEED, SERIAL_8N1);
    
      // Initialize pin to light up onboard led
      pinMode(2, OUTPUT);
    
      // Countdown of 5 seconds before calibration
      // Internall led is light up while waiting
      digitalWrite(2, HIGH);   
      delay(5000);
      digitalWrite(2, LOW);
    
      // Calibrate actuators (get ranges)
      calibrateMinimums();
      calibrateMaximums();
    }
    
    
    
    
    // ============================================================================================================================
    // SERIAL COMUNICATION SEND/RECEIVE
    // ============================================================================================================================
    void sendReceiveSerial()
    {
      // Receive pretended positions from the FlyPT Interface through serial
      // Value received is in number of steps
      // Received in the format: 0 x x x H L S H L S H L S where:
      // 0 127 127 128 = Start of info for pretended position
      // 0 127 127 126 = Command to look for minimums or go to minimum
      // 0 127 127 130 = Command to look for maximums (should be run after minimum for calibration)
      // 0 127 127 129 = Command to calibrate
      // H = signed byte, the high signed byte of the pretended position
      // L = unsigned byte, the low byte of the pretended position
      // S = byte for speed
      // H L S is received 3 times, one for each actuator in sequence
      while (Serial.available()>0)
       {
        if (command<CMD_MINIMUM && command>CMD_MAXIMUM)
        {
          command = ((command << 8) | Serial.read()); // Move left 8 bits and add at the end the new 8 bits
        }
        else if (Serial.available()>=6)
        {
          // Get pretended position and send the current one
          if (command == CMD_POSITION)
          {
            // Send command of current position
            Serial.write(0);
            Serial.write(127);
            Serial.write(127);
            Serial.write(127);
            // For each actuator...
            for(int n=0; n<NUMBER_ACTUATORS; n++)
            {
              // Get pretended position
              actuator[n][PRETENDED_POSITION] = constrain(((int8_t)Serial.read() << 8) | Serial.read(), -actuator[n][RANGE], actuator[n][RANGE]);
              // Get pretended speed
              actuator[n][SPEED] = Serial.read();
              // Send current position
              Serial.write(highByte(actuator[n][CURRENT_POSITION]));
              Serial.write(lowByte(actuator[n][CURRENT_POSITION]));
            }
            Serial.flush();
          }
          else if (command == CMD_MINIMUM)
          {
            calibrateMinimums();
          }
          else if (command == CMD_MAXIMUM)
          {
            calibrateMaximums();
          }
          // Reset command
          command=CMD_NONE;
          // Return from function to execute something else.... We don't want to stay here to much time in the while, just what is needed.
          return;
        }
      }
    }
    
    
    
    
    // ============================================================================================================================
    // CALIBRATE MINIMUMS
    // ============================================================================================================================
    void calibrateMinimums()
    {
      // Move all actuators up, untill minimum switches are deactivated
      int found=0;
      for(int n=0;n<NUMBER_ACTUATORS;n++)
      {
        digitalWrite (actuator[n][DIRECTION_PIN],UP);
        ledcWrite(actuator[n][PWM_CHANNEL], CALIBRATION_SPEED);
        actuator[n][FOUND]=false;
      }
      while (found<NUMBER_ACTUATORS)
      {
        for(int n=0;n<NUMBER_ACTUATORS;n++)
        {
          // Read limit switch position (we are looking for more than zero)
          // We read more than one time to be sure (4 times in this case)
          if(!actuator[n][FOUND] && analogRead(actuator[n][LIMITS_PIN])>0 && analogRead(actuator[n][LIMITS_PIN])>0 && analogRead(actuator[n][LIMITS_PIN])>0 && analogRead(actuator[n][LIMITS_PIN])>0)
          {
            ledcWrite(actuator[n][PWM_CHANNEL], 0);
            actuator[n][FOUND]=true;
            found++;
          }
        }
      }
     
      // Move all actuators down untill all minimum switches are activated and make it current position -range
      for(int n=0;n<NUMBER_ACTUATORS;n++)
      {
        digitalWrite (actuator[n][DIRECTION_PIN],DOWN);
        ledcWrite(actuator[n][PWM_CHANNEL], CALIBRATION_SPEED);
        actuator[n][FOUND]=false;
      }
      while (found<NUMBER_ACTUATORS)
      {
        for(int n=0;n<NUMBER_ACTUATORS;n++)
        {
          // Read limit switch position (we are looking for zero)
          // We read more than one time to be sure (4 times in this case)
          if(!actuator[n][FOUND] && analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])<=0)
          {
            ledcWrite(actuator[n][PWM_CHANNEL], 0);
            actuator[n][CURRENT_POSITION]=0;
            actuator[n][FOUND]=true;
            found++;
          }
        }
      }
    }
    
    
    
    
    // ============================================================================================================================
    // CALIBRATE MAXIMUMS
    // ============================================================================================================================
    void calibrateMaximums()
    {
      // Go up untill maximum switches are activated and make that position the maximum
      // Split maximum in half to calculate range and make minimum=-range and maximum=+range
      int found=0;
      for(int n=0;n<NUMBER_ACTUATORS;n++)
      {
        digitalWrite (actuator[n][DIRECTION_PIN],UP);
        ledcWrite(actuator[n][PWM_CHANNEL], CALIBRATION_SPEED);
        actuator[n][FOUND]=false;
      }
      while (found<NUMBER_ACTUATORS)
      {
        for(int n=0;n<NUMBER_ACTUATORS;n++)
        {
          // Read limit switch position (we are looking for big value 4095)
          if(!actuator[n][FOUND] && (analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN]))/4 >= 4095)
          {
            ledcWrite(actuator[n][PWM_CHANNEL], 0);
            actuator[n][CURRENT_POSITION]=actuator[n][CURRENT_POSITION]/2;
            actuator[n][RANGE]=actuator[n][CURRENT_POSITION];
            actuator[n][FOUND]=true;
            found++;
          }
        }
      }
     
      // Send maximums to interface through serial
      // Value sent is in number of counts
      // Sends in format: 0 127 127 129 H L H L H L where:
      // 0 127 127 129 = Start of info
      // H = high byte of value
      // L = low byte of value
      // HL 3 times for each actuator in sequence
      Serial.write(0);
      Serial.write(127);
      Serial.write(127);
      Serial.write(129);
      Serial.write(highByte(actuator[0][RANGE]));
      Serial.write(lowByte(actuator[0][RANGE]));
      Serial.write(highByte(actuator[1][RANGE]));
      Serial.write(lowByte(actuator[1][RANGE]));
      Serial.write(highByte(actuator[2][RANGE]));
      Serial.write(lowByte(actuator[2][RANGE]));
      Serial.flush();
    }
    
    
    
    
    // ============================================================================================================================
    // MAIN LOOP TO RUN IN CORE 1
    // ============================================================================================================================
    // Here we get and send the serial commands and make the actuator move
    // This is runing in core 1
    void loop()
    {
      int limitValue=2047; // Define only once, outside of the loop
      while(true)  // While we are here, nothing else runs on the background...
      {
        // Send and receive controls
        sendReceiveSerial();
        
        // Update actuators behaviour
        for(int n=0;n<NUMBER_ACTUATORS;n++)
        {
          // Set direction
          // Get current position with semaphore because of the other core/thread
          // that can be updating it's value
          // ====================================================================
          xSemaphoreTake( semaphore, portMAX_DELAY );
          if(actuator[n][CURRENT_POSITION] < actuator[n][PRETENDED_POSITION]) digitalWrite (actuator[n][DIRECTION_PIN], UP);
          else digitalWrite (actuator[n][DIRECTION_PIN], DOWN);
          xSemaphoreGive( semaphore );
          
          // Set speed
          // =========
          ledcWrite(actuator[n][PWM_CHANNEL], actuator[n][SPEED]);
          
          // Check limits
          // ============
          // Adjust position if minimum or maximum switch is activated
          // This avoids any drift in positioning,recalibrating the actuator
          limitValue=(analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN])+analogRead(actuator[n][LIMITS_PIN]))>>2;
          // If at maximum, recalibrate maximum and invert direction of travel for safety
          if(limitValue>=4095)
          {
            digitalWrite (actuator[n][DIRECTION_PIN], DOWN);
            xSemaphoreTake( semaphore, portMAX_DELAY );
            actuator[n][CURRENT_POSITION]=actuator[n][RANGE];
            xSemaphoreGive( semaphore );
          }
          // If at minimum, recalibrate minimum and invert direction of travel for safety
          else if (limitValue<=0)
          {
            digitalWrite (actuator[n][DIRECTION_PIN], UP);
            xSemaphoreTake( semaphore, portMAX_DELAY );
            actuator[n][CURRENT_POSITION]=-actuator[n][RANGE];
            xSemaphoreGive( semaphore );
          }
        }
      }
    }
    
    
    
    
    // ============================================================================================================================
    // UPDATE CURRENT POSITIONS LOOP TO RUN IN CORE 0
    // ============================================================================================================================
    // This thread updates the actuators current positions reading the hall sensors
    // This is runing in core 0
    void TaskUpdatePositions(void * parameter)
    {
      int angle=0; // Define only once, outside of the loop
      while (true) // While we are here, nothing else runs on the background...
      {
        for(int n=0;n<NUMBER_ACTUATORS;n++)
        {
          angle=digitalRead(actuator[n][HALL_1_PIN])*4+digitalRead(actuator[n][HALL_2_PIN])*2+digitalRead(actuator[n][HALL_3_PIN]);
          if (actuator[n][LAST_SUM]>0) actuator[n][LAST_SUM]=incrementUp[angle][actuator[n][LAST_ANGLE]];
          else actuator[n][LAST_SUM]=incrementDown[angle][actuator[n][LAST_ANGLE]]; 
          actuator[n][LAST_ANGLE]=angle;
          // Use semaphore because of data sharing between cores/threads
          xSemaphoreTake( semaphore, portMAX_DELAY );
          actuator[n][CURRENT_POSITION]+=actuator[n][LAST_SUM];
          xSemaphoreGive( semaphore );
        }
      }
    }
    This is not the final version.

    So, if you want, I can try to adapt your Arduino code.
    I would love to do so and see this working in another motion rig.
    • Like Like x 2
    • Informative Informative x 1
  15. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    OK, I'm making some changes for a serial output without feedback on position and using a user defined string.
    That way, you just have to put your current serial string format in the interface.
    Give me some time...
    • Like Like x 1
  16. SilentChill

    SilentChill Problem Maker

    Joined:
    Jul 19, 2014
    Messages:
    2,643
    Occupation:
    Railway Maintenance
    Location:
    Morecambe, Lancashire, England
    Balance:
    20,560Coins
    Ratings:
    +3,488 / 34 / -0
    My Motion Simulator:
    DC motor, Arduino, Motion platform, 6DOF
  17. DOFreality

    DOFreality Member

    Joined:
    Oct 30, 2016
    Messages:
    84
    Location:
    Montreal
    Balance:
    343Coins
    Ratings:
    +45 / 5 / -0
    My Motion Simulator:
    2DOF, 3DOF, DC motor, Arduino, Motion platform, 6DOF
    Why not STM32?
    ESP is bad in real time staff and interruptions to Chinese WiFi communication code
  18. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    From what I read, the ESP32 is way faster in a single core. Even more using two cores.
    And it's in the same price range. Less than 5€.
    I'm not using Bluetooth or WifFi.

    The main reason was speed and price. Because I count the steps of the hall sensors inside the BLDC motors.
    I can count on 3 motors in real time without problems since I moved this task to another core.
  19. DOFreality

    DOFreality Member

    Joined:
    Oct 30, 2016
    Messages:
    84
    Location:
    Montreal
    Balance:
    343Coins
    Ratings:
    +45 / 5 / -0
    My Motion Simulator:
    2DOF, 3DOF, DC motor, Arduino, Motion platform, 6DOF
    ESP is more powerful, but there few issues in using it in this application like ours. It is aimed for IOT.
    It has bad architecture . Basically it is split in to two parts. One primary - Chinese programmed (with many reported bugs) to drive wireless communication and occasionally give control to the second part that you can program with buggy SDK, Interruptions are not implemented properly. So you can;t rely on it as it can freeze for some critical time.
    1.6 $ STM 32 well time proven "blue pill" can drive 6 and more BLDC motors with 3 halls each as a feedback loop and do many more needed math calculations in reliable fashion. There are also of knowledge base and libraries as well as community for the STM32

    BTW can you share 6 DOF games profiles that you have done already for Steward ?
    here are LFS and Dirt3 that I have

    Attached Files:

  20. pmvcda

    pmvcda aka FlyPT

    Joined:
    Nov 3, 2010
    Messages:
    2,158
    Location:
    Portugal
    Balance:
    15,264Coins
    Ratings:
    +2,532 / 17 / -0
    My Motion Simulator:
    6DOF
    Well, now it's done and working...
    But I might use the STM32 for my future semi DD wheel and pedals. Have some ideas... some different than the usual ones.

    I'm using my own program to control the hexapod.
    I calculate the extension of the actuators to get the pretended pose. So it's a mix of settings between simtools and my program.
    I use my program to handle limits, ranges and filters(I can make it real time with my program).
    And simtools to mix values and washout.
    But I have not finished the rig, I need to mount the wheel and pedals to make the tests and create profiles.
    Hope it's soon.
    • Like Like x 1