PDA

View Full Version : Arduino as 128 inputs DirectX interface



sandb0x
09-24-2016, 03:27 AM
Hi folks!
This is a recipe how to make a 128 input DirectX interface using only two wires on Arduino Leonardo for around £15 (Board + I/O expanders).

Parts:
1. Arduino Leonardo or Micro (Mega and Uno may work with https://github.com/NicoHood/HoodLoader2) not tested by me.
2. 8 x MCP23017 http://uk.farnell.com/microchip/mcp23017-e-sp/ic-io-expander-16bit-i2c-28dip/dp/1332088
3. 2 x Breadboards or make your own PCB.
4. 8 x 10K resistors
5. Switches and Buttons
6. Arduino Libraries
a. https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library
b. https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-2.0
7. 128 buttons joystick tester: http://www.planetpointy.co.uk/joystick-test-application/

Notes:
To connect a button or a switch: one wire to ground, second to first MCP pin 21 (GPA0) - result DX button 1. No need for a resistor as it uses an internal pullout.

For a DX button 16 connect to first MCP pin 8 (GPB7)
For a DX button 17 connect to second MCP pin 21 (GPA0) and so on.


The interface is recognised by P3D and LINDA.
FSUIPC uses windows interface so it only recognises up to 32 buttons.

The joystick axes, hat switches can also be activated. Refer to joystick library documentation.

The interface can be father expanded by using shift registers but it simpler to make another one using different joystick address.



The Arduino code:

#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Joystick.h>


Adafruit_MCP23017 mcp0;
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
Adafruit_MCP23017 mcp3;
Adafruit_MCP23017 mcp4;
Adafruit_MCP23017 mcp5;
Adafruit_MCP23017 mcp6;
Adafruit_MCP23017 mcp7;


Joystick_ Joystick = {
Joystick_(0x03, 128, 0, false, false, false, false, false, false, false, false, false, false, false)
};


void setup() {
mcp0.begin(0); // use address 0X20
for (int index = 0; index < 16; index++)
{
mcp0.pinMode(index, INPUT);
mcp0.pullUp(index, HIGH);
}

mcp1.begin(1); // use address 0X21
for (int index = 0; index < 16; index++)
{
mcp1.pinMode(index, INPUT);
mcp1.pullUp(index, HIGH);
}


mcp2.begin(2); // use address 0X22
for (int index = 0; index < 16; index++)
{
mcp2.pinMode(index, INPUT);
mcp2.pullUp(index, HIGH);
}

mcp3.begin(3); // use address 0X23
for (int index = 0; index < 16; index++)
{
mcp3.pinMode(index, INPUT);
mcp3.pullUp(index, HIGH);
}

mcp4.begin(4); // use address 0X24
for (int index = 0; index < 16; index++)
{
mcp4.pinMode(index, INPUT);
mcp4.pullUp(index, HIGH);
}

mcp5.begin(5); // use address 0X25
for (int index = 0; index < 16; index++)
{
mcp5.pinMode(index, INPUT);
mcp5.pullUp(index, HIGH);
}

mcp6.begin(6); // use address 0X26
for (int index = 0; index < 16; index++)
{
mcp6.pinMode(index, INPUT);
mcp6.pullUp(index, HIGH);
}

mcp7.begin(7); // use address 0X27
for (int index = 0; index < 16; index++)
{
mcp7.pinMode(index, INPUT);
mcp7.pullUp(index, HIGH);
}


// Initialize Joystick Library
Joystick.begin();
}


// Last state of the buttons
int lastButtonState0[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState2[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState3[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState4[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState5[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState6[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int lastButtonState7[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};


void loop() {


// Read pin values mcp0
for (int index = 0; index < 16; index++)
{
int currentButtonState0 = !mcp0.digitalRead(index);
if (currentButtonState0 != lastButtonState0[index])
{
Joystick.setButton(index, currentButtonState0);
lastButtonState0[index] = currentButtonState0;
}
}

// Read pin values mcp1
for (int index = 0; index < 16; index++)
{
int currentButtonState1 = !mcp1.digitalRead(index);
if (currentButtonState1 != lastButtonState1[index])
{
Joystick.setButton(index+16, currentButtonState1);
lastButtonState1[index] = currentButtonState1;
}
}


// Read pin values mcp2
for (int index = 0; index < 16; index++)
{
int currentButtonState2 = !mcp2.digitalRead(index);
if (currentButtonState2 != lastButtonState2[index])
{
Joystick.setButton(index+32, currentButtonState2);
lastButtonState2[index] = currentButtonState2;
}
}

// Read pin values mcp3
for (int index = 0; index < 16; index++)
{
int currentButtonState3 = !mcp3.digitalRead(index);
if (currentButtonState3 != lastButtonState3[index])
{
Joystick.setButton(index+48, currentButtonState3);
lastButtonState3[index] = currentButtonState3;
}
}

// Read pin values mcp4
for (int index = 0; index < 16; index++)
{
int currentButtonState4 = !mcp4.digitalRead(index);
if (currentButtonState4 != lastButtonState4[index])
{
Joystick.setButton(index+64, currentButtonState4);
lastButtonState4[index] = currentButtonState4;
}
}

// Read pin values mcp5
for (int index = 0; index < 16; index++)
{
int currentButtonState5 = !mcp5.digitalRead(index);
if (currentButtonState5 != lastButtonState5[index])
{
Joystick.setButton(index+80, currentButtonState5);
lastButtonState5[index] = currentButtonState5;
}
}

// Read pin values mcp6
for (int index = 0; index < 16; index++)
{
int currentButtonState6 = !mcp6.digitalRead(index);
if (currentButtonState6 != lastButtonState6[index])
{
Joystick.setButton(index+96, currentButtonState6);
lastButtonState6[index] = currentButtonState6;
}
}

// Read pin values mcp7
for (int index = 0; index < 16; index++)
{
int currentButtonState7 = !mcp7.digitalRead(index);
if (currentButtonState7 != lastButtonState7[index])
{
Joystick.setButton(index+112, currentButtonState7);
lastButtonState7[index] = currentButtonState7;
}
}


delay(50);
Joystick.sendState();
}



Connection diagram:

http://i.imgur.com/R9qKBPw.jpg


http://www.mycockpit.org/forums/attachment.php?attachmentid=11748&stc=1



MCP23017 pins layout:
http://www.mycockpit.org/forums/attachment.php?attachmentid=11743&stc=1

MCP23017 Addresses:

http://www.mycockpit.org/forums/attachment.php?attachmentid=11744&stc=1


Results in joystick tester:

http://www.mycockpit.org/forums/attachment.php?attachmentid=11745&stc=1



Result in P3D:

http://www.mycockpit.org/forums/attachment.php?attachmentid=11746&stc=1




Results in LINDA:

http://www.mycockpit.org/forums/attachment.php?attachmentid=11747&stc=1


Example of 64 buttons DX device on stripboard:
http://www.mycockpit.org/forums/attachment.php?attachmentid=12510&stc=1

http://www.mycockpit.org/forums/attachment.php?attachmentid=12511&stc=1

wody
04-07-2017, 09:20 AM
Hello Sandb0x,

thanks for this Arduino interface. I need 2 of them for my Mustang cockpit with LINDA.

I saw you have used fritzing. Did you evermake a PCB with pins for the buttons? I have no idea how to design a board usable in the cockpit. So it would be nice to get some help.

Can I connect also an encoder? If yes, any specialities to them?

Thanks a lot for this inspiration!
Peter

tiburon
04-08-2017, 01:26 AM
Thanks ! I'm going to try this. Have to think of some sort of break-out solution because connecting 128 wires to a breadboard is not my idea of happiness.

ranpetel
05-27-2017, 08:49 AM
Hi, I have few questions please:

1) How can I build it with the Arduino Micro?
2) Where do I plug the SDA and SCL in the Micro?
3) Arduino Micro don't have an on board pull-ups in it's SDA and SCL as far as I know. What should I do then?

Thanks ahead.
Ran

ranpetel
05-31-2017, 08:03 AM
OK, Problems fixed.
1) Same as Leonardo
2) Digital pins 2 and 3
3) It does has on board pull-ups

I also notice that the code here showed me only X, Y AXIS ISO 128 buttons. That fixed by replacing bellow code:
Joystick_ Joystick = {Joystick_(0x03, 128, 0, false, false, false, false, false, false, false, false, false, false, false)
};

With this code:
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD, 128, 0, false, false, false, false, false, false, false, false, false, false, false);

