Jump to content
The simFlight Network Forums
dazz

Script to filter throttle spikes

Recommended Posts

Hi everyone. I'm working in a script to filter my TQ spikes. It looks like this so far:

while (true) do
	new1 = ipc.get("old1")
	new2 = ipc.get("old2")
	new3 = ipc.readSW(0x66C0)

	if new1 == nil then new1 = 0 end
	if new2 == nil then new2 = 0 end
	if new3 == nil then new3 = 0 end

	ipc.log("new1 = " .. new1)
	ipc.log("new2 = " .. new2)
	ipc.log("new3 = " .. new3)
	ipc.log("-----------------------")

	ipc.set("old1", new2)
	ipc.set("old2", new3)

	nextV = new3

	if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then
		nextV = new2
	end

	if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then
		nextV = new1
	end

	nextV = nextV * -1

	ipc.control(66504, nextV)
	ipc.log("nextV = " .. nextV)
	ipc.log("***********************")

	ipc.sleep(50)
end

It's of course in it's infancy yet. Couple questions please.

I want to expand it to filter all 4 throttle axis independantly, and a stack would come in handy.

1.- Any suggestions on a stack implementation for Lua? Don't even need it to take care of concurrency, as I will only have one writer

2.- Can I store the stacks in the global just like ipc.set does or do I need to build the stacks for each iteration? If I can't I might as well forget about using "complex" data structures and keep it simple instead

3.- Also considering assigning the axis to a Lua pluggin that will update a global variable via ipc.set instead of using the 0x66C0 offset. What is the best approach performance wise? I take it when I assign my throttle axis to the 0x66C0 offset, FSUIPC is also running a thread to update the value the same way the Lua plugin would. Is that correct?

...more questions to come

Thanks in advance

Share this post


Link to post
Share on other sites

Hi everyone. I'm working in a script to filter my TQ spikes. It looks like this so far:

Have you considered making it event driven rather than running a never ending loop? It would also then not need to use global variables as the plug-in would be always there and running on demand.

I want to expand it to filter all 4 throttle axis independantly, and a stack would come in handy.

Why a stack? Tables are very easy in Lua. You could use a table in stack fashion of course.

I take it when I assign my throttle axis to the 0x66C0 offset, FSUIPC is also running a thread to update the value the same way the Lua plugin would. Is that correct?

It's scanning axes the same way no matter what you assign them to. If an axis is assigned to send a control to FS, it sends the control to FS. If it is assigned to update an offset, it updates an offset. Whether any of that is done in the main thread or an axis scanning thread isn't really relevant to anything.

Regards

Pete

Share this post


Link to post
Share on other sites

Thanks Pete

Have you considered making it event driven rather than running a never ending loop? It would also then not need to use global variables as the plug-in would be always there and running on demand.

Yes, I have also considered intercepting the axis, but the idea is to pick the last n axis readings, discard the max and min value and apply the average of the rest. In an event driven approach I would be discarding the last reading even if it's a valid value.

With the loop, the next iteration would ensure the proper value is applied.

I will try different implementations including event driven, but for now that's what I'm trying to do

Why a stack? Tables are very easy in Lua. You could use a table in stack fashion of course.

A stack seems to fit my needs just perfectly with this approach since I can keep the last n relevant values updated naturally. I can see that Lua has a native implementation of a stack, but a table would do too.

So, is there a way to store a complex structure like a stack or a table in the global space like ipc.set does please?, or maybe ipc.set works with any kind of data structure? I can always try that before asking hehe

Share this post


Link to post
Share on other sites

Yes, I have also considered intercepting the axis, but the idea is to pick the last n axis readings, discard the max and min value and apply the average of the rest. In an event driven approach I would be discarding the last reading even if it's a valid value.

I was thinking more of an even like on the offset you are changing or possibly a timer event so you can sample as you do now.

A stack seems to fit my needs just perfectly with this approach since I can keep the last n relevant values updated naturally. I can see that Lua has a native implementation of a stack, but a table would do too.

Ah, you've perhaps read more than me. I've read most of the Lua manual once, but forgot most of it too! ;-0

So, is there a way to store a complex structure like a stack or a table in the global space like ipc.set does please?, or maybe ipc.set works with any kind of data structure? I can always try that before asking hehe

No, it only works with strings and numbers. Sorry. Maybe another reason to use events? You can do the same as what you've got but with a 50 mSec timer even instead of a 50msec sleep in a loop. Then keep all of your variables in-thread.

Regards

Pete

Share this post


Link to post
Share on other sites

I was thinking more of an even like on the offset you are changing or possibly a timer event so you can sample as you do now.

Ah, you've perhaps read more than me. I've read most of the Lua manual once, but forgot most of it too! ;-0

No, it only works with strings and numbers. Sorry. Maybe another reason to use events? You can do the same as what you've got but with a 50 mSec timer even instead of a 50msec sleep in a loop. Then keep all of your variables in-thread.

Regards

Pete

Might as well keep it simple with just 3 readings and avoid the need of building a stack or a table, and also calculating the average. I'm testing with 3 readings and it works great already

Ok, the timer event sound like a much more elegant solution, thanks for the suggestion. Do I need to worry about thread overlapping if the event is triggered when the previous one has not finished jet?

Share this post


Link to post
Share on other sites

Might as well keep it simple with just 3 readings and avoid the need of building a stack or a table, and also calculating the average. I'm testing with 3 readings and it works great already

Ok, the timer event sound like a much more elegant solution, thanks for the suggestion. Do I need to worry about thread overlapping if the event is triggered when the previous one has not finished jet?

No. The event only executes when you exit. The timer just sets a flag. So, no matter how many timer events occur, you only get entered once if they all pile up because you take a while executing.

Regards

Pete

Share this post


Link to post
Share on other sites

No. The event only executes when you exit. The timer just sets a flag. So, no matter how many timer events occur, you only get entered once if they all pile up because you take a while executing.

Regards

Pete

Ok, then I guess I'll have to be careful not to overflow the call stack, but it's definitely a nice approach. Thanks again Pete

Share this post


Link to post
Share on other sites

Ok, it's working pretty well already, but I'd like to improve a couple of aspects.

1.- This is really no big deal, and guess there's nothing that can be done about it, but, is there a way to increase the rate at which the axis are polled? as it stands now I get readings slower than I'd like and it makes the throttles a bit jerky, and add some lag

2.- I'm using the 0x66C0 and 0x66D0 offsets at the moment, but I'd like to avoid that just in case someone is using them already, but can't think of a way to do this. Is there a way to pass a parameter to a Lua pluggin so that I assign the throttle axis to it and the pluggin updates a global variable with the new value of the axis?

There's probably a better way to do this, so any suggestions are welcome

Share this post


Link to post
Share on other sites

1.- This is really no big deal, and guess there's nothing that can be done about it, but, is there a way to increase the rate at which the axis are polled? as it stands now I get readings slower than I'd like and it makes the throttles a bit jerky, and add some lag

The default is 50 times a second, which is a *lot* faster than the FS default. It is controlled by the PollInterval value in the main [buttons] section of the INI file. You could speed it up, but if it's too fast I doubt that the Lua could execute fast enough to catch every value received.

Are you sure that what you observe isn't a result of the 'delta' value which prevents values which are only slightly different being supplied?

You also need to make the Lua program as compact as possible -- each statement is executed with a thread yield between, so the fewer executed the faster it executes as it yields less to other threads. Of course that means other threads (like FS) get less time ...

2.- I'm using the 0x66C0 and 0x66D0 offsets at the moment, but I'd like to avoid that just in case someone is using them already, but can't think of a way to do this. Is there a way to pass a parameter to a Lua pluggin so that I assign the throttle axis to it and the pluggin updates a global variable with the new value of the axis?

When you assign an Axis directly to a Lua program execution the Lua program gets the axis value in ipcPARAM. However, that's not really what you want in this case as you should be using events. I could look at providing an assignable control to set ipcPARAM to a given value (the axis in this case) for a specified Lua plugin, a bit like the LuaSet for Lua flags (LuaValue", perhaps).

There's probably a better way to do this, so any suggestions are welcome

You could try assigning to the normal axes as usual, but then disconnecting them from FS via offset 310A. you can then read the post-calibration values which WOULD have been sent to FS in offsets 3328 ff., and write the resluts of your computations to the relevant FS-actioning offsets. this is how fly-by-wire can be done, which is a similar control-manipulation process.

Regards

Pete

Share this post


Link to post
Share on other sites

Yeah, I love the 310A thing. I'll do that.

Now time to re-read the guide again before I ask any more unnecessary questions, should have noticed the PollInterval is described there, so sorry about that.

I'll double check my delta value too

I could look at providing an assignable control to set ipcPARAM to a given value (the axis in this case) for a specified Lua plugin, a bit like the LuaSet for Lua flags (LuaValue", perhaps).

That would be awesome, if it's something that won't take too long it would be a nice addition

Thanks Pete

Share this post


Link to post
Share on other sites

Hi everyone. I'm working in a script to filter my TQ spikes. It looks like this so far:

Hi Dario,

I would love to try this! I had my TQ replaced but I still get a bit of noise on the throttles, I hate it when they go to 100% when taxing! annoying. Can you post the final version or send it to jaltuve@gmail.com?

Gracias!

Share this post


Link to post
Share on other sites

Hi Dario,

I would love to try this! I had my TQ replaced but I still get a bit of noise on the throttles, I hate it when they go to 100% when taxing! annoying. Can you post the final version or send it to jaltuve@gmail.com?

Gracias!

Hola Jesús! :)

This is what I got so far:

Throttle_1:

ipc.set("old11", -16384)
ipc.set("old12", -16384)
ipc.writeSW(0x66C0, -16384)

while (true) do
	new1 = ipc.get("old11")
	new2 = ipc.get("old12")
	new3 = ipc.readSW(0x66C0)

	ipc.set("old11", new2)
	ipc.set("old12", new3)

	nextV = new3

	if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then	nextV = new2 end

	if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then	nextV = new1 end

	nextV = (nextV / 2) + 8192

	ipc.control(66420, nextV)

	ipc.sleep(30)
end

Throttle_2:

ipc.set("old21", -16384)
ipc.set("old22", -16384)
ipc.writeSW(0x66D0, -16384)

while (true) do
	new1 = ipc.get("old21")
	new2 = ipc.get("old22")
	new3 = ipc.readSW(0x66D0)

	ipc.set("old21", new2)
	ipc.set("old22", new3)

	nextV = new3

	if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then	nextV = new2 end

	if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then	nextV = new1 end

	nextV = (nextV / 2) + 8192

	ipc.control(66423, nextV)

	ipc.sleep(30)
end

You'll need to assign your throttles 1 & 2 to offsets 0x66C0 and 0x66D0 via Offset Dword Set and start the Lua pluggins in the Auto section of your 767, as you most than likely know already, but just in case someone else feels like giving it a try.

Truth be told, my spiking is not that bad, so if you need a more agressive filtering let me know

Share this post


Link to post
Share on other sites

Next version, using the throttle disconnect offset. Now axes should be normally assigned to throttle 1 & 2 in FSUIPC:

Throttle 1:

ipc.set("old11", -16384)
ipc.set("old12", -16384)

while (true) do	
	ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 64))
	new1 = ipc.get("old11")
	new2 = ipc.get("old12")
	new3 = ipc.readSW(0x3330)

	ipc.set("old11", new2)
	ipc.set("old12", new3)

	nextV = new3

	if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then	nextV = new2 end

	if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then	nextV = new1 end

	nextV = (nextV / 2) + 8192

	ipc.writeSW(0x088C, nextV)

	ipc.sleep(50)
end

Throttle 2

ipc.set("old21", -16384)
ipc.set("old22", -16384)

while (true) do
	ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 128))
	new1 = ipc.get("old21")
	new2 = ipc.get("old22")
	new3 = ipc.readSW(0x3332)

	ipc.set("old21", new2)
	ipc.set("old22", new3)

	nextV = new3

	if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then	nextV = new2 end

	if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then	nextV = new1 end

	nextV = (nextV / 2) + 8192

	ipc.writeSW(0x0924, nextV)

	ipc.sleep(50)
end

There's something wrong with this, because it tends to crash the sim very often. It happened also with the previous version, so time to try the event triggered approach

Also, post-calibration readings don't seem to be actually calibrated, so I need to do that crappy adjustment to the axis value:

nextV = (nextV / 2) + 8192

Share this post


Link to post
Share on other sites

There's something wrong with this, because it tends to crash the sim very often. It happened also with the previous version

1. i'd like to know more about that. I don't see anything there which should crash the sim, though the furious use of Globals (which are stored in a separate Lua thread) is, to put in mildly, very unusual and may be exposing a weakness somewhere in the Lua memory management.

2. Since they both run 'forever', why are you using ipc.set and ipc.get to store global copies anyway? There's no need at all. You could just use variables local to that Lua plug-in. It seems to add unnecessary complexity, and will slow it down somewhat.

3. Why two separate plug-ins? Even without tables or stacks you could put all that into one loop, or probably one loop and one local function, called twice each loop, once for each throttle.

4. Reading and writing offset 310A 40 times a second (20 times each, twice) seems a bit over the top when it only needs refreshing once every few seconds. An ideal candidate for a separate time-event called function.

Also, post-calibration readings don't seem to be actually calibrated

Really? No calibration? So changing thingfs in the calibration tab in FSUIPC makes no difference to the values? Ouch! Can you shown me your FSUIPC INI file please? The values stored should most certainly be post-calibration. There are quite a few applications which depend on that.

Maybe you have the NRZ option selected? Folks with Saitek quadrants seem to use that a lot. Maybe that gets you a forward thrust value going from -ve min to +ive max rather than 0 to +ve max ... if so I'll need to fix that. The NRZ option was added much later and this may be an oversight.

However, they should still be calibrated, just to the -16k to +16k range used by FS Axis Throttle Set controls for forward thrust, not the 0 - 16k use by the older ThrottleN Set controls for forward thrust.

How did you arrive at (nextV / 2) + 8192? That sounds like the input values you see are -16k to +16k, not 0 to 16k, right? What makes them look uncalibrated?

Regards

Pete

Share this post


Link to post
Share on other sites

1. How are you starting these programs running? via ipcReady.lua? You shouldn't have them assigned to anything, except possibly a button or keypress you use once ot start them if not via ipcReady.

For now I'm using a keypress, for debugging purposes

2. Since they run forever, why are you using ipc.set and ipc.get to store global copies?.

Thanks for making me look as the idiot I am hahaha (ok, I don't need help with that). Yeah, I totally screwed up there :)

Really? Can you shown me your FSUIPC INI file please? The values stored should most certainly be post-calibration. There are quite a few applications which depend on that.

Maybe you have the NRZ option selected? Folks with Saitek quadrants seem to use that a lot. Maybe that gets you a forward thrust value going from -ve min to +ive max rather than 0 to +ve max ... if so I'll need to fix that. The NRZ option was added much later and this may be an oversight.

Regards

Pete

I'm not using UseAxisControlsForNRZ. Actually I didn't even have the axes set in the calibration section *blush*, so no wonder the post-calibration offsets' output are not calibrated. I've tested so many configs that I mistakenly thought I had them calibrated via FSUIPC. Again, sorry about that

Yes, the axes work like that ( -16K to +16K), and yes, it's an effin saitek TQ. Best advise would be to stay away from saitek stuff actually

Share this post


Link to post
Share on other sites

3. Why two separate plug-ins? Even without tables or stacks you could put all that into one loop, or probably one loop and one local function, called twice each loop, once for each throttle.

tried that, but the levers move out of sync

4. Reading and writing offset 310A 40 times a second (20 times each, twice) seems a bit over the top when it only needs refreshing once every few seconds. An ideal candidate for a separate time-event called function.

Yes, that's one of the things I had left to try. An independant thread that will do that every 8-9 seconds. Silly question, but just in case. ipc.sleep puts the thread to sleep and it's not an active wait right? or would it be better to use a timer triggered event fot this?

Share this post


Link to post
Share on other sites

Event triggered, same idea.

Works great with one axis. when I run the second one it crashes within seconds

ipc.set("old11", -16384)
ipc.set("old12", -16384)
ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 64))

function throttle1(off, new3)	
	new1 = ipc.get("old11")
	new2 = ipc.get("old12")

	nextV = new3

	if not (new2 > new3 and new2 > new1) and not (new2 < new3 and new2 < new1) then	nextV = new2 end

	if not (new1 > new3 and new1 > new2) and not (new1 < new3 and new1 < new2) then	nextV = new1 end

	ipc.set("old11", new2)
	ipc.set("old12", new3)

	nextV = (nextV / 2) + 8192

	ipc.writeSW(0x088C, nextV)
end

event.offset(0x3330, "SW", "throttle1")

is there something that explains the crashes?

Share this post


Link to post
Share on other sites

tried that, but the levers move out of sync

Really? Even though you are writing them both at the same time?

ipc.sleep puts the thread to sleep and it's not an active wait right?

Yes. Your thread will get no time at all until the sleep period expires. It would be daft to put your thread to sleep for 8 seconds -- how will it update the throttle values?

... or would it be better to use a timer triggered event fot this?

For everything, yes, as I keep advising. All three of your activitiies can be in one Lua driven by a couple of timer events -- one at 50 mSecs for the two throttles and the other at 8 secs for 310A.

regards

Pete

Share this post


Link to post
Share on other sites
Really? Even though you are writing them both at the same time?<br>
<br>It's much smoother with two separate pluggins. Guess it has to do with the yield in between statements<br>
It  would be daft to put your thread to sleep for 8 seconds -- how will it update the throttle values?<br>
<br>I was obviously talking about the thread to reset the bits for throttle disconnects, not the one to intercept the throttles<br>
All three of your activitiies can be in one Lua driven by a  couple of timer events -- one at 50 mSecs for the two throttles and the  other at 8 secs for 310A.<br>
<br>There doesn't seem to be a built-in timer implementation in Lua, nor can I find any info about timers in the documentation or the examples provided. What do you use for a timer please?<br><br>By the way, I keep getting FSUIPC.dll crashes no matter what.<br> <br>On a side note, the script work ok with spikes, but it doesn't help much with noise induced by other levers, and I'm not sure there's nothing a reasonably simple script can do about it

Share this post


Link to post
Share on other sites

There doesn't seem to be a built-in timer implementation in Lua, nor can I find any info about timers in the documentation or the examples provided. What do you use for a timer please?

The event.timer function, as added in a recent version. Please check the Download Links subforum. I think you must be referring to out of date documentation for the FSUIPC Lua libraries.

By the way, I keep getting FSUIPC.dll crashes no matter what.

I tried your own Lua programs and even shortened the "sleep" down to 10 mSecs, and it took me 15 minutes of almost constant throttle movement before I could get even one crash, which I am pretty sure was some sort of Lua memory management problem, where it had run out of memory and was tidying up. I'm afraid the core Lua code is not mine and I cannot fix that.

The problem is arising anyway because of the wrong use of the global "set" and "get" functions. The inter-thread operations are not at all suited to hight intensity use.

You offer no information for me to assist in diagnosing your "FSUIPC.DLL crashes" in any case, so I really don't know what you expect me to do. Sorry.

On a side note, the script work ok with spikes, but it doesn't help much with noise induced by other levers, and I'm not sure there's nothing a reasonably simple script can do about it

Well, i don't know much about filters, but yours seems less capable, according to my testing, than the built-in Fliter facilities in FSUIPC's calibration pages. Why did you not use those?

Regards

Pete

Share this post


Link to post
Share on other sites

The event.timer function, as added in a recent version. Please check the Download Links subforum. I think you must be referring to out of date documentation for the FSUIPC Lua libraries.

Ok, I did it again. Should have thought of that. Thanks

I tried your own Lua programs and even shortened the "sleep" down to 10 mSecs, and it took me 15 minutes of almost constant throttle movement before I could get even one crash, which I am pretty sure was some sort of Lua memory management problem, where it had run out of memory and was tidying up. I'm afraid the core Lua code is not mine and I cannot fix that.

The problem is arising anyway because of the wrong use of the global "set" and "get" functions. The inter-thread operations are not at all suited to hight intensity use.

You offer no information for me to assist in diagnosing your "FSUIPC.DLL crashes" in any case, so I really don't know what you expect me to do. Sorry.

I have a timer based version ready to test, using local variables so hope that puts an end to the crashes. I'll get back to you with more relevant info if it keeps happenning, but I'm pretty sure everything will be ok

Well, i don't know much about filters, but yours seems less capable, according to my testing, than the built-in Fliter facilities in FSUIPC's calibration pages. Why did you not use those?

I can't seem to get these Saitek axes working properly via FSUIPC calibration due to the -16K ~ 16K range thing, so I can't use the built in filter.

What I could do is to use the calibration to filter the axes, and then intercept the post calibration offset to apply the (nextV / 2) + 8192

correction

EDIT: ok, I just needed to check the "No Reverse Zone" option. Damn it, this is embarrasing :)

Edited by dazz

Share this post


Link to post
Share on other sites

I have a timer based version ready to test, using local variables so hope that puts an end to the crashes. I'll get back to you with more relevant info if it keeps happenning, but I'm pretty sure everything will be ok

There's one other thing. I think you should only be setting the throttle when it needs changing. Continually writing the same value, whether to the Throttle offset or via ipc.control will both result in lots of unnecessary messages flying about through the Windows message queue. With a complex aircraft that's the last thing you want to do -- there's usually far too many already!

Just keep a copy of the last value sent and only send the next when it is different. That'll remove most of the unnecessary stuff going on.

I've also just completed changes to provide the direct method of setting ipcPARAM that I hinted at. Basically then all you need to do is assign the axis to "LuaValue xxxx" where xxxx is the name of your ready-running Lua plugin for that throttle, and you can do it all from ipcPARAM. There's also an event.param so it can be properly event driven without bothering with timer adjustments (unless you want to add more sophistication for filtering only fast changes, not slow ones.

Here's your Throttle 1 Lua re-written using the new facilities:

new1 = -16384
new2 = -16384
prevV = -16384

function param(new3)

    	nextV = new3

    	if not (new2 &gt; new3 and new2 &gt; new1) and not (new2 &lt; new3 and new2 &lt; new1) then nextV = new2 end
    	if not (new1 &gt; new3 and new1 &gt; new2) and not (new1 &lt; new3 and new1 &lt; new2) then nextV = new1 end

    	new1 = new2
    	new2 = new3

    	if nextV ~= prevV then
   		ipc.control(66420, nextV)
   		prevV = nextV
    	end
end

event.param("param")

You can still calibrate, and set NRZ if you wish, as this sends the Axis Throttle1 Set control just like FS would. Note that "PrevV" is used to stop it sending non-changing values, though in fact this is less necessary because the event.param function will not call the operating function ("param") if ipcPARAM doesn't change. The function doesn't even need to read ipcPARAM because its value is supplied as the parameter to the function.

The versions of FSUIPC3 and FSUIPC4 with these facilities should be ready for release tomorrow (Wednesday), or the day after at the latest, I hope. It will also contain new Lua functions:

ipc.togglebitsUB, ipc.togglebitsUW, ipc.togglebitsUD

ipc.setbitsUB, ipc.setbitsUW, ipc.setbitsUD

ipc.clearbitsUB, ipc.clearbitsUW, ipc.clearbitsUD

Those will also feature in a revised WideClient.

Regards

Pete

Share this post


Link to post
Share on other sites

I just added the prevV check and the code looks like this now. I know I could encapsulate things in functions, but it's a bit more compact like this... that and because I'm a lazy bum :P

Runs flawlessly, no crashes at all, even though there's no reason left for this anymore but I'll hang on just for the fun of it, and it will help with future scripts

ipc.set("old11", -16384)
ipc.set("old12", -16384)
ipc.set("prev1V", -16384)
...

function throttle1(off, new3)	
	new1 = ipc.get("old11")
	new2 = ipc.get("old12")

	nextV = new3

	if not (new2 &gt; new3 and new2 &gt; new1) and not (new2 &lt; new3 and new2 &lt; new1) then	nextV = new2 end
	if not (new1 &gt; new3 and new1 &gt; new2) and not (new1 &lt; new3 and new1 &lt; new2) then	nextV = new1 end

	new1 = new2
	new2 = new3
	new3 = ipc.readSW(0x3330)

	ipc.set("old11", new2)
	ipc.set("old12", new3)

	nextV = new3

	if not (new2 &gt; new3 and new2 &gt; new1) and not (new2 &lt; new3 and new2 &lt; new1) then	nextV = new2 end
	if not (new1 &gt; new3 and new1 &gt; new2) and not (new1 &lt; new3 and new1 &lt; new2) then	nextV = new1 end

	if nextV ~= prev1V then
			--ipc.control(66420, nextV)
			ipc.writeSW(0x088C, nextV)
			prev1V = nextV
	end
end

function throttle2(off, new3)
	...
end

function resetBits()
	ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 64))
	ipc.writeUB(0x310A, logic.Or(ipc.readUB(0x310A), 128))
end

event.offset(0x3330, "SW", "throttle1")
event.offset(0x3332, "SW", "throttle2")
event.timer(5000, "resetBits")
resetBits()

There's something about the event.param solution that I'm not sure about. Is it shared globally? I mean if I have both axes writing there how do I know what offset fired the event.param?

You're also using local variables in an event driven implementation? I would have thought that every time an event triggers the action, it runs in a separate instance... time to test it myself :)

Share this post


Link to post
Share on other sites
I just added the prevV check and the code looks like this now.

You are still using globals (ipc.get and ipc.set) unnecessarily, though. That makes it a lot jerkier than it need to be, because every get and every set is a multi-threaded synching operation -- it actually has to get and put the values from/to a separate thread, every single access!

All you need to do is replace the global references by direct variable names. i.e.

old11 =  -16384
old12 =  -16384
prev1V =  -16384

etc, throughout.

There's something about the event.param solution that I'm not sure about. Is it shared globally? I mean if I have both axes writing there how do I know what offset fired the event.param?

The parameter it refers to being changed is the ipcPARAM specific to this current plug-in. It isn't a shared global accessed via get and set.

You obviously would need to have separate plug-ins for each throttle if using the "param" method. with your method you could combine the throttle actions for all throttles into one plug-in using tables. But not using ipcPARAM because you can't tell which throttle sent it.

You're also using local variables in an event driven implementation? I would have thought that every time an event triggers the action, it runs in a separate instance... time to test it myself :)

No, you are misunderstanding the whole advantage of the event methods. The fact that you've established one or more events keeps the plug-in loaded, ready-compiled and ready to run. It is merely 'sleeping', with its event functions being called as needed according to the events defined. It's truly like adding code to FSUIPC.

If, in the functions, you eventually cancel all outstanding events (via event.cancel), only then is the plug-in "unplugged".

Regards

Pete

Share this post


Link to post
Share on other sites

True, I misunderstood your first post where you clearly stated that in an event triggered solution the plug-in would be always there and running on demand

Does this mean that a single thread is serving both events the same way it would with a sleep clause? If that's the case I think it's better to run each throttle in a separate pluggin

EDIT: I put some ipc.log lines in both functions and it looks like it's actually a single thread

Is that the reason why there can only be one timer per pluggin? Is the timer function also running in the same thread? Logs seem to confirm that also

EDIT2: I simplified the code:

old2 = -16384

function throttle2(off, newV)
	nextV = ipc.readSW(0x3332)

	if not (newV &gt; nextV and newV &gt; old2) and not (newV &lt; nextV and newV &lt; old2) then nextV = newV end

	ipc.writeSW(0x0924, nextV)
	old2 = nextV
end

event.offset(0x3332, "SW", "throttle2")

In the event driven version I don't really need to check if the previous value equals the new one, since the function is called when the lever is actioned so most of the times it will be a new value. I'm not polling the axis anymore, so I can skip that and make the code simpler.

I also store the filtered value as the "old" one, so if a reading is discarded as a probable spike, it won't be used for further calculations.

This "old" or previous value is compared to the one that triggered the event (newV) and a new reading (nextV). The new reading is to make sure that the last value is not unnecessarily discarded, so in normal conditions, the last time the event is triggered (when the lever is realeased) nextV and newV will be the same.

I have another pluggin for the throttle2 and a third one for the axes disconnects. With ipcParam I'll get rid of the last one since I won't need to assign the throttles to the axes, but to the Lua pluggins instead

Edited by dazz

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

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.