Jump to content

rotary encoder for 1:1 knob turning?


Sprool

Recommended Posts

In my current button box build I have a matrix of 4 rotary encoders, and I want the on-screen dial/knob rotation to mimic the rotation of the rotary encoder on the panel.

Since a lot of the DCS key mapping allows for keypresses to increment a parameter up or down, such as cockpit instrument light brightness or heading indicator, using a rotary encoder each small rotation step results in what the joystick controller recognises as a button depress, that just nudges the dial or setting one small increment up or down. The result is for a knob on the game to turn one revolution you have to turn the rotary encoder about 20 revolutions. Is there a way I can get it to turn on 1:1 ratio? Some setting in game or default lua, or some extra code I could add - its Arduino-board driven?

Link to comment
Share on other sites

Heres the code covering the 4 rotaries,

void rotary_init() {
 for (int i=0;i<NUMROTARIES;i++) {
   pinMode(rotaries[i].pin1, INPUT);
   pinMode(rotaries[i].pin2, INPUT);
   #ifdef ENABLE_PULLUPS
     digitalWrite(rotaries[i].pin1, HIGH);
     digitalWrite(rotaries[i].pin2, HIGH);
   #endif
 }
}


unsigned char rotary_process(int _i) {
  unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1);
 rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
 return (rotaries[_i].state & 0x30);
}

void CheckAllEncoders(void) {
 for (int i=0;i<NUMROTARIES;i++) {
   unsigned char result = rotary_process(i);
   if (result == DIR_CCW) {
     Joystick.button(rotaries[i].ccwchar, 1); delay(25); Joystick.button(rotaries[i].ccwchar, 0);
     Joystick.button(rotaries[i].ccwchar, 0);
   };
   if (result == DIR_CW) {
     Joystick.button(rotaries[i].cwchar, 1); delay(25); Joystick.button(rotaries[i].cwchar, 0);
   };
 }
}

Really not sure which i can edit to give more movement, what are you like on arduino code?

All its doing is going through the 4 encoders then outputting (digital write) one pulse CW or one pulse CCW if it detects any of the encoder state have changed. How can I get DCS to amplify the response to move the knob/dial a lot more per pulse?


Edited by Sprool
Link to comment
Share on other sites

This version compiled ok, if I left it as rotaries = rotaries * 2; i got an error;

void CheckAllEncoders(void) {
 for (int i=0;i<NUMROTARIES;i++) {
   unsigned char result = rotary_process(i);
   if (result == DIR_CCW) {
     Joystick.button(rotaries[i].ccwchar, 1); delay(50); Joystick.button(rotaries[i].ccwchar, 0);
     rotaries[i].ccwchar = rotaries[i].ccwchar*2;
     };
   if (result == DIR_CW) {
     Joystick.button(rotaries[i].cwchar, 1); delay(50); Joystick.button(rotaries[i].cwchar, 0);
         rotaries[i].cwchar = rotaries[i].cwchar*2;
   };

However the knob doesnt turn at all now in game?

Link to comment
Share on other sites

isnt the 1 or zero just acting as a flag on/off to register the rotary has changed position, cw or ccw? If so then making the number bigger will not achieve anything, if I get it to output 2, 3 or 4 pulses each time it moves then maybe that would work ?

Link to comment
Share on other sites

  • 2 weeks later...

From Longuich:

"..so what an encoder does is add or subtract (usually) 4 from what its current values is.

Hence the equation to see whether you're turning it clockwise or counterclockwise.

 

if I'm reading it all correctly you just get a 1 or 0 for the left and right pins on the encoders. there's no way to make those values more.. unless you tell the script to press "turn left" or "turn right" twice.

 

 

if (result == DIR_CCW) {

Joystick.button(rotaries.ccwchar, 1); delay(50); Joystick.button(rotaries.ccwchar, 0);

 

};

if (result == DIR_CW) {

Joystick.button(rotaries.cwchar, 1); delay(50); Joystick.button(rotaries.cwchar, 0);

};

 

 

this here turns the joystick button press on and or off.

I'm missing the part where all joystickbutton states are sent to the computer.

 

could you try and see what happens if you change the code to:

 

if (result == DIR_CCW) {

Joystick.button(rotaries.ccwchar, 1); delay(50); Joystick.button(rotaries.ccwchar, 0);

Joystick.button(rotaries.ccwchar, 1); delay(50); Joystick.button(rotaries.ccwchar, 0);

 

};

if (result == DIR_CW) {

Joystick.button(rotaries.cwchar, 1); delay(50); Joystick.button(rotaries.cwchar, 0);

Joystick.button(rotaries.cwchar, 1); delay(50); Joystick.button(rotaries.cwchar, 0);

};

Link to comment
Share on other sites

This just sends out 2 signals as keypresses instead of one to DCS, in effect getting the knob to rotate 2 click instead of one. Fine for some knobs like cockpit illumination, instrument brightness, etc, but then knobs like hornet radio channel select will miss out every other channel.

Link to comment
Share on other sites

Correct. We found that the current script does not support anything other than a single or double (of triple) pulse; bcause it’s a generic loop that catches all encoders and treats them all alike. Which is obviously the way we wwnt it in 2020 ,)

 

 

Sent from my iPhone using Tapatalk

Link to comment
Share on other sites

Thanks, gents. I have now subscribed to this thread. (I hadn't before:doh:)

 

I am a noob, so I have very limited coding ability.

 

if (result == DIR_CCW) {
Joystick.button(rotaries[i].ccwchar, 1); delay(50); Joystick.button(rotaries[i].ccwchar, 0);

 

My understanding of this code is that the HID joystick button is pressed, held for 50 milliseconds, and then released.

 

If you would like to have the rotary encoder (RE) move the in-game knob more with every detent of the RE, simply increase the delay time so that the HID joystick button is held down for a longer time before being released.

 

I am thinking about using DCS-BIOS now, as I would like to use my little button box for multiple modules and need those delay times to be different for different modules and different in-game knobs.

 

If you would like to try my RE code below, feel free. I separated the REs out so that I could use different delay times for different encoders. Here are the relevant bits of code for an RE connected to pins 0 and 1 that press joystick buttons 16 and 17:

 

int prev0; //global integer variable to hold on/off state of PIN 0

void setup() {
 pinMode(0, INPUT_PULLUP); //apply voltage to the pin (I think)
 prev0 = digitalRead(0); //read the current state of pin 0 and stick it into prev0
 }

void loop() {
   if (digitalRead(0) != prev0 && digitalRead(0) == 1){  //if pin 0 changes
   if (digitalRead(1) != digitalRead(0)){                        //and if the RE is rotated one direction
   Joystick.pressButton(16); delay([b]YOUR_DELAY_HERE[/b]); Joystick.releaseButton(16); 
   } else {                                                                 //or if the RE is rotated the other direction
   Joystick.pressButton(17); delay([b]YOUR_DELAY_HERE[/b]); Joystick.releaseButton(17);
   }
}
   prev0 = digitalRead(0); //read the current state of pin 0 and stick it into prev0
}  

I am copying and pasting bits and pieces here so there might be some curly bracket error :blush:

I hope this makes sense. More importantly, I hope it is correct.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...