Jump to content
The simFlight Network Forums

Using a trim wheel axis to operate with trim INC and DEC instead


Pete Dowson

Recommended Posts

A trim wheel, such as that sold by Saitek, is very nice, but unless it is motorised so that when the autopilot is controlling trim the wheel can be automatically moved to its correct position, it poses difficulties unless you fly under manual control all of the time.

With the autopilot operating the trim for vertical flight control modes, the wheel's position will not often match the actual trim position in FS. This doesn't matter if you don't move it, as axes are not read until moved. But as soon as you move it, the actual setting for the wheel position is immediately applied, resulting in a sudden trim change.

FSUIPC does have an option to disconnect the trim axis when the autopilot is using it (see the DisconnTrimForAP option in the Advanced User's guide), but this doesn't get over the discrepancy in the position when the A/P is disconnected. Really the only satisfactory way of having a trim wheel operate through the trim axis control is to have it motorised so that is always goes to the currently set FS position when the A/P adjusts it, or when you load a new flight.

An alternative, which can work but which does spoil some of the advantages of having a realistic trim wheel, is to revert it to sending elevator trim up and trim down commands to FS, instead of using the value directly as the trim vale. This effectively makes it similar to the NumPad 1 and 7 keys, or the spring-loaded two way toggle switches or levers fitted to many commercial yokes.

The way to do this is to use a Lua plug in which converts the change in axis value to a trim Inc or Dec. Here's an example:


function checkvalue(val)
if prev ~= nil then
if val > prev then ipc.control(65615)
elseif val < prev then ipc.control(65607)
end
end
prev = val
end

event.param("checkvalue")
[/CODE]

Save this as, say, "trimwheel.lua", in the Modules folder and add this to your INI file:

[Auto]

1=Lua trimwheel

Run FS and assign your axis, in the normal FS controls assignment on the left, to "Luavalue trimwheel".

Regards

Pete

Link to comment
Share on other sites

  • 5 years later...

This appears to be an ideal solution to using my Saitek Pro Trim Wheel, but I ran into some caveats.

1) At least with the Saitek trim wheel, I had to reverse the values in the Lua script, which is an easy fix.  I did:

function checkvalue(val)
   if prev ~= nil then
		  if val > prev then ipc.control(65607)
		  elseif val < prev then ipc.control(65615)
		  end
   end
   prev = val
end

event.param("checkvalue")

2) If I turn the trim wheel too quickly, I do not get the full range of movement in the sim trim indication.  When I move the trim wheel quickly from its' lowest to highest positions, on the sim it is only moved about half way through its' range of motion.  If I move it slowly, I can get the full range of motion.  I suspect the trim wheel is sending the nose up/nose down commands too quickly and some of the commands are being ignored.  Is there anyway to fix this?

 

3) The last issue is something that is a limitation with the Saitek Trim Wheel, and cannot be fixed FSUIPC, but I am mentioning it as it is unexpected.  The issue is that the trim wheel has limits to the values it can send nose up or down, but turning the wheel there is no indication you have reached full nose up or down, or where you are in the range.  That means, if trim wheel is physically at nose up (or down), before you start the simulator, then in the sim you cannot trim more nose up (or down).  In this case having a trim wheel that does not have physical limits would be ideal.  I wonder if the Saitek can be modified.  Internally it uses a optical rotary position sensor.  This can somewhat worked around by going into FSUIPC and seeing what the position of the trim wheel is at and setting it to roughly what sim trim position you want to start with.

I am using Prepar3d v4.1 and FSUIPC v5.121b

Jessica

Link to comment
Share on other sites

I adjusted Pete's script to solve all three of your issues:

  1. The script writes directly to offset 0x0BC0
  2. For larger movements of the wheel the script makes larger changes the offset.
  3. If the wheel is near the end of its range (upper or lower 1/16th) a warning popup will appear and suggest disconnecting and reconnecting the wheel (I have connected it to the USB hub of my Saitek yoke, so this is easily reachable)

Additionally I have configured the trim wheel to set AP vertical speed or pitch or attitude hold if the AP is enabled instead of acting as a trim wheel.

And for the times I use only a joystick instead of the full setup, I have assigned two joystick buttons to act as trim, with increasing speed if the buttons are hold for a longer time.

