Jump to content
The simFlight Network Forums
AK Mongo

rotary encoder input speed

Recommended Posts

Although the rotary speed is just fine when using GoFlight software, the rotary speed is terribly slow when working with Lua.

Sorry, I've no idea what you are doing now what you want to see or do. Maybe if you showed what it is you've done and what you are trying to do I might be able to advise. There is no reason why a Lua program accessing devices can't be as efficient as you need it to be. It doesn't need to be fast. Even if it only operated at 1000 Lua lines per second (though it is never anywhere near that slow), with the typically small number of lines needing executing can outpace any dial you are trying to adjust. So it must be all in the way you are programming it.

BTW "GFDev.DLL" is used by FSUIPC for GF button assignments, and is accessed by the Lua gfd library. But the "HidDemo" you refer to is all about accessing USB HID devices directly, via the Lua com library. There's no GFDev.DLL involved then, it is bypassed.

If you are only wanting to program GF devices I'm not sure why you want to go down that route. You can, but I don't think there's any big advantages. The HID facilities were mainly added to access other USB HID devices, which either could not be seen directly in FSUIPC (not being joystick or GF), or have more facilities than can be accessed using the normal methods.

Regards

Pete

Share this post


Link to post
Share on other sites

Pete,

If you are only wanting to program GF devices I'm not sure why you want to go down that route.

Using Lua, my goal is to use several GF-166 radios and have them more accurately model the function and displays of several instruments in the RealAir Beech Duke. Thus far, I have accomplished replicating the DME and XPDR. I am currently working on the ADF w/Timer.

Maybe if you showed what it is you've done and what you are trying to do I might be able to advise.

By way of example, the following is a short Lua script I am using to control/display the Altimeter on a GF-166. It is launched via ipc.ready and, via FSUIPC, the rotaries are assigned either Kohlsman Dec/Inc.


unit = 1
function AltDisp(offset, value)
value = value / 16
value = value * 0.0295302
gfd.SetDisplay(GF166, unit, 0, string.format("%2.2f ",value))
end

event.offset("0330", "UW", "AltDisp")
[/CODE]

My issue is that the rotaries can only go so fast before they bog down in making adjustments. I know that the encoders can make significantly faster adjustments because there seems to be no limit to their speed when designating the function of a GF-166 via GFconfig.

In trying to research and solve this issue, I came across this current thread on the forum and thought that it might prove helpful to me in this matter.

HidScanner has provided me with the following info for one of my GF-166 radios:

[CODE]
Device at "\\?\hid#vid_09f3&pid_0050#7&2870454e&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
Vendor=09F3, Product=0050 (Version 1.4)
Manufacturer= GoFlight
Product= GF-166
Serial Number=
Usage Page: 14
Input Report Byte Length: 4
Output Report Byte Length: 0
Feature Report Byte Length: 7
Number of Link Collection Nodes: 8
Number of Input Button Caps: 1
Number of InputValue Caps: 1
Number of InputData Indices: 9
Number of Output Button Caps: 0
Number of Output Value Caps: 0
Number of Output Data Indices: 0
Number of Feature Button Caps: 2
Number of Feature Value Caps: 5
Number of Feature Data Indices: 14
Buttons range 1 -> 8 at indices 1 -> 8
Value Dial at index 0, range -128 -> 127, using 8 bits
[/CODE]

Using this info, I made adjustments to HidDemo.lua to reflect the respective GF-166.

Vendor = "GoFlight"

Product = "GF-166"

Device = 0

Logging = true

I launched HidDemo from a button assignment in FSUIPC and made adjustments in both directions using each of the rotary encoders. However, when I went to look for the HidDemo.log in the Modules folder, it had not been generated. I tried several times in doing this step with no results.

Recalling that GF modules interact with GFDev.dll, I thought that maybe I was heading down a dead end street, and that is when I posed the question to you whether or not what I was attempting was even possible.

Your insight and direction at this point would be most appreciated.

Dan

FYI...Concerning HidDemo.lua: When I "Syntax Checked" in the LuaEdit program, it claimed that the following lines had errors. I could not see where the errors were, but thought that this might be of interest to you.

99 ipc.writeUW(0x3ba8 + ((i-1) * 2), val) -- Error Message: ')' expected near 'x3ba8'

130 ipc.writeUD(0x3340 + ((i-1) * :cool:, buttons[i]) -- Error Message: ')' expected near 'x3340'

Share this post


Link to post
Share on other sites

By way of example, the following is a short Lua script I am using to control/display the Altimeter on a GF-166. It is launched via ipc.ready and, via FSUIPC, the rotaries are assigned either Kohlsman Dec/Inc.

I've programmed lots of hardware devices like radios and so on, and there are rules I always follow:

1. When adjusting the value, stop processing changes from FS and display the update directly, locally.

2. Only display a new value from FS after n milliseconds has passed since the last change was sent.

If you don't do this you will ALWAYS have lag. In order to do what you want you need to process both the input and output in your Lua.

My issue is that the rotaries can only go so fast before they bog down in making adjustments.

Yes, exactly.

I know that the encoders can make significantly faster adjustments because there seems to be no limit to their speed when designating the function of a GF-166 via GFconfig.

Because they program it the way I suggest.

Using this info, I made adjustments to HidDemo.lua to reflect the respective GF-166.

...

I launched HidDemo from a button assignment in FSUIPC and made adjustments in both directions using each of the rotary encoders. However, when I went to look for the HidDemo.log in the Modules folder, it had not been generated. I tried several times in doing this step with no results.

The HidDemo logging uses "ipc.log" to log the data. The logging goes to the FSUIPC log unless, in the FSUIPC logging options, you check the Lua log option -- that makes each Lua write to its own log when ipc.log is used.

FYI...Concerning HidDemo.lua: When I "Syntax Checked" in the LuaEdit program, it claimed that the following lines had errors. I could not see where the errors were, but thought that this might be of interest to you.

99 ipc.writeUW(0x3ba8 + ((i-1) * 2), val) -- Error Message: ')' expected near 'x3ba8'

130 ipc.writeUD(0x3340 + ((i-1) * :cool:, buttons) -- Error Message: ')' expected near 'x3340'

Well, your line 130 has an error now, with :cool: in there, but both the original lines are fine. I don't know this "LuaEdit" (is that from the Lua website?), but it evidently doesn't check syntax correctly! Maybe you should send them a bug report?

Regards

Pete

Share this post


Link to post
Share on other sites
1. When adjusting the value, stop processing changes from FS and display the update directly, locally.

2. Only display a new value from FS after n milliseconds has passed since the last change was sent.

Pete,

What you are making me aware of is of great interest to me. However, it is also new territory for me.

I am more than eager to learn, but I am not quite sure where to start. I will dig into the LUA script examples that are included with FSUIPC to see what I can glean from there.

But any direction, insight or examples that you can provide to help me on my way would be most appreciated.

Dan

Share this post


Link to post
Share on other sites

I am more than eager to learn, but I am not quite sure where to start. I will dig into the LUA script examples that are included with FSUIPC to see what I can glean from there.

I don't think there's anything in Lua very usefully related to this. I've used the methods I described in C programs, not Lua -- all the hardware I've ever programmed were programmed long before I had even heard of Lua. But you can still do it in Lua, there's no difference from any other programming. What is it you don't understand?

Don't assign the dial "button" returns in FSUIPC. Instead use the event.gfd function to get your function called when something changes on the device, then gfd.GetValues and gfd.Dial to read the dial to see if that changed. Use the change to update a value you are reading for the radio (event.offset for the radio offset) and send that back to FS ipc.writeUW to the same offset) and also send it to the GF display (gfd.setdisplay), as you are doing now. Also read the time (ipc.elapsedtime) and store that in a variable which you can check in the event.offset function for the radio -- simply do not update the display if the time now is withing N milliseconds of the last write by a dial change. The value for 'N' will bed to be determined by experiment, but something in the order of 300 - 700 is normal. You want to be reasonably sure that either the user has stopped turning the dial, or at least has definitely hesitated.

Regards

Pete

Share this post


Link to post
Share on other sites

Pete,

Thank you for your direction!!!!

Below is what I have come up with and it is functioning more to my liking. Just like you said, using the event.gfd made a HUGE difference.

However, I am certain that I did not properly implement ipc.elapsedtime because my milliseconds value (0.5) is nowhere near what you said it would be (300-700). If you could give me some further direction concerning this, I would appreciate it.

Also, while I could get a value (1) identifying the inner rotary using gfd.GetValues and gfd.Dial, I could not get any value at all so as to identify (and utilize) the outer rotary. When I have a little more time, I intend to experiment with event.button to see if I can identify and utilize the outer rotary that way. Any insight you might provide would be most appreciated.

Again, thank you for your coaching. I have learned a lot in the last couple of days and I appreciate it so much!

(Concerning the multiple ipc.control() commands...the way it displays on my GF-166 is more to my liking than with a single ipc.control() command.)


-- launched from ipc.runlua
time1 = ipc.elapsedtime()
function AltDisp(offset, value)
gfd.SetDisplay(GF166, 1, 0, string.format("%2.2f ",(value/16)*0.0295302))
end
function AltRotary(model, unit)
gfd.GetValues(GF166,1)
Dial1 = gfd.Dial(1)
if Dial1 == -1 then
time2 = ipc.elapsedtime()
if (time2 - time1) < 0.5 then
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
ipc.control(65884)
else
ipc.control(65884)
end
time1 = ipc.elapsedtime()
end
if Dial1 == 1 then
time2 = ipc.elapsedtime()
if (time2 - time1) < 0.5 then
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
ipc.control(65883)
else
ipc.control(65883)
end
time1 = ipc.elapsedtime()
end
end
event.gfd("GF166",1,"AltRotary")
event.offset("0330", "UW", "AltDisp")
[/CODE]

Share this post


Link to post
Share on other sites

However, I am certain that I did not properly implement ipc.elapsedtime because my milliseconds value (0.5) is nowhere near what you said it would be (300-700). If you could give me some further direction concerning this, I would appreciate it.

I'm afraid your code bears little resemblance to anything I have suggested.

To start with, since the return from ipc.elapsedtime() is always an integer, a number of milliseconds, the lines like this

if (time2 - time1) < 0.5 then[/CODE]

will only be true if time2 actually equals time1, which is hardly ever likely to be true, or nearly always true. I can't tell. Your code might actually be equivalent to:

[CODE]
function AltDisp(offset, value)
gfd.SetDisplay(GF166, 1, 0, string.format("%2.2f ",(value/16)*0.0295302))
end

function AltRotary(model, unit)
gfd.GetValues(GF166,1)
Dial1 = gfd.Dial(1)
if Dial1 == -1 then
ipc.control(65884)
end
if Dial1 == 1 then
ipc.control(65883)
end
end

event.gfd("GF166",1,"AltRotary")
event.offset("0330", "UW", "AltDisp")[/CODE]

If you are happy with the results you are getting you might as well simplify it like that. Either way you might as well strip out the timers and elapsedtime calls and either include your many incs and decs or only one as you wish.

You seemed to have missed the points I was making entirely. Recall what i said. Here, I break it down a bit:

[b]"Don't assign the dial "button" returns in FSUIPC. Instead use the [b]event.gfd[/b] function to get your function called when something changes on the device, then [b]gfd.GetValues[/b] and [b]gfd.Dial[/b] to read the dial to see if that changed."[/b]

Okay, you've done that well.

[b]"Use the change to update a value you are reading for the radio ([b]event.offset[/b] for the radio offset) and send that back to FS [b]ipc.writeUW[/b] to the same offset) and also send it to the GF display ([b]gfd.setdisplay[/b]), as you are doing now."[/b]

You aren't doing any of that. You are simply sending a single INC or DEC to FS and letting it change the radio value, not you. The method I'm talking about requires your code to maintain the radio value, work the increments and decrements yourself, and update the display AND the FS offset, yourself. You are not doing any of that.

[b]"Also read the time ([b]ipc.elapsedtime)[/b] and store that in a variable which you can check in the event.offset function for the radio -- simply do not update the display if the time now is withing N milliseconds of the last write by a dial change."[/b]

Instead of this you are setting time2 on entry to your dial change detection and setting time1 at the end. What do you think the difference in those times is supposed to indicate? At best it tells you how fast your PC is at executing the intervening lines.

The point of having times at all was to stop your other routine, the one setting the display, from updating the display at all when you, the user, are supposedly updating it directly on the dial changes -- which you are not. You aren't even testing the time in the display routine!

I'm thinking this is far too complicated for you. Is that right?

Also, while I could get a value (1) identifying the inner rotary using [b]gfd.GetValues[/b] and [b]gfd.Dial[/b], I could not get any value at all so as to identify (and utilize) the outer rotary.

You are using gfd.Dial(1) at present. Why '1'? Have you tried other numbers? The logical first one would be 0, as in gfd.Dial(0), of course. Surely if there's a 1 there must have been a 0 as they are numbered 0-7 as documented.

(Concerning the multiple [b]ipc.control()[/b] commands...the way it displays on my GF-166 is more to my liking than with a single [b]ipc.control()[/b] command.)

I really doubt they are being executed. Or, possibly, they are always being executed. I'm not sure if the two times are always the same or always different, but it could be a near random chance.

Pete

Share this post


Link to post
Share on other sites

Hi everyone. I'm looking for some help with rotary encoders and I'm happy to pay.

Here's my current situation:

* I am using a Leo Bodnar BU0386X Joystick controller (with the rotary encoder plug in);

* I have a registered copy of FSUIPC;

* I'm running a commercial version of Prepar3D.

I have developed a multi-function display for an EHSI that has two rotary encoders installed. The one of the left is the course selector knob which is set to the VOR1 OBI Inc / Dec variables. The one on the right is the Heading Select Knob and is set to the Heading Bug Inc / Dec variables.

EHSI.PNG

When you click (rotate) the rotary encoder once, it will move the Heading Bug (for example) one increment / one degree. This is extremely frustrating for the user who might want to rotate through 180 degrees as it takes forever.

I need to make it such that when the rotary encoder is turned faster, the Heading Bug (for example) moves quicker.

I notice in FSUIPC, there's a variable to do these rotations at 10 degree increments and can see from the forums that I can create a plugin / driver to swap between the variables depending on how fast the knob is being rotated by using the virtual buttons / virtual joystick.

I also see that (from this forum) many other people have had the same problem and share my frustrations.

I've looked right through the forums and even tried a few things but since I have zero programming knowledge, all my attempts have been futile and I know that it's time to call the experts in.

So here's what I need:

I just need someone that really knows what they're talking about (and has actually done this in the past) to do this for me from start to finish. Ie, they will need to write the program and give me simple, step-by-step instructions on how to install. Given my lack of ability to program, what I'm able to offer is going to be limited. Ie, I can get your files and install them etc. but I can't do any of the programming.

As mentioned, I'm happy to pay the right person to do this job for me but it has to be from start to finish! (Sorry to badger this point but I can't be dealing with anyone saying "have you tried this or have you tried that".... I just need someone to do this as a paid job for me.)

Thanks and I hope to hear from anyone that can do this for me soon.

Kind regards, Chris

Share this post


Link to post
Share on other sites

So here's what I need:

I just need someone that really knows what they're talking about (and has actually done this in the past) to do this for me from start to finish. Ie, they will need to write the program and give me simple, step-by-step instructions on how to install. Given my lack of ability to program, what I'm able to offer is going to be limited. Ie, I can get your files and install them etc. but I can't do any of the programming.

As mentioned, I'm happy to pay the right person to do this job for me but it has to be from start to finish! (Sorry to badger this point but I can't be dealing with anyone saying "have you tried this or have you tried that".... I just need someone to do this as a paid job for me.)

Thanks and I hope to hear from anyone that can do this for me soon.

Kind regards, Chris

I did something like this a while ago with Leo's card and 5 rotary encoders for my MCP. If you read this post here:

I will tell you however that most encoders only have 16 de-tents per revolution. This is not nearly enough for what you want.

In the end I went back to my Phidgets setup.

Personally I don't think you will get want you want with Leos card. You need to use a more efficient setup that writes directly to the fsuipc offsets.

Share this post


Link to post
Share on other sites

I've looked right through the forums and even tried a few things but since I have zero programming knowledge, all my attempts have been futile and I know that it's time to call the experts in.

There's already a few Lua plug-in solutions for this which work reasonably well. They use accelerated increment/decrement controls when the rotary is turned faster. Take a look at these threads:

http://forum.simflight.com/topic/70537-rotarieslua-with-leo-bodnars-card/page__hl__rotaries.lua

http://forum.simflight.com/topic/68260-rotary-encoder-input-speed/page__p__426533__hl__rotaries.lua#entry426533

These are just two of the more useful ones I think, found by a quick search. There are also threads on this subject over in http://www.mycockpit.org/forums/.

Regards

Pete

Share this post


Link to post
Share on other sites

Hi Alaxus

Thanks for the advice. However, I'm afraid it's still well beyond me. What I really need is for someone to do this for me as a paid job. Are you interested? Also, if you think the Leo card is not the most efficient way of doing it, do you have any recommendations as to other options? I'm happy to consider using a whole different card and driver if necessary to achieve the goal.

Thanks again, Chris

Share this post


Link to post
Share on other sites

Hi Alaxus

Thanks for the advice. However, I'm afraid it's still well beyond me. What I really need is for someone to do this for me as a paid job. Are you interested? Also, if you think the Leo card is not the most efficient way of doing it, do you have any recommendations as to other options? I'm happy to consider using a whole different card and driver if necessary to achieve the goal.

Thanks again, Chris

Currently I am using 5 of these in my MCP

http://www.phidgets.com/products.php?category=7&product_id=1052_0

with this software: fs2phidgets

http://www.mycockpit.org/forums/downloads.php?do=cat&id=20

Its pretty straight forward.

The other one you can look at is the goflight module:

http://www.goflightinc.com/collections/modules/products/gf-rp48-push-button-rotary

Again pretty straight forward.

Have a look in to those first as I think it will work better for your situation.

Share this post


Link to post
Share on other sites

Pete (or anyone would might be able to help),

 

I've used this lua to get two rotary controllers up and working perfectly.  However, when I go to add a third rotary the alternate joystick (64) never shows up.

 

For instance, I have the following entry:

Rotaries = {6,7,2,3,0,1}  

Only 6,7,2,3 work, not 0,1.  I've tried it in a different order and the same happens, the last pair doesn't work.  I've also tried a number of different rotary controllers that are attached the same BU0836X board, but it doesn't matter which I use only the first two show up.  Any help you can give would be appreciated. 

 

Bill

Share this post


Link to post
Share on other sites

Pete (or anyone would might be able to help),

 

I've used this lua to get two rotary controllers up and working perfectly.  However, when I go to add a third rotary the alternate joystick (64) never shows up.

 

For instance, I have the following entry:

Rotaries = {6,7,2,3,0,1}  

Only 6,7,2,3 work, not 0,1.  I've tried it in a different order and the same happens, the last pair doesn't work.  I've also tried a number of different rotary controllers that are attached the same BU0836X board, but it doesn't matter which I use only the first two show up.  Any help you can give would be appreciated.

 

Sorry, what Lua are we talking about here? Do you mean the one supplied as an example in the Lua package installed with FSUIPC? Or do I have to search back in this rather long (and very old) thread you've resurrected and appended to?

 

And how are you testing to see that the last two (one rotary) doesn't work?  If its my exmple rotary code than please note that there is an error in line 69:

 

               ipc.togglebitsUB(offset, thisbutton)

 

should be

 

               ipc.togglebitsUD(offset, thisbutton)

 

UB = Unsigned Byte (8 bits = 2 rotaries)

UD = Unsigned Dword (32 bits = 8 rotaries)

 

Odd this hasn't been discovered before!

 

Pete

Share this post


Link to post
Share on other sites

Pete,

 

Sorry for resurrecting such an old thread.  Upon a search, this lua was exactly what I was looking for so I went with it.  I'm pretty new to this, so I read the entire thing and got it up and running.  I'm happy to say that the code fix you supplied above (UB to UD) fixed my problem.  I used the lua from post #25 in this thread.  You might want to go back and edit that post so no one else runs into this problem. 

 

Thanks for your help (and quick reply!)

 

Bill

Share this post


Link to post
Share on other sites

Pete,

 

Sorry for resurrecting such an old thread.  Upon a search, this lua was exactly what I was looking for so I went with it.  I'm pretty new to this, so I read the entire thing and got it up and running.  I'm happy to say that the code fix you supplied above (UB to UD) fixed my problem.  I used the lua from post #25 in this thread.  You might want to go back and edit that post so no one else runs into this problem. 

 

Thanks for your help (and quick reply!)

 

Bill

 

 

I've corrected the original, which is the one in the Lua package downloadable from the Download Links subforum and also which will be installed into your FSUIPC Documents folder. If there are pasted copies in threads I'm not going to find them all in any case -- I would expect folks to use the ones installed.

 

Thanks,

Pete

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.