Multiple Rotary encoders - help

Hi everyone,
Ahead of everything, i apologise as i am so new to all this. I have spent the last week learning something i really dont have much of an idea about. After a week, i know enough to be able to communicate with hopefully, some of you in a way that i dont frustrate you.
Perhaps i have the wrong board, the wrong software, i dont know.

Here is my project
4 simple rotary encoders mounted in a housing, connected it to USB port, using it in my flight sim so that i can adjust values for different instruments in the cockpit eg heading bug, course bar altitude, VOR (these can be assigned in the sim once device is plugged in and recognised as a USB device

Equipment and software
U PICO Pi board
micropython
flightsim - Xplane 11/12

Success thus far
I have managed to find a simple code for one rotary encoder, i have worked out some of the coding, trial and error and have limited understanding of coding - but in the readout, as i turn the encoder i have the values increasing and decreasing.

Problem 1
I have no idea how to use the current code i found and duplicate it 3 more times for the other 3 encoders.

Problem 2
I have no idea of what i need to do in order for the pico board to be recognised as a USB device - whether it needs to be a gamepad or joystick or something else
I “think” i will need to install a library for this to happen, but again, no idea which one or where to get it from, let alone the code i need for the pico so that it just works.

Below is a link i used from youtube (this is how i found this forum) the link to the files im using and a copy of the code which works, showing the increasing and decreasing values of the encoder as i turn the knob.

I am pretty sure you are all laughing right now, because what i am trying to achieve is probably so simple as putting the keys in the ignition of a car and turning the key, for that i apologise.

I am determined to get this done, i have even tried to use Arduino IDE to do this, but there too i run into iussues where i cannot find any good tutorials, or code to help me…even chatgpt didnt work - that was the last resort.

So i hope someone here has the patience to help or to guide me so that i can learn how to do this so i feel some sense of achievement - even if it you attach what ever i need to this post just to get me out of your hair.

Thank you ahead and please be kind …lol

link i used to find you with the files in the description

code i am using at the moment (its for only 1 encoder)


# A simple example showing how to read values from a rotary encoder
# Requires the RotaryIRQ library from https://github.com/miketeachman/micropython-rotary

from rotary_irq_rp2 import RotaryIRQ


# Enter the two GPIO pins you connected to data pins A and B
# Note the order of the pins isn't strict, swapping the pins
# will swap the direction of change.
rotary = RotaryIRQ(3, 4, pull_up=True)

# If you're using a Standalone Rotary Encoder instead of a module,
# you might need to enable the internal pull-ups on the Pico
# rotary = RotaryIRQ(14, 15, pull_up=True)

current_val = 0  # Track the last known value of the encoder
while True:
    new_val = rotary.value()  # What is the encoder value right now?
    
    if current_val != new_val:  # The encoder value has changed!
        print('Encoder value:', new_val)  # Do something with the new value
        
        current_val = new_val  # Track this change as the last know value
        
rotary2 = RotaryIRQ(6, 7, pull_up=True)
current_val = 0  # Track the last known value of the encoder'

apologies, this is the code i am using

# A simple example showing how to read values from a rotary encoder
# Requires the RotaryIRQ library from https://github.com/miketeachman/micropython-rotary

from rotary_irq_rp2 import RotaryIRQ


# Enter the two GPIO pins you connected to data pins A and B
# Note the order of the pins isn't strict, swapping the pins
# will swap the direction of change.
rotary = RotaryIRQ(3, 4, pull_up=True)


# If you're using a Standalone Rotary Encoder instead of a module,
# you might need to enable the internal pull-ups on the Pico
# rotary = RotaryIRQ(14, 15, pull_up=True)

current_val = 0  # Track the last known value of the encoder
while True:
    new_val = rotary.value()  # What is the encoder value right now?
    
    if current_val != new_val:  # The encoder value has changed!
        print('Encoder value:', new_val)  # Do something with the new value
        
        current_val = new_val  # Track this change as the last know value

This line

rotary = RotaryIRQ(14, 15, pull_up=True)

establishes an object with the name ‘rotary’ that you can reference in a line such as

new_val = rotary.value() # What is the encoder value right now?

in order to get the value. So if you have more devices you use the same code to create the other objects but with different names (rotary1, rotary2, perhaps) and the appropriate pin numbers for those other encoders. Then duplicate the code you are using to handle the value, substituting the correct object name, and using separate variables if you need to keep track of them simultaneously.

Whether or not the Pico needs to be a gamepad or joystick or some other USB device depends entirely on the application that you are interfacing it to - XPlane 11/12. Is there a user forum for that application?. If it’s accessible someone may be able to look at it for you and find the section that refers to interfacing external devices.

Meanwhile you can get the other encoders up and running and oputput the results to console to confirm that your code can retrieve and process each value.

2 Likes

Hi Jeff105671,
Thank you so much. I managed to work out the code for 2 encoders after my post, so now i know how to handle that part.

In relation to the xplane, when i set the pico up using Audrino IDE and had it as a joystick/game pad device, xplane just simply recognised it when i plugged it in. I am thinking that should also be the case using micropython. I just dont know which library to use and the code i need for the pico to become an extrenal usb device. I looked at the user manual fro the flight simulator and it just says " Note: X‑Plane can only interface with USB devices. This covers nearly all the controllers manufactured in the last ten years, but if you have a non-USB device, an adapter will be needed to change it to a USB input.

Does any of this help? Thank you again :slight_smile:

So there are two parts to that - the first is to set up the Pico Pi as a USB device. Then you need to find out exactly what is meant by “nearly all the controllers manufactured in the last ten years” because I suspect that is not quite so broad a range of devices as it implies, but in any case you still have to be specific about what USB device the Pico will be.

For instance, if the app supports a keyboard HID as a game controller then there is an example of a project here:
Custom USB games controllers with Raspberry Pi Pico

The Pico is configured as a keyboard HID. You will need to know the keyboard codes for each function that is supported. Code for the controller then converts user input (rotary encoders in your case) to key sequences.

1 Like

Hi Hubert
I have done just that. Only difference I have XPlane 10. I have used 10 encoders. 9 for Nav and DME tuning and 1 for elevator trim.

Each encoder button has to be filtered or switch bounce will scramble the whole thing and readings all over the place. So I cheated a bit and used a product designed and sold by Leo Bodnar of IK. I used 2 boards. The first has the encoder connections as part of a matrix but to display approximate elevator trim position I needed to connect a small Arduino in parallel with one of the inputs which the matrix would not allow. So I had to upgrade to a bigger Bodnar board which would allow this.

Google “Leo Bodnar” to get to his site for details. All debounce is taken care of within these boards.

These boards are plug and play and each encoder switch appears in XPlane so you can assign whatever function you like to them. These boards also have 8 analog inputs which appear as axes in Plane and once again can be assigned anything which requires analog input (pitch, Roll etc)

The Arduino is used purely to analyse the encoder inputs and drive the LEDs for elevator trim approximate position. The push button on that encoder is used to return the trim to default “take off” position.

Have a good read and if you have any questions feel free to ask. There are other recent posts on encoders on this forum. Search “rotary encoder” and see what comes up.
Cheers Bob

3 Likes

Hi Robert,

I have done exactly that lol, i have one of those Leo Bodnar boards on its way. I was hopin the pico board i have i can achieve the same thing - and learn something new…oh and not let it send me insane as i don’t tend to give up … ha ha ha…

1 Like

Hi Hubert
Sorry that link take you to the project. There is more info on the progression to the larger board on the forum posts here

Project by Robert; Potentiometer Position Monitor

Search the forum for that to get more info.
Cheers Bob
What Bodnar board are you getting??
EDIT. Sorry for confusing the issue. The link take you to the Forum post. The “Read more” link takes you to the project which outlines the initial story.

1 Like

this is the board i have ordered

thank you again, i will keep exploring…its a very steep learning curve :wink:

Nothing posted. No board.
Cheers Bob

BBI-32 Button Box Interface - With Connectors

Hi Hubert
Yes that should work nicely. You might have to download some configuration software. I used the BU0836A with the breakout matrix board and later changed to BU0836X which doesn’t have the buttons laid out in a matrix format. I am using some of the Analog inputs which the Button Box Interface does not have.
If you need the configuration software it is pretty self explanatory and easy to use, you are basically telling it that the buttons are Rotary Encoders or straight buttons. When I got it it was Windows only which was not a big deal as although I use a Mac I also have a (old) Windows laptop unit. I think from memory once loaded the software starts up as soon as you plug your board into the computer.

My boards seem to handle switch bounce very nicely so I imagine yours will too. They work very well and seamlessly integrate with XPlane.
Cheers Bob

1 Like

Hi Hubert,

Welcome to the forum :slight_smile:
I’ve just edited your first two messages slightly to fix the formatting on the code sections and make it a bit easier to read.

Sounds like Jeff and Bob have already got you sorted with some great advice on all the main points of your project in question. Best of luck with the flight sim controller build, please report back with some photos of the build so we know how it turns out!

1 Like

Awesome…i am still determined to get this damn pico board to be recognised as a USB device so that xplane can see it. I managed it using Arduino IDE but i just cant wrap my head around circuit python…it surely cant be that hard…

Hi Trent,

Thank you

Hi hubert

Interesting to do as a learning exercise but if you use the Bodnar board you won’t need to. The Bodnar board is recognised quite happily and all the connected buttons are there ready to be assigned.
Cheers Bob

2 Likes

Hi Trent,

I thought i would turn to you as i am really lost. I am not sure if i am even making sense in what i am looking for around my issue. I am determined to resolve this as i this Pico board using Arduino can do what i need. All i need is to know what code/library i need to use so that the Pico is seen as a USB device. I have a sample code which proves this to work in the simulator i am using and it does recognise it as a joystick/game controller. This is the link. When i run this, the sim recognises the pico as a joystick. All i need to do is remove everything in this code bar the encoders…i must be stupid…Pico RP2040 HID Joystick Library for Arduino IDE - YouTube

hope you or anyone else can help this stupid old man ha ha ha

1 Like

Hi Hubert,

Really sweet project! Keen to see it.
Though unfortunately micropython doesn’t have any HID support at the moment, so you’ll have to use the Arduino library in that link.

The only rotating bit in the tutorial is the potentiometer, adding some code to keep track of the encoders wont be too much of a stretch once you check out the tutorials below.

(Here’s a link to a couple guides on Encoders with the Arduino:

https://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/)

Using the position from each of the encoders you can keep track of and set one of the Joystick objects from the HID library:
void PicoGamepad::SetX(uint16_t val)

Other analog inputs for your controller:
// gamepad.SetZ(val);
// gamepad.SetRx(val);
// gamepad.SetRy(val);
// gamepad.SetRz(val);
// gamepad.SetS0(val);
// gamepad.SetS1(val);

If you hit any roadblocks with it let us know and we can help out! :slight_smile:

4 Likes

If you have the example working then you have already achieved this.

That example uses the library PicoGamepad

#include <PicoGamepad.h>
PicoGamepad gamepad;

Then, when you read the encoder value as in your first example (‘new_val’) you set the virtual joystick axis that you want to use to that value and send it to the device. Something like:

    . . .
    if (current_val != new_val) {    // The encoder value has changed!
    gamepad.SetX(new_val);       // Do something with the new value
    gamepad.send_update();        // Send that input via HID
       
4 Likes