The NEW Build Your Own Arcade Controls

Software Support => Automated Projects => Topic started by: Ginsonic on February 07, 2017, 05:22:32 am

Title: Yet another Rotary Joystick project
Post by: Ginsonic on February 07, 2017, 05:22:32 am
I just finished the first (mechanical) part of my brand new Rotary Joystick project. I decided to construct all pieces by myself in 3D and print them out using my Witbox 2 3D printer (PLA).
Attached you see the pictures of the assembled stick and handle and the construction desktop of  the single parts. I used a standard SANWA shaft and spring, the rest is printed stuff (even the tiny E-ring  ;) )
In theory (mechanically) it works great, let's see, what the controller part will bring...

The electrical part is a Lorlin CK1028 12pos rotary switch, later on I will connect both joysticks to an arduino micro to handle the rotary keyboard presses for MAME.

Title: Re: Yet another Rotary Joystick project
Post by: DaOld Man on February 07, 2017, 10:12:42 am
Looks good!
Title: Re: Yet another Rotary Joystick project
Post by: BadMouth on February 07, 2017, 12:19:08 pm
I love the LS-30 style top!

Please share your arduino sketch once it's done.  :angel:

What do the detents on that rotary switch feel like?
I'm using an ALPs switch that I bought off ebay and the detents feel perfect, but the switch costs $5-6 on ebay and doesn't appear to be commonly available elsewhere.

Years ago I built a rotary setup using a 16 postion optical rotary encoder from sparkfun, but you could barely feel the detents.  The ALPs gives a satisfying snap to position.  (but not too strong)
Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on February 08, 2017, 05:07:57 am
I love the LS-30 style top!
Me too, especially the haptics is great.

Please share your arduino sketch once it's done.  :angel:
Sure, I just finished both rotaries and I will start the electrical/programming part soon.

What do the detents on that rotary switch feel like?
I'm using an ALPs switch that I bought off ebay and the detents feel perfect, but the switch costs $5-6 on ebay and doesn't appear to be commonly available elsewhere.
Years ago I built a rotary setup using a 16 postion optical rotary encoder from sparkfun, but you could barely feel the detents.  The ALPs gives a satisfying snap to position.  (but not too strong)
Same here, the detents feel just right, not too strong but clearly noticable.
I first wanted to use a real rotary sensor, but it didn't feel right, and there was a too high probability to rotate unintentionally when using the 4-way joystick.
Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on February 14, 2017, 01:54:12 am
Next step is finished ! I soldered 11 resistors (1.2k) between the twelve pins of the switch, so that the whole construction acts like a potentiometer (three wire solution).
First tests using an Arduino Micro were pretty succesfull, I now will implement the final sketch. The main advantage is, that you need only one analog input for one rotary stick, so an Arduino can handle up to twelve sticks (theoretically ! Who in the world needs twelve rotary sticks ?  ;) )
The Arduino Micro can act as a native HID controller, so that keyboard, joystick and mouse commands can be natively sent to the PC over USB.
I already used a Arduino Leonardo using HID in my Pinball cabinet as a keyboard/joystick controller for plunger and nudging, works like a charm.

Links:
http://jespereklund.blogspot.co.at/2011/10/rotary-selector-switch-for-arduino.html (http://jespereklund.blogspot.co.at/2011/10/rotary-selector-switch-for-arduino.html)
https://github.com/NicoHood/HID (https://github.com/NicoHood/HID)

Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on February 15, 2017, 05:09:23 am
First tests with one stick attached worked like a charm  ;D
The only thing, that is urgently needed, is a small capacitor between ground and analog input port for debouncing !
Title: Re: Yet another Rotary Joystick project
Post by: melvinbates on February 15, 2017, 10:57:51 am
That's an interesting idea with the resistors, very cool.
Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on February 15, 2017, 01:08:58 pm
That's an interesting idea with the resistors, very cool.
And it really works great, today I simultaneously tested with two rotary sticks, no glitches, no false moves regardless how fast I rotate the handle.
For now the only thing with Arduino keyboard is, that it can only send regular ASCII characters but no special chars. I have to check MAME, which free keys I could use for the movements of both players (sticks), or I have to find a way to get another keyboard implementation.
Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on February 22, 2017, 05:19:23 am
I guess, that's why they call it micro  ;D
Cute !
Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on February 23, 2017, 03:08:23 am
Well, project succesfully finished ! All I have to do now is, to create a new control panel for my cab to add the two rotary sticks. As promised before, here is the sketch. Currently it is implemented for up to two sticks, but it can be easily modified for more sticks. The "If debug" parts can be removed, they are for testing only !

You have to include two Arduino libraries:
https://github.com/NicoHood/HID (https://github.com/NicoHood/HID)
https://github.com/donid/akuhell (https://github.com/donid/akuhell)

It was much fun, thanks for watching  ;D !

