Synchronize switches with xplane not working

Support for Arduino in combination with Air Manager and Air Player

Moderators: russ, Ralph

Message
Author
User avatar
Sling
Posts: 5237
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Synchronize switches with xplane not working

#11 Post by Sling »

I hear you but this is a specific application. Another application will require different code. The combining of different API functions to achieve a certain outcome is certainly something that could do with a repository of useful functions. We did start a useful community functions library a while back so perhaps we could add this to it. I’ll dig out that thread and ask if anyone has any further examples they would like to see added.

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Synchronize switches with xplane not working

#12 Post by jph »

Sling wrote: Sun Apr 11, 2021 11:00 am I hear you but this is a specific application. Another application will require different code. The combining of different API functions to achieve a certain outcome is certainly something that could do with a repository of useful functions. We did start a useful community functions library a while back so perhaps we could add this to it. I’ll dig out that thread and ask if anyone has any further examples they would like to see added.
Appreciated Tony.
I still appear to have come across a couple of potential 'bugs' - however, until and unless I explore all possibilites - AND get more experienced with AM AND Lua - then I have to consider all issues as being at my end. (apart from the obvious 'problem between chair and keyboard' errors) .. :lol:
100% on the library or repository - definitely needed inho. I can certainly offer what I can and learn a hell of a lot from others.
Joe
Joe. CISSP, MSc.

xplanearg
Posts: 44
Joined: Mon May 04, 2020 10:37 am

Re: Synchronize switches with xplane not working

#13 Post by xplanearg »

Sling wrote: Sat Apr 10, 2021 4:06 pm @xplanearg Let me explain. First up what you have come up with will work but it has flaws in that you are sharing the same callback for the switch and the subscribe. The switch callback and subscribe callback can and often do have different arguments that are given to the callback to perform its function. In this case you have stumbled across a working solution because you are only using a single argument for each and it happens to be the valid data for both sources.
Let me show the conventional way to do this as per my instructions.

Create a variable to store the hardware switch position at the head of your code and initialise it with the hardware switch position. You can get the position by using the hw_switch_get_position() function.
I made a little error here. It should go after the switch add because it can’t get the position until the switch has been added. See below.

Update this variable with the switch position in the switch callback.

Code: Select all

function switch_49_callback(position)
 
    if position == 0 then
        xpl_command("sim/lights/landing_lights_off")
    else
        xpl_command("sim/lights/landing_lights_on")
    end
    hw_sw_pos = position —update hw switch position var
    
end
switch_49_id = hw_switch_add("ARDUINO_MEGA2560_A_D49", switch_49_callback)

local hw_sw_pos = hw_switch_get_position(switch_49_id) —this is the var create and initialise
Subscribe to the dataref that relates to the switch in question and in the callback compare the subscribed data (sim switch position) to the previously stored hardware switch position. If they are different call the switch callback with the correct position data as the argument.

Code: Select all

function subscribe_callback(pos)
    —if sim switch position does not match the hardware switch position then
    —call the switch callback to send the correct command to the sim
    If pos ~= hw_sw_pos then
        switch_49_callback{hw_sw_pos)
    end
end
xpl_dataref_subscribe("sim/cockpit2/switches/landing_lights_on", "INT", subscribe_callback)
Like I said at the start, your code will work but for the reasons given this is the more conventional method.

Hopefully this explains how to do it and what is happening in each step. A slightly different method would not use a variable to store the hw switch position but just use the hw_switch_get_position() function within the subscribe callback to get the hw switch position just before doing the comparison.

I hope this helps.

Tony

Hi Tony, thanks for your answer, however your solution does not work.
when you move the switch the code automatically writes down the value to zero. It goes on briefly and then off again. So its impossible to turn on the switch.

Ive tried to fix your code, however i think airmanager is fundamentally flawed.
The problem with initial synchronization is still there after i fixed your code, the same happens with my 'solution' previously proposed. Both solutions don't work properly with initial synchronization.

Code: Select all

function switch_36_callback(position)
  local position = hw_switch_get_position(switch_36_id)
  print("The battery switch got changed to position " .. position) 
  if position == 0 then
    xpl_command("sim/electrical/battery_1_off")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_dn") -- c90 laminar
  elseif position == 1 then
    xpl_command("sim/electrical/battery_1_on")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_up") -- c90 laminar
  end
end
switch_36_id = hw_switch_add("ARDUINO_MEGA2560_A_D36", switch_36_callback)
xpl_dataref_subscribe("sim/cockpit2/electrical/battery_on", "INT[8]", switch_36_callback)

The problem i think is because airmanager is event driven, meaning the callbacks or functions only get called when something changes. Even if you subscribe to the corresponding dataref, if the dataref does not change at the start of the simulation, the callback does not get called. Meaning the physical switch and virtual don't get synchronized.

There is no 'While true loop' or continues loop that runs the lua code. It is event driven, only runs when something changes.

Im surprised and disappointed that something so simple like a switch, something basic for any cockpit builder is so hard to configure properly in air manager. I cant believe im the first person with this issue.

the way i got around this, and im still testing it is like so:

Code: Select all

function switch_36_callback(position)
  local position = hw_switch_get_position(switch_36_id)
  print("The battery switch got changed to position " .. position) 
  if position == 0 then
    xpl_command("sim/electrical/battery_1_off")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_dn") -- c90 laminar
  elseif position == 1 then
    xpl_command("sim/electrical/battery_1_on")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_up") -- c90 laminar
  end
end
switch_36_id = hw_switch_add("ARDUINO_MEGA2560_A_D36", switch_36_callback)
xpl_dataref_subscribe("sim/time/total_running_time_sec", "FLOAT", switch_36_callback)
Instead of subscribing to the corresponding dataref, (battery state dataref in this case) im subscribing to the 'sim/time/total_running_time_sec' dataref.
this dataref increments itself every second, so this forces the call of the callback every second.
Effectively im transforming this event driven callback into a continuous while true loop.

I hope this addresses the issue and can move on to building other parts of the sim

User avatar
Sling
Posts: 5237
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Synchronize switches with xplane not working

#14 Post by Sling »

There is no fundamental flaw. I have switch sync working very well with lots of my panels.

I’m not at my sim pc right now so let me take a look when I’m home. It will likely be something trivial.

Tony

ps. I must stress again. My code does not use the same callback for both the switch and the subscribe. There are no examples AFAIK showing them combined so why do you persist with this?

Also forcing the callback to fire every second is simply not required and means code will be unnecessarily run. Not the best for optimal performance.

User avatar
Corjan
Posts: 2936
Joined: Thu Nov 19, 2015 9:04 am

Re: Synchronize switches with xplane not working

#15 Post by Corjan »

Hi,


To be honest, your code seems flawed ;)
Doing a xpl_subscribe using the same switch callback means that the INT[] will be placed in the position argument of the switch_36_callback function.
This is probably not what you want to happen.

You can use the timer if you want to simulate a loop:

Code: Select all

function switch_36_callback(position)
  -- Ignore
end
switch_36_id = hw_switch_add("ARDUINO_MEGA2560_A_D36", function()
  -- ignore events from switch
end)

-- Called every 100ms
timer_start(0, 100, function()
  local position = hw_switch_get_position(switch_36_id)
  print("The battery switch got changed to position " .. position) 
  if position == 0 then
    xpl_command("sim/electrical/battery_1_off")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_dn") -- c90 laminar
  elseif position == 1 then
    xpl_command("sim/electrical/battery_1_on")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_up") -- c90 laminar
  end
end)

Corjan

User avatar
Sling
Posts: 5237
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Synchronize switches with xplane not working

#16 Post by Sling »

@xplanearg

As i suspected it was a couple of small issues. The first was a typo that would of reported an error the second was just the variable declaration. All fixed below.

Code: Select all


local hw_sw_pos

function switch_49_callback(position)

    if position == 0 then
        xpl_command("sim/lights/landing_lights_off")
    else
        xpl_command("sim/lights/landing_lights_on")
    end
    hw_sw_pos = position --update hw switch position var
    
end
switch_49_id = hw_switch_add("ARDUINO_MEGA2560_A_D49", switch_49_callback)

hw_sw_pos = hw_switch_get_position(switch_49_id) --this is the var create and initialise

function subscribe_callback(pos)
    --f sim switch position does not match the hardware switch position then
    --call the switch callback to send the correct command to the sim
    if pos ~= hw_sw_pos then
        switch_49_callback(hw_sw_pos)
    end
