A simple dial (aka spinner) input control using arduino and a rotary encoder. The dial is shown in the computer as a mouse with X movement. The movement has been tuned to be "accelerated" so if you do small movements, you have precision, but if you move it kickly, it runs faster. Use a modified version of ClickEncoder library. See below for more details.

Demo video on YouTube

This project provides:

  1. The chassis' fabrication models (3D print) and assembly guide.
  2. The arduino sketch to control the encoder and pass the mouse inputs to the computer.

Table Of Contents

  1. Project Features
  2. Part List
  3. 3D Printing and Assembly
    1. Parts
      1. Wheel
      2. Chassis
      3. Arduino Holder
      4. Spacers
    2. Assembly
    3. Arcade Installation
  4. Electronics
    1. Encoder Mod
    2. Wiring
  5. Software
    1. Install
      1. TimerOne
      2. ClickEncoder
      3. ArduSpinner
    2. Tests
    3. Binary
    4. Mame

Project Features

  1. Complete implementation for a dial (aka spinner) input control. Just print the files, wire it, download the sketch and play in MAME. The main motivation was to create a low profile, MAME compatible (in fact, it works in all computers that accept a USB mouse as input) input device to play arkanoid style games.
  2. Low profile device. Just about 3cm width, 8cm height.
  3. Easy to use. Just plug and play with minimum MAME configuration.
  4. Easy to build.
  5. Cheap.

Part List

To build ArduSpinner you need the following things:

3D Printing and assembly

There are 4 parts that you have to print. The STL are ready positioned in the "right" way to be printed, so just print them as is. I use a Ender-3 Pro with Marlin Firwmare, and PLA, and get good results. I use CURA for slicing with the following major configuration settings:

Layer Height0.21
Initial Layer Height0.32
Wall Thickness0.88
Wall Line count3
Top/Bottom Thickness0.92
top Thickness0.92
Top Layers5
bottom Thickness0.92
bottom Layers5
Top/Bottom patternlines
Horizontal expansion0
Infill density60>#/td###
Infill patterngrid
Printing temperature190
Printing temperature initial layer195
Build plate temperature55
Build plate temperature initial layer75
Initial Layer flow100
Enable retractionChecked
Retraction Distance6.5
Retraction Speed50
Print Speed50
Infill Speed50
Wall speed25
Top/Bottom speed25
Travel Speed150
Initial Layer Print Speed15
Initial Layer Travel Speed30
Combing modeAll
Avoid Supports when travellingchecked
Z Hop when retractedchecked
Enable Print coolingchecked
Fan Speed100
Initial Fan Speed0
Regular Fan Speed at Height0.72
Regular Fan Speed at Layer3
Generate SupportChecked
Support PlacementEverywhere
Support Overhang Angle47
Support PatternZigZag
Support Density20
Support Z Distance0.2
Suport X/Y Distance0.88
User Towersunchecked
Build plate adhesion typeNone
Surface modeNormal
Enable Bridge SettingsChecked

This table resumes the printing times for my Ender-3 configuration:

part namecuantitycolorprinting time hh:mm
arduino holder1green00:08

(I print the wheel in black, alone, and the rest of them in green, all together)




Arduino Holder



It's very easy: I recommend you to wire it first:

  1. Put the encoder with the connectors as shown in the first photo, and screw the nut tight.
  2. Put the spaces between the arduino holder and the back of the encoder, and screw then. Yo get something like a sandwitch (second photo). This allows to create some force between the rod and the back of the encoder.
  3. Put the wheel in the rod. Check that the chanfer inside the wheel fits the chanfer in the encoder's rod. Push to the end and you get arduspinner mounted.
  4. Press the arduino inside the arduino holder, if you want to mount it there.

Arcade Installation

I design the ArduSpinner to get a low profile, so you can install it in the joystick plate from your arcade machine. I cut a hole of 6.5cmx2.5cm in the table, and screw the ArduSpinner to it. The arcade machine is an own design and it is slim (wood width is about 1cm), but ArduSpinner can be fitted from 1.6cm to 1cm wood boards (or less).


Encoder Mod

The KY-040 encoder is a continuous encoder, so you can rotate from left to right continuous. But to "feel" it, the encoder comes with some detents so you get feedback when rotate it. To play, is somewhat crappy, so I remove the detents. This part is just a simple spring that detents the encoder plate. It's easy to remove it.

  1. Remove the metallic cover, put in place with 4 pins. Use a plyer and straight them, and remove it (left size of the photo)

  1. You find the upper part, the rod with the encoder, and the lower one, the contacts with the button, made in plastic We need to fix the upper part (the rod) so don't mess to much with the lower one (lower part not shown).
  2. Remove the plate encoder (just pull) and remove with the plyer the spring (the metallic part in the center of the first photo), then push the plate again into the rod. The should move freely.
  3. Assembly the thing. Check for the small metallic plate in the lower part (the button) is in place, put the metallic cover and bend again the pins, and you get a smooth encoder without detents, and a free spring.


Encoder PINArduino PINWire ColorNotes
+VCCredWorks on 5V and 3V
SWD4whiteNot used, so not connected
DTD2greyDigital Interrupt PIN
CLKD3pinkDigital Interrupt PIN


This sketch only works on boards with the ATmega32U4, so the USB interface can be reprogrammed to simulate a USB device (HID) and send inputs to the computer. It's possible to use a software USB stack and use a ESP8266, but it is very complex and only allow a small range of posibilitites. With the new ESP-Pro version, we can reprogram the USB controller as the ATmega32U4. You can use Arduino Leonardo or Micro (I use the last one for size). Pick the original board if you can to support Arduino.

The software is very simple: Just read the data from the rotary encoder, and map it to mouses' X position. There's not so much to be configured, so it should work as is. You can change the PIN assigments, but remember that D2 and D3 are the digital pins that allows interrupts, so if you plan to modify the sketch to use interrupts instead of polling, leave them as is.

IMPORTANT NOTE: On MacOS 10.12.6 I can't get the Leonardo's USB interface with Arduino IDE 1.8.8 working. So please use Windows to burn the Sketch, or use a more updated version of MacOS.


You need the following libraries installed in your Arduino libraries folder.


This library is required in order to work, so you can install it from the Arduino IDE's Library Manager. Just go to Sketch->Include Library->Manage Libraries menu, and search for TimerOne. Add it and that's all.



I modify the library to reset the Acceleration when the direction changes, and tuned the acceleration values for my application, so you need to copy it to the Arduino libraries folder (Usually in your Documents folder). Just copy the encoder directory.



After install and copy the libraries, just restart the Arduino IDE, and open the arduspinner.ino sketch. Now, Just select in the Tools Menu, Boards and check the Leonardo. Select the port, and flash arduspinner.ino on it. That's all. When you move the spinner, the led flashes.

Uncomment //#define RELASE 1 if you want debug output to the Serial Monitor (at 115200 bauds)


In dev/ folder you could find some tests. They are created to test some functionality. Just for reference.


I provide the compiled version for the sketch:

You can put the file directly in the arduino using for example avrdude or Arduino Builder the process is fairly complex and you can brick the arduino. I recommend you to build and flash using the ide istead, but if you want to try, you're welcome.


There is a minimum configuration in mame.ini file. Just change keyboard to mouse for dial_device. Save and play. The MAME options for Analog input are set as default (I don't change them). Enjoy!

As a side note, if you run your arcade in windows 7 and you want that Windows doesn't start never in recovery mode, log into windows, and launch a cmd as administrator. then run this: