I built 10$ trim wheel for myself and my brother. Both are working perfectly.
If anybody is interested here are some details:
- Arduino Pro Micro ATmega32U4 (compatible clone) - 6$
-very easy to buy - rotary encoder 30 impulses per rotation (higher is better) - 1$
-most encoders are 24 impulses or less, 30 or more are much better - star knob M10 (diameter 50-65 mm) - 1$
-prefered 8 sided or more (hard to buy), 5 sided or less will look and feel bad (easy to buy)
-star knob is mounted on encoder via plastic nail expansion anchor cuted in half and reamed a little. This is most problematic part because is very hard to mount it streight, maybe gluing might be easier. - three jumper wires female to female - 1$
-very easy to buy - micro USB cable - 1$
-very easy to buy
I wrote custom firmware for Arduino and rotary encoder because all code which I found on internet worked bad and were loosing precision. I also added communication via virtual COM port (thru USB), so I am able to set encoder to proper position when for example autopilot changed a trim (my software is communicating with Flight Simulator to read the trim from the sim and then is sending this value via COM port to Arduino).
Where to buy parts:
AliExpress (cheap), local stores, eBay, Amazon (expensive), Allegro (Poland)
How to connect:
Rotary encoder with button has 3+2 pins (without button 3 pins). Connect yellow to left, green to middle, blue to right.
At the board connect yellow to pin 7, green to pin GND (on the same side as 7 & 8), blue to pin 8.
If you want revert rotation direction then switch yellow with blue at the board or at the encoder (better to switch wires than use reverse option in FS settings).
How to flash the board:
- Install Arduino IDE 2.x and start it.
- Connect the board, select “Tools > Port > Arduino Leonardo” and COM port.
- Paste source code (sketch) to the editor.
/*
* Trim Wheel 1.0 for Arduino Pro Micro/Leonardo (ATmega32U4)
* with incremental rotary encoder
* (c) 2021 Szymon SZZYY Zielinski
* szy.ziel@gmail.com
*/
#include <Joystick.h>
#define ROTPIN_A 8
#define ROTPIN_B 7
#define ROT_RESOLUTION 255 /* 1 impulse = 100%/255 = 0.4% of max trim */
static int PrevStateAB;
static int RotDir, RotVal = 0;
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD,
0, 0, // Button Count, Hat Switch Count
false, true, false, // only Y Axis
false, false, false, // No Rx, Ry, or Rz
false, false, // No rudder or throttle
false, false, false); // No accelerator, brake, or steering
void setup() {
pinMode(ROTPIN_A, INPUT_PULLUP);
pinMode(ROTPIN_B, INPUT_PULLUP);
Serial.begin(9600);
Joystick.begin();
Joystick.setYAxisRange(-ROT_RESOLUTION, ROT_RESOLUTION);
PrevStateAB = (digitalRead(ROTPIN_A) << 1) | digitalRead(ROTPIN_B);
}
void loop()
{
int CurrStateAB;
/*
* Encoder can be set by external program via COM port.
* This functionality is required by autopilot or flaps auto trim.
*/
if (Serial.available() > 1)
{
RotVal = (Serial.read() << 8) | Serial.read();
}
/*
* rot1 11->01 01->00
* rot2 00->10 10->11
* -rot1 11->10 10->00
* -rot2 00->01 01->11
*/
CurrStateAB = (digitalRead(ROTPIN_A) << 1) | digitalRead(ROTPIN_B);
if (PrevStateAB != CurrStateAB)
{
int PrevCurrStateAB = (PrevStateAB << 2) | CurrStateAB;
if ((PrevCurrStateAB == 0b1101) || (PrevCurrStateAB == 0b0010))
{
RotDir = 1;
}
else if ((PrevCurrStateAB == 0b1110) || (PrevCurrStateAB == 0b0001))
{
RotDir = -1;
}
else if ((PrevCurrStateAB == 0b0100) || (PrevCurrStateAB == 0b1011))
{
if ((RotDir == 1) && (RotVal < ROT_RESOLUTION))
{
RotVal++;
Joystick.setYAxis(RotVal);
/* Serial.println(RotVal); */
}
}
else if ((PrevCurrStateAB == 0b1000) || (PrevCurrStateAB == 0b0111))
{
if ((RotDir == -1) && (RotVal > -ROT_RESOLUTION))
{
RotVal--;
Joystick.setYAxis(RotVal);
/* Serial.println(RotVal); */
}
}
PrevStateAB = CurrStateAB;
}
}
- Add below joystick library. Click the on the “library icon” and select install.
https://github.com/MHeironimus/ArduinoJoystickLibrary/archive/version-2.0.zip - Select “Upload” from main editor. It should compile the code and upload it to the board.
How to test the trim:
- In Windows click Start button, type joy.cpl in the Start Search box, and then press ENTER.
- Select Arduino Leonardo, and then click Properties.
- On the Test tab cross should go up or down if you rotate the wheel.
To check real resolution of encoder just enable println (remove /* and */) in the code. You should see in Arduino IDE Serial Monitor (enable it in Tools) rotation values.
Problems:
When autopilot or flaps auto trim change trim value then this value must be send to trim wheel to avoid inconsistency (for example if you rotate wheel to 10, then autopilot change trim to 20, then you rotate wheel again, trim will skip to 11 which is wrong).
I made a special program which is connected to MSFS and is sending new trim values to Arduino when required. This program is only required if you are using autopilot or plane has flaps auto trim. You need start it before or after MSFS start. Can be downloaded from here:
Can I connect second wheel or other stuff to one board?
Yes, but changes to source code are required.