end
xpl_dataref_subscribe("sim/cockpit2/switches/landing_lights_on", "INT", subscribe_callback)


xplanearg
Posts: 44
Joined: Mon May 04, 2020 10:37 am

Re: Synchronize switches with xplane not working

#17 Post by xplanearg »

xplanearg wrote: Tue Apr 13, 2021 8:32 pm
the way i got around this, and im still testing it is like so:

Code: Select all

function switch_36_callback(position)
  local position = hw_switch_get_position(switch_36_id)
  print("The battery switch got changed to position " .. position) 
  if position == 0 then
    xpl_command("sim/electrical/battery_1_off")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_dn") -- c90 laminar
  elseif position == 1 then
    xpl_command("sim/electrical/battery_1_on")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_up") -- c90 laminar
  end
end
switch_36_id = hw_switch_add("ARDUINO_MEGA2560_A_D36", switch_36_callback)
xpl_dataref_subscribe("sim/time/total_running_time_sec", "FLOAT", switch_36_callback)
Instead of subscribing to the corresponding dataref, (battery state dataref in this case) im subscribing to the 'sim/time/total_running_time_sec' dataref.
this dataref increments itself every second, so this forces the call of the callback every second.
Effectively im transforming this event driven callback into a continuous while true loop.

I hope this addresses the issue and can move on to building other parts of the sim
I did further testing with this method, and although it works when applied to multiple switches, air manager fundamentally slows down. Now i have a 1 second delay from the moment i press a button to the actual action happening

xplanearg
Posts: 44
Joined: Mon May 04, 2020 10:37 am

Re: Synchronize switches with xplane not working

#18 Post by xplanearg »

Corjan wrote: Wed Apr 14, 2021 7:15 am Hi,


To be honest, your code seems flawed ;)
Doing a xpl_subscribe using the same switch callback means that the INT[] will be placed in the position argument of the switch_36_callback function.
This is probably not what you want to happen.

You can use the timer if you want to simulate a loop:

Code: Select all

function switch_36_callback(position)
  -- Ignore
end
switch_36_id = hw_switch_add("ARDUINO_MEGA2560_A_D36", function()
  -- ignore events from switch
end)

-- Called every 100ms
timer_start(0, 100, function()
  local position = hw_switch_get_position(switch_36_id)
  print("The battery switch got changed to position " .. position) 
  if position == 0 then
    xpl_command("sim/electrical/battery_1_off")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_dn") -- c90 laminar
  elseif position == 1 then
    xpl_command("sim/electrical/battery_1_on")
    xpl_command("laminar/c90/fltctrl/switch/elev_trim_control_up") -- c90 laminar
  end
end)

Corjan
Is this the recommended way to have a switch in airmanager? so far ive been proposed several options, non of those work properly. What is the recommended way?
if i do this timer for many switches, will airmanager slow down?
thanks.

xplanearg
Posts: 44
Joined: Mon May 04, 2020 10:37 am

Re: Synchronize switches with xplane not working

#19 Post by xplanearg »

Sling wrote: Wed Apr 14, 2021 8:37 am @xplanearg

As i suspected it was a couple of small issues. The first was a typo that would of reported an error the second was just the variable declaration. All fixed below.

Code: Select all


local hw_sw_pos

function switch_49_callback(position)

    if position == 0 then
        xpl_command("sim/lights/landing_lights_off")
    else
        xpl_command("sim/lights/landing_lights_on")
    end
    hw_sw_pos = position --update hw switch position var
    
end
switch_49_id = hw_switch_add("ARDUINO_MEGA2560_A_D49", switch_49_callback)

hw_sw_pos = hw_switch_get_position(switch_49_id) --this is the var create and initialise

function subscribe_callback(pos)
    --f sim switch position does not match the hardware switch position then
    --call the switch callback to send the correct command to the sim
    if pos ~= hw_sw_pos then
        switch_49_callback(hw_sw_pos)
    end
end
xpl_dataref_subscribe("sim/cockpit2/switches/landing_lights_on", "INT", subscribe_callback)

Thanks for your code, i suppose this is what you run in your sim and works? i will test this shortly.
cheers.

User avatar
Sling
Posts: 5237
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Synchronize switches with xplane not working

#20 Post by Sling »

Yes it is tested working code.

Post Reply