Maybe you can adjust it for your own needs:

-- Using a trim wheel axis to operate with trim INC and DEC instead
-- http://forum.simflight.com/topic/72492-using-a-trim-wheel-axis-to-operate-with-trim-inc-and-dec-instead/
--
-- [Auto]
-- 1=Lua trimwheel
-- assign your axis, in the normal FS controls assignment on the left, to "Luavalue trimwheel".

boundary = 16384-2048

joystick = "J" -- Saitek Aviator Stick
button_dn = 4  -- T1
button_up = 5  -- T2

function trimbutton(joynum, button, downup)
  factor = 20
  direction = (button == button_up) and -1 or 1
  trimwheel(factor*direction)
  ipc.sleep(100)
  while ipc.testbutton(joynum, button) do
    if factor < 200 then
      factor = factor+2
    end
    trimwheel(factor*direction)
    ipc.sleep(30)
  end
  trimwheel(0)
end

function trimwheel_trim(change)
  trim = ipc.readSW(0x0BC0) - change
  if trim < -16384 then
    trim = -16384
  elseif trim > 16383 then
    trim = 16383
  end
  ipc.writeSW(0x0BC0, trim)
end

function trimwheel_ap_vs(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    ipc.control(65895) -- AP_VS_VAR_DEC
  elseif change < 0 then
    ipc.control(65894) -- AP_VS_VAR_INC
  end
end

function trimwheel_ap_pitch(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    ipc.control(66584) -- AP_PITCH_REF_INC_DN
  elseif change < 0 then
    ipc.control(66583) -- AP_PITCH_REF_INC_UP
  end
end

function trimwheel_ap_pitch_atthold(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65804, 1) -- AP_ATT_HOLD_ON
    end
    ipc.control(66584) -- AP_PITCH_REF_INC_DN
  elseif change < 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65804, 1) -- AP_ATT_HOLD_ON
    end
    ipc.control(66583) -- AP_PITCH_REF_INC_UP
  end
end

function trimwheel_ap_pitch_althold(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65816, 1) -- AP_ALT_HOLD_OFF
    end
    ipc.control(66584) -- AP_PITCH_REF_INC_DN
  elseif change < 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65816, 1) -- AP_ALT_HOLD_OFF
    end
    ipc.control(66583) -- AP_PITCH_REF_INC_UP
  end
end

function trimwheel_c182(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    ipc.writeLvar("kap140_dn_button", 1)
  elseif change < 0 then
    ipc.writeLvar("kap140_up_button", 1)
  else
    ipc.writeLvar("kap140_dn_button", 0)
    ipc.writeLvar("kap140_up_button", 0)
  end
end

function aircraftchange(eventtype)
  if ipc.readSTR(0x3D00, 14) == "C337 Skymaster" then
    trimwheel = trimwheel_ap_pitch_atthold
  elseif ipc.readSTR(0x3D00, 5) == "C182_" then
    trimwheel = trimwheel_c182
  elseif ipc.readSTR(0x3D00, 10) == "Cessna 441" then
    trimwheel = trimwheel_ap_vs
  elseif ipc.readSTR(0x3D00, 20) == "Boeing Stratocruiser" then
    trimwheel = trimwheel_ap_pitch_althold
  else
    trimwheel = trimwheel_trim
  end
end

aircraftchange(nil) -- initialize at least once

function checkvalue(val)
  if prev ~= nil and val ~= prev then -- axis moved
    if math.abs(val) > boundary then
      ipc.display(string.format(
        "Warning:\n\n" ..
        "Trim wheel value near boundary: %d\n" ..
        "Reconnect to restore full range.\n",
        val), 10)
    else
      ipc.display("")
    end
    trimwheel(val - prev)
  end
  prev = val
end

event.sim(AIRCRAFTCHANGE, "aircraftchange")
event.param("checkvalue")
event.button(joystick, button_dn, "trimbutton")
event.button(joystick, button_up, "trimbutton")

 

Link to comment
Share on other sites

Thank you so much!  This really works well!

I modified the script slightly, but this really is an idea solution.

 

Jessica

-- Using a trim wheel axis to operate with trim INC and DEC instead
-- http://forum.simflight.com/topic/72492-using-a-trim-wheel-axis-to-operate-with-trim-inc-and-dec-instead/
--
-- [Auto]
-- 1=Lua trimwheel
-- assign your axis, in the normal FS controls assignment on the left, to "Luavalue trimwheel".

boundary = 16384-2048

function trimwheel_trim(change)
  trim = ipc.readSW(0x0BC0) - change
  if trim < -16384 then
    trim = -16384
  elseif trim > 16383 then
    trim = 16383
  end
  ipc.writeSW(0x0BC0, trim)
end

function trimwheel_ap_vs(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    ipc.control(65895) -- AP_VS_VAR_DEC
  elseif change < 0 then
    ipc.control(65894) -- AP_VS_VAR_INC
  end
end

function trimwheel_ap_pitch(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    ipc.control(66584) -- AP_PITCH_REF_INC_DN
  elseif change < 0 then
    ipc.control(66583) -- AP_PITCH_REF_INC_UP
  end
end

function trimwheel_ap_pitch_atthold(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65804, 1) -- AP_ATT_HOLD_ON
    end
    ipc.control(66584) -- AP_PITCH_REF_INC_DN
  elseif change < 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65804, 1) -- AP_ATT_HOLD_ON
    end
    ipc.control(66583) -- AP_PITCH_REF_INC_UP
  end
end

function trimwheel_ap_pitch_althold(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65816, 1) -- AP_ALT_HOLD_OFF
    end
    ipc.control(66584) -- AP_PITCH_REF_INC_DN
  elseif change < 0 then
    if ipc.readUW(0x07D0) > 0 then -- AP alt lock
      ipc.control(65816, 1) -- AP_ALT_HOLD_OFF
    end
    ipc.control(66583) -- AP_PITCH_REF_INC_UP
  end
end

function trimwheel_c182(change)
  if ipc.readUW(0x07BC) == 0 then -- AP disabled
    trimwheel_trim(change)
  elseif change > 0 then
    ipc.writeLvar("kap140_dn_button", 1)
  elseif change < 0 then
    ipc.writeLvar("kap140_up_button", 1)
  else
    ipc.writeLvar("kap140_dn_button", 0)
    ipc.writeLvar("kap140_up_button", 0)
  end
end

function aircraftchange(eventtype)
  if ipc.readSTR(0x3D00, 5) == "C182_" then
    trimwheel = trimwheel_c182 
  elseif ipc.readSTR(0x3D00, 12) == "Carenado A36" then
    trimwheel = trimwheel_ap_vs
  else
    trimwheel = trimwheel_trim
  end
end

aircraftchange(nil) -- initialize at least once

function checkvalue(val)
  if prev ~= nil and val ~= prev then -- axis moved
    if math.abs(val) > boundary then
      ipc.display(string.format(
        "Warning:\n\n" ..
        "Trim wheel value near boundary: %d\n" ..
        "Reconnect to restore full range.\n",
        val), 10)
    else
      ipc.display("")
    end
    trimwheel(val - prev)
  end
  prev = val
end

event.sim(AIRCRAFTCHANGE, "aircraftchange")
event.param("checkvalue")

 

Link to comment
Share on other sites

  • 1 month later...

Please forgive me I am new to Lua and the finer areas of FSUIPC.

I am using Prepar3d v4.1 and FSUIPC v5.122

I attempted to set this up and I'm a little confused. Is 'Luavalue trimwheel' supposed to be seen as an Event in the Axis Controls Section of the P3d Controls menu, then you assign the Axis Control you want to use to that Event  ?
I'm not seeing it for some reason in the list of events.
I have attached the FSUIPC and also the trimwheel log files.

Would be grateful if someone could offer me some guidance.

 

Regards, Alan Phillips

 

FSUIPC5.log

trimwheel.log

Edited by Alan Phillips
Wrong FSUIPC version in text.
Link to comment
Share on other sites

You won't see the axis because you have no trim wheel, at least your log only shows joystick and rudder.

You can still use the buttons part of my script above though and ignore everything related to the trim axis. Here you have to set the joystick letter and button numbers in the script.

Link to comment
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
×
×
  • 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.