That do the trick!

Now for a new question, windows does not recognize more than 32 buttons, in this case, how do I make this code to activate as 4 Joysticks of 32 buttons?

wody
05-31-2017, 09:07 AM
download the 128 button joystick tester (http://www.planetpointy.co.uk/joystick-test-application/) as mentioned in part 7 in first post. The buttons are here, just Win does not show more than 32 buttons...

Peter

ranpetel
06-08-2017, 04:53 AM
download the 128 button joystick tester (http://www.planetpointy.co.uk/joystick-test-application/) as mentioned in part 7 in first post. The buttons are here, just Win does not show more than 32 buttons...

Peter

Hi Peter,
Thank for your answer. I know and use "128 button joystick tester (http://www.planetpointy.co.uk/joystick-test-application/)" and it is a great tool but, this was not what I meant. My question is, whether someone know how to modify the code to show 4 different 32 buttons joysticks ISO 1 128 buttons as not all simulators/programs, especially old ones know how to deal with more than 32 buttons since they relay on Windows capabilities.

There are other 3rd party programs like Linda for FSX that do the job or, as I use X-PLANE 11, it handle 128 buttons with no problems at all but I'm still looking for something more basic for older programs which don't have 3rd party programs nor the capabilities to understand or deal with 128 buttons and divide it to 4 basic 32 buttons.

Hope I clarify myself better now ;)

ranpetel
07-18-2017, 06:22 AM
Is it possible to turn one MCP to potentiometers ISO buttons?
If yes, what would be the code change for that please?
Thanks.

wody
08-17-2017, 04:28 PM
Hi,
has somebody made a PCB? Would be nice, I do not know ho to make such a PCB

Thanks,
Peter