4 joystick (6-axis 6-dof) game controller

a 4 joystick game controller for 6axis+ games (inertial thrust space games)

Similar projects worth following
(demo video in logs)
4 joystick game controller made with arduino, programmed with code and driver taken from Cleric-K's github page. The controller is designed to be used for space games, particularly space games that are simple enough that they could be enjoyed from a casual posture (simple navigation and shooting). The game controller allows for all 6 axis of control to be on joysticks. To make the coordination of your pointer fingers easier to learn, simply use each front stick to control one axis. My configuration is:
- left thumb: strafe updownleftright
- left pointer: pull trigger for throttle, push trigger for reverse thrust
- right thumb: pitch/yaw
- right pointer: roll
some logic: I chose yaw and pitch on the thumb, and only play games that allow for rapid yaw (Orbital Racer, simulation mode, float on). Although many players will prefer to roll and pitch for control, and a lot of games optimize this motion,,, it is still extra moves when only one is required.

to program the controller, just go to cleric-k's vjoyserialfeeder page. 

everything is there. I will add my specific code and vjoyserialfeeder json in a while. 

Then you will be able to build an identical copy and just download all the codes and configs. They are on a different computer. 


my specific vjoyserialfeeder configuration.

JavaScript Object Notation (JSON) - 4.23 kB - 07/21/2021 at 18:37



here is my specific arduino sketch. YOu will also need the ibus.h and ibus.cpp files from the cleric-k repository

ino - 3.05 kB - 07/21/2021 at 18:20


  • Some demonstration videos

    tsmspace07/21/2021 at 18:39 0 comments

  • arduino sketch paste

    tsmspace07/21/2021 at 18:25 0 comments

    #include "ibus.h"

    // //////////////////
    // Edit here to customize

    // How often to send data?
    #define UPDATE_INTERVAL 10 // milliseconds

    // 1. Analog channels. Data can be read with the Arduino's 10-bit ADC.
    // This gives values from 0 to 1023.
    // Specify below the analog pin numbers (as for analogRead) you would like to use.
    // Every analog input is sent as a single channel.
    #define NUM_ANALOG_INPUTS 8
    byte analogPins[] = {A0, A1, A2, A3, A4, A5, A6, A7}; // element count MUST be == NUM_ANALOG_INPUTS

    // 2. Digital channels. Data can be read from Arduino's digital pins.
    // They could be either LOW or HIGH.
    // Specify below the digital pin numbers (as for digitalRead) you would like to use.
    // Every pin is sent as a single channel. LOW is encoded as 0, HIGH - as 1023
    #define NUM_DIGITAL_INPUTS 12
    byte digitalPins[] = {2,3,4,5,6, 7,8,9,10,11,12,13}; // element count MUST be == NUM_DIGITAL_INPUTS

    // 3. Digital bit-mapped channels. Sending a single binary state as a 16-bit
    // channel is pretty wasteful. Instead, we can encode one digital input
    // in each of the 16 channel bits.
    // Specify below the digital pins (as for digitalRead) you would like to send as
    // bitmapped channel data. Data will be automatically organized in channels.
    // The first 16 pins will go in one channel (the first pin goes into the LSB of the channel).
    // The next 16 pins go in another channel and so on
    // LOW pins are encoded as 0 bit, HIGH - as 1.
    byte digitalBitmappedPins[] = {}; // element count MUST be == NUM_DIGITAL_BITMAPPED_INPUTS

    // Define the appropriate analog reference source. See

    // Define the baud rate
    #define BAUD_RATE 115200

    // /////////////////


    IBus ibus(NUM_CHANNELS);

    void setup()
      analogReference(ANALOG_REFERENCE); // use the defined ADC reference voltage source
      Serial.begin(BAUD_RATE);           // setup serial

    void loop()
      int i, bm_ch = 0;
      unsigned long time = millis();


      // read analog pins - one per channel
      for(i=0; i < NUM_ANALOG_INPUTS; i++)

      // read digital pins - one per channel
      for(i=0; i < NUM_DIGITAL_INPUTS; i++)
        ibus.write(digitalRead(digitalPins[i]) == HIGH ? 1023 : 0);

      // read digital bit-mapped pins - 16 pins go in one channel
      for(i=0; i < NUM_DIGITAL_BITMAPPED_INPUTS; i++) {
      int bit = i%16;
      if(digitalRead(digitalBitmappedPins[i]) == HIGH)
      bm_ch |= 1 << bit;

      if(bit == 15 || i == NUM_DIGITAL_BITMAPPED_INPUTS-1) {
      // data for one channel ready
      bm_ch = 0;


      time = millis() - time; // time elapsed in reading the inputs
      if(time < UPDATE_INTERVAL)
        // sleep till it is time for the next update
        delay(UPDATE_INTERVAL  - time);

View all 2 project logs

  • 1
    specific build decisions

    I won't provide a schematic yet, you will just need to look at the picture. I used an arduino nano v3. The design will change, but you can see where the wires go in the pictures.

    The pulldown resistors are 10k, the joysticks are 10k. The joystick tactile buttons are not included in the build yet, but I ordered one of those arduino multiplexers so that I can include them soon. 5v runs from the arduino to the rails on the breadboard, so does ground. The joysticks just plug directly to the analog pins. The power runs from the rails to the tactile buttons on the breadboards, and from the buttons the wire runs to the pins on the arduino. A pulldown resistor is placed between the arduino pins and ground. This means that the sketch will read high as press. 

    the joysticks use up all of the analog pins, my stick order is thumb left, thumb right, finger left, finger right on the analog pins (a0-a8), you will calibrate which axis goes to which axis in vjoyserialfeeder, so it doesn't actually matter, you can just map them in the driver. The buttons go to d2-d13 . tx and rs are used by usb. 

  • 2
    vjoyserialfeeder setup

    The setup for vjoyserialfeeder is pretty easy. I have also uploaded my configuration json, but if your pins are not in the same order as mine, then your axis and buttons will not have the same number order. This doesn't matter though, because you will need to map all of the controls in each game anyway, and mostly you just select the control and press the button or deflect the stick you want, so it's really fine. You will need to calibrate each of your axis, and while using a breadboard you may need to calibrate frequently. I believe that if you have a very stable build without any loose parts, or if it is well soldered together, calibration should be very stable. 

View all instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates