Learning to make an Arduino pro micro based HID

Hi all,
I’m looking for help on how to make a HID with some specific control function. The device is supposed to control functions on Digital Combat Simulator.

For my specific device I have the following constraints:
3x potentiometer, with one pot functionally limited to 90 degrees (it can rotate further, but I want it to linearly reach the max over the first 90 degrees of rotation).
2x rotary encoder. The encoders are basic ones without pcb (installation space constraint), so I will only use pin A, pin B, and the Gnd pin. Any pull-up resistors would have to be activated internally to the arduino.
1x (on)-off-(on) switch, with both (on) positions wired to a unique pin, and no function for the off position (I.e. not wired).
Debounce through software for switch and rotary encoders.

I asked AI to help me get a code for this, but apparently others believe the sketch created by AI is inconsistent. It also doesn’t work ( not sure if that’s because of pins 0 and 1 being used for one encoder. I was told I cannot use pins 0 and 1.). Happy to share that ode if someone is interested and believes it’s a good starting point.

Now I’m an absolute noob when it comes to programming and how electronic components might affect that programming, but rather than have someone give me the code, I’d like to learn how to come up with the right code.
So I was thinking, if someone can teach me the building blocks, and I then mix and match those for my device, that way maybe I learn to do this independently myself.
E.g. if someone can tell me how to programme a single rotary encoder, how to programme a single switch, and a single potentiometer, maybe enhanced with how to ramp the range within 90 degrees, then I imagine I can work out at least for this device the whole thing myself.

There may be constraints to pin usage for pots, rotary encoders, and/or switches/buttons. I’d love to hear about those too.

As a note, I cannot find good tutorials for what I want, either here, on google or YouTube, hence my request here.
Many thanks in advance!

That is a good approach. Forget about HID until you understand how to use rotary encoder, potentiometer, and a single switch.
This link should explain how to read a potentiometer.
Using switches is very simple. Connect one side of the switch to the Arduino input pin, and connect the other side of the switch to Gnd. Use pinMode(x,INPUT_PULLUP), where x is pin number. Then use digitalRead(x) to check whether the switch is on or off. If it's off digitalRead(x) will return HIGH.
When you've got the hang of those two things, move on to rotary encoders.
At some point it would be good for you to read the Arduino Cookbook

2 Likes

@Dave_Lowther has given you great advice. I just want to add that reading buttons and switches is much more complex than it appears. Check the built-in Examples, specifically Debounce, to understand the problem. Then go ahead and use any of the dozens of bounce or button libraries to handle the details, especially double, triple, long press, etc.

1 Like

Thanks both.
I actually managed to get some code together for managing rotary encoders with debounce and it works really nicely. Only thing is, I only know how to do a serial print to IDE for it. I don’t know how to turn the output into an action on the pc (in my case it would be an in-game command).

I would have expected switches to be really simple (except for multi presses and debounce etc), and I understand the need for pull up resistors.

I can see how potentiometers can be not complex, especially with constraints to range values etc.

In my case, I’m using Arduinos to simulate physical controls for a flight simulator, soo the only interaction I’m planning to have is between the Arduino and the pc.

I’ve taken the note of the cookbook. Are there other illustrative books on the topic I could read? My local library has only one book and it didn’t look very good (little to no code and very few illustrations). Amazon has loads, but no idea if they’re any good.

LOTS of info HERE and on the forum under Tutorials. Some will be long reads with various experts arguing fine points, but EXTREMELY valuable. One of my go-to guys is Nick Gammon, very well thought of in the Arduino world. Just type
nick gammon
into a Google search box, his forum will be the first hit; he is that famous. LOTS of good info, but it will take a while (months?) at least to read all there is in this short list.

1 Like

Thanks.

The below code is my first successful-ish sketch. Meaning, the rotaries behave exactly the way I want. Just limited to serial print.


/*
 * Arduino Sketch for Rotary Encoder Interface
 * 
 * This code interfaces with two rotary encoders connected to an Arduino Nano.
 * The first encoder is connected to pins D8 and D9, and the second encoder is
 * connected to pins D6 and D7. The common pins of both encoders are connected
 * to GND. The code reads the state of the encoders and prints the direction of
 * rotation to the serial monitor.
 */

const int encoder1PinA = 9; // Encoder 1 Pin A connected to D9
const int encoder1PinB = 8; // Encoder 1 Pin B connected to D8
const int encoder2PinA = 7; // Encoder 2 Pin A connected to D7
const int encoder2PinB = 6; // Encoder 2 Pin B connected to D6

int encoder1Pos = 0; // Position counter for encoder 1
int encoder2Pos = 0; // Position counter for encoder 2

int encoder1LastStateA;
int encoder2LastStateA;

void setup() {
  pinMode(encoder1PinA, INPUT);
  pinMode(encoder1PinB, INPUT);
  pinMode(encoder2PinA, INPUT_PULLUP);
  pinMode(encoder2PinB, INPUT_PULLUP);

  Serial.begin(9600);

  encoder1LastStateA = digitalRead(encoder1PinA);
  encoder2LastStateA = digitalRead(encoder2PinA);
}

const int debounceDelay = 5; // milliseconds
unsigned long lastDebounceTime1 = 0; // last time the encoder 1 changed
unsigned long lastDebounceTime2 = 0; // last time the encoder 2 changed

void loop() {
  int encoder1StateA = digitalRead(encoder1PinA);
  int encoder2StateA = digitalRead(encoder2PinA);

  // Encoder 1
  if (encoder1StateA != encoder1LastStateA) {
    lastDebounceTime1 = millis(); // reset the debounce timer
  }

  if ((millis() - lastDebounceTime1) > debounceDelay) {
    if (encoder1StateA != digitalRead(encoder1PinA)) {
      if (digitalRead(encoder1PinB) != encoder1StateA) {
        encoder1Pos++;
      } else {
        encoder1Pos--;
      }
      Serial.print("Encoder 1 Position: ");
      Serial.println(encoder1Pos);
    }
  }
  encoder1LastStateA = encoder1StateA;

  // Encoder 2
  if (encoder2StateA != encoder2LastStateA) {
    lastDebounceTime2 = millis(); // reset the debounce timer
  }

  if ((millis() - lastDebounceTime2) > debounceDelay) {
    if (encoder2StateA != digitalRead(encoder2PinA)) {
      if (digitalRead(encoder2PinB) != encoder2StateA) {
        encoder2Pos++;
      } else {
        encoder2Pos--;
      }
      Serial.print("Encoder 2 Position: ");
      Serial.println(encoder2Pos);
    }
  }
  encoder2LastStateA = encoder2StateA;
}

I hope I posted that code in the correct format

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.