Quote
#include "HID-Project.h"

#include "akuhell_languages.h"
#define KEYBOARD_LAYOUT_LANG KBD_LAYOUT_EN_US
#include "akuhell.h"

boolean debug = false;
char str[512];

const int CW = 1, CCW = -1;

const int rotaryPins = 12; // number of used pins on rotary switch
const int players = 2; // for one player set to 1, for more than 2 players set to desired value, raise maxPlayers and add array values

const int maxPlayers = 2; // if more than two players are needed, raise value and add corresponding values to the arrays below
int idxLastPin[maxPlayers] = {0, 0}; // variable for storing the last pin. If adding new array values, set their value to 0
int analogPort[maxPlayers] = {0, 1}; // portnumber of used analog port for the different rotary sticks
String keyCw[maxPlayers] = {"]", "/"}; // sent keypress for clockwise rotation for the different rotary sticks
String keyCcw[maxPlayers] = {"[", "\\"}; // sent keypress for counterclockwise rotation for the different rotary sticks


void setup()
{
  Serial.begin(9600);
  Keyboard.begin();

  // store selected pins at startup
  for (int i = 0; i < players; i++) {
    idxLastPin = getActiveRotaryPin(analogPort);

    if (debug) {
      sprintf(str, "<setup> player: %d / active pin: %d", i + 1, idxLastPin + 1);
      Serial.println(str);
    }
  }
}

void loop()
{
  // check rotation for all sticks/players
  for (int idxPlayer = 0; idxPlayer < players; idxPlayer++) {
    handleRotation(idxPlayer);
  }

  delay(10);
}

int getActiveRotaryPin (int port)
{
  float pinVal = 0.0;
  int pinValRaw = 0 ;
  int pinIndex = 0;
  float divider = 1023.0 / (float)(rotaryPins - 1);

  pinValRaw = analogRead(port);
  pinVal = round((float)pinValRaw / divider);
  pinIndex = pinVal;

  return pinIndex;
}

void handleRotation(int idxPlayer) {
  // get current selected pin
  int idxActivePin = getActiveRotaryPin(analogPort[idxPlayer]);

  // stick was rotated ?
  if (idxActivePin != idxLastPin[idxPlayer]) {
    if (debug) {
      sprintf(str, "<handleRotation> player: %d / pin %d to %d", idxPlayer + 1, idxLastPin[idxPlayer] + 1, idxActivePin + 1);
      Serial.println(str);
    }

    // send key
    if (idxLastPin[idxPlayer] > idxActivePin && idxLastPin[idxPlayer] - idxActivePin > 3) {
      sendKey(idxPlayer, CCW);
    }
    else if (idxActivePin > idxLastPin[idxPlayer] && idxActivePin - idxLastPin[idxPlayer] > 3) {
      sendKey(idxPlayer, CW);
    }
    else if (idxActivePin > idxLastPin[idxPlayer]) {
      sendKey(idxPlayer, CCW);
    }
    else if (idxActivePin < idxLastPin[idxPlayer]) {
      sendKey(idxPlayer, CW);
    }

    // store current pin as source for next movement
    idxLastPin[idxPlayer] = idxActivePin;
  }
}

void sendKey(int idxPlayer, int dir) {
  switch (dir) {
    case CW:
      if (debug) {
        sprintf(str, "<sendKey> player %d: / CW ", idxPlayer + 1);
        Serial.println(str);
      }

      Keyboard_writeUtf8Character(keyCw[idxPlayer]);
      break;

    case CCW:
      if (debug) {
        sprintf(str, "<sendKey> player %d: / CCW ", idxPlayer + 1);
        Serial.println(str);
      }

      Keyboard_writeUtf8Character(keyCcw[idxPlayer]);
      break;

    default:
      break;
  }
}
Title: Re: Yet another Rotary Joystick project
Post by: PL1 on July 28, 2020, 10:13:32 am
And here they are in format "step", you should be able to open the file in the usual suspects like Fusion360.
Have fun  :cheers:
Thanks for sharing.   :cheers:

Download link for the 3d parts:  http://forum.arcadecontrols.com/index.php?action=dlattach;topic=163248.0;attach=384000 (http://forum.arcadecontrols.com/index.php?action=dlattach;topic=163248.0;attach=384000)  (embedded in other thread)


Scott
Title: Re: Yet another Rotary Joystick project
Post by: Ginsonic on July 28, 2020, 10:44:44 am
You're welcome!

BTW in the version attached I modified a few parts, the axis for the rotary lever is no longer printed, please use a long screw and a nut (much more stable), and the joystick mounting holes are more versatile now!
I only glued the microswitches, works like a charm, but please feel free to modify the switch box and add mouting holes.
After inserting the inner part of the rotary handle, there are two small slots at the bottom to lift it up a bit in order to remove it later on for service purposes!