Interfacer CDU Opencockpits MD-80 Rotate OCUSBMapper

Avro

PILOTE PRO
Messages
1 946
Réactions
271
Bonjour,

j'ai acheté un CDU version 3 à un membre du forum, Julien. C'est un CDU version 3 pour le 737 mais il ressemble beaucoup à celui qui équipe le MD-80 de l'éditeur Rotate sous X-Plane 11.

En regardant les Datarefs du MD-80, je vois que Rotate a bien fait les choses puisque les variables utiles sont bien présentes. Il n'y a plus qu'à faire !

J'utilise l'excellent système, OCUSBMapper, élaboré par Pikitanga et qui remplace avantageusement SIOC.

Il y a un plugin à télécharger ici :
La procédure d'installation est bien décrite dans cette même page.

Ensuite, il faudra créer un dossier portant le nom du script .lua inclus dans ce même dossier. Le scrip complet est joint à cet article. Renommez-le pour enlever l'extension .txt.

Dossier.jpg


Je vous explique mon code car cela peut vous permettre de réaliser la même opération pour un autre appareil.

Code:
--*************************************************************************************--

--**                                    CONSTANTS                                     **--

--*************************************************************************************--


CDU_DEVICE = 0

Cette variable est utile pour gérer le CDU Captain ou First Officer

Code:
--*************************************************************************************--
--**                                 LOCAL VARIABLES                                  **--
--*************************************************************************************--

local color_black      = "0"
local color_blue       = "1"
local color_cyan       = "2"
local color_dark_gray  = "3"
local color_gray       = "4"
local color_green      = "5"
local color_light_gray = "6"
local color_magenta    = "7"
local color_orange     = "8"
local color_pink       = "9"
local color_red        = "A"
local color_white      = "B"
local color_yellow     = "C"

Nous définissions les couleurs du texte utilisables pour notre CDU. Dans mon cas, je n'utiliserai que la couleur verte : color_green = "5"

Code:
--*************************************************************************************--
--**                               FIND CUSTOM DATAREFS                                  **--
--*************************************************************************************--

-- buttons

cduDR_button = find_dataref("pikitanga/ocusbmapper/cdu/input/button")
battery      = find_dataref("Rotate/md80/electrical/battery_on")

Je défini les datarefs utiles. Il existe deux types de datarefs, celles utiles pour gérer le CDU lui même : find_dataref("pikitanga/ocusbmapper/cdu/input/button") et celles propres à mon avion : find_dataref("Rotate/md80/electrical/battery_on")

Ma première variable détectera quelle est la touche appuyée et la seconde va lire dans les données de mon avion si la batterie de mon MD-80 est sur ON.

Code:
-- display

cduDR_dspl_line0  = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/dspl/line0")
cduDR_dspl_line1  = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/dspl/line1")
...
cduDR_dspl_line12 = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/dspl/line12")
cduDR_dspl_line13 = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/dspl/line13")

Les 14 lignes envoyées au CDU sont stockées dans les variables cduDR_dspl_line0 à cduDR_dspl_line13

Code:
-- color

cduDR_color_line0  = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/color/line0")
cduDR_color_line1  = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/color/line1")
...
cduDR_color_line12 = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/color/line12")
cduDR_color_line13 = find_dataref("pikitanga/ocusbmapper/cdu" .. CDU_DEVICE .. "/output/color/line13")

Gestion de la couleur paramétrée par ligne.

Code:
-- leds hardware

cduDR_led_ofst = find_dataref("pikitanga/ocusbmapper/cdu/output/led/ofst")
cduDR_led_msg  = find_dataref("pikitanga/ocusbmapper/cdu/output/led/msg")
cduDR_led_exec = find_dataref("pikitanga/ocusbmapper/cdu/output/led/exec")
cduDR_led_dspy = find_dataref("pikitanga/ocusbmapper/cdu/output/led/dspy")
cduDR_led_fail = find_dataref("pikitanga/ocusbmapper/cdu/output/led/fail")

Les led sur le CDU, si je passe la variable cduDR_led_exec à la valeur 1, elle s'allume sur le CDU


Code:
-- Display MD80

MD80_cdu_DR_line_0 = find_dataref("Rotate/md80/instruments/cdu_line_01")
MD80_cdu_DR_line_1 = find_dataref("Rotate/md80/instruments/cdu_line_02")
...
MD80_cdu_DR_line_12 = find_dataref("Rotate/md80/instruments/cdu_line_13")
MD80_cdu_DR_line_13 = find_dataref("Rotate/md80/instruments/cdu_line_14")

Je récupère dans les variables MD80_cdu_DR_line_0 à MD80_cdu_DR_line_13 les valeurs que je peux lire aussi dans mon cockpit virtuel.

Code:
-- Led MD80 sim
MD80_led_exec = find_dataref("Rotate/md80/fms/exec_pending")
MD80_led_test = find_dataref("Rotate/md80/test/annun_digital_click")

Je lis aussi l'état de deux valeurs dans mon appareil : la led Exec est-elle allumé : MD80_led_exec, ai-je appuyé sur le bouton de test de mes annonciateurs : MD80_led_test.

Code:
--*************************************************************************************--
--**                               FIND CUSTOM COMMANDS                               **--
--*************************************************************************************--

MD80cduA = find_command("rotate/md80/cdu/Cdu_A")
MD80cduB = find_command("rotate/md80/cdu/Cdu_B")
...
MD80cduY = find_command("rotate/md80/cdu/Cdu_Y")
MD80cduZ = find_command("rotate/md80/cdu/Cdu_Z")
MD80cdu0 = find_command("rotate/md80/cdu/Cdu_0")
MD80cdu1 = find_command("rotate/md80/cdu/Cdu_1")
...
MD80cdu8 = find_command("rotate/md80/cdu/Cdu_8")
MD80cdu9 = find_command("rotate/md80/cdu/Cdu_9")
MD80cduBAR = find_command("rotate/md80/cdu/Cdu_BAR")
MD80cduBLNK = find_command("rotate/md80/cdu/Cdu_BLNK")
MD80cduCLB = find_command("rotate/md80/cdu/Cdu_CLB")
MD80cduCLR = find_command("rotate/md80/cdu/Cdu_CLR")
MD80cduCRZ = find_command("rotate/md80/cdu/Cdu_CRZ")
MD80cduDEAR = find_command("rotate/md80/cdu/Cdu_DEAR")
MD80cduDEL = find_command("rotate/md80/cdu/Cdu_DEL")
MD80cduDES = find_command("rotate/md80/cdu/Cdu_DES")
MD80cduDIR = find_command("rotate/md80/cdu/Cdu_DIR")
MD80cduEXEC = find_command("rotate/md80/cdu/Cdu_EXEC")
MD80cduFIX = find_command("rotate/md80/cdu/Cdu_FIX")
MD80cduFL1 = find_command("rotate/md80/cdu/Cdu_FL1")
MD80cduFL2 = find_command("rotate/md80/cdu/Cdu_FL2")
...
MD80cduFL5 = find_command("rotate/md80/cdu/Cdu_FL5")
MD80cduFL6 = find_command("rotate/md80/cdu/Cdu_FL6")
MD80cduFR1 = find_command("rotate/md80/cdu/Cdu_FR1")
MD80cduFR2 = find_command("rotate/md80/cdu/Cdu_FR2")
...
MD80cduFR5 = find_command("rotate/md80/cdu/Cdu_FR5")
MD80cduFR6 = find_command("rotate/md80/cdu/Cdu_FR6")
MD80cduHOLD = find_command("rotate/md80/cdu/Cdu_HOLD")
MD80cduINIT = find_command("rotate/md80/cdu/Cdu_INIT")
MD80cduLEGS = find_command("rotate/md80/cdu/Cdu_LEGS")
MD80cduMENU = find_command("rotate/md80/cdu/Cdu_MENU")
MD80cduNEXT = find_command("rotate/md80/cdu/Cdu_NEXT")
MD80cduPREV = find_command("rotate/md80/cdu/Cdu_PREV")
MD80cduPROG = find_command("rotate/md80/cdu/Cdu_PROG")
MD80cduPTO = find_command("rotate/md80/cdu/Cdu_PTO")
MD80cduRTE = find_command("rotate/md80/cdu/Cdu_RTE")
MD80cduSIGNO = find_command("rotate/md80/cdu/Cdu_SIGNO")
MD80cduSPC = find_command("rotate/md80/cdu/Cdu_SPC")

Si je clique sur un bouton du CDU (voir plus haut la variable cduDR_button), je déclencherai une action dans X-Plane par l'une des commandes ci-dessus.

Pour l'instant, ce n'est qu'une déclaration de variable nous allons voir ce mécanisme ci-dessous ;)

Code:
--*************************************************************************************--
--**                                  SYSTEM FUNCTIONS                                **--
--*************************************************************************************--

function cdu_leds()

        if MD80_led_test == 1 and battery == 2 then
            cduDR_led_exec[0] = 1
            cduDR_led_ofst[0] = 1
            cduDR_led_msg[0]  = 1
            cduDR_led_dspy[0] = 1
            cduDR_led_fail[0] = 1
        end
        if MD80_led_test == 0 and battery < 2 then
            cduDR_led_exec[0] = 0
            cduDR_led_ofst[0] = 0
            cduDR_led_msg[0]  = 0
            cduDR_led_dspy[0] = 0
            cduDR_led_fail[0] = 0
        end
       
        if MD80_led_exec == 1 then
            cduDR_led_exec[0] = 1
        end
        if MD80_led_exec == 0 then
            cduDR_led_exec[0] = 0
        end
   
end

Nous définissons des fonctions. Nous verrons plus loin ce qui les déclenchent. Cette fonction gère l'affichage des leds. La première condition vérifie que l'utilisateur a cliqué sur le bouton de test des annonciateurs et que la batterie est bien sur ON. Dans ce cas, toutes les leds du CDU s'allument. Le second test vérifie que la led EXEC doit être allumé.

Code:
function cdu_buttons()

    if cduDR_button[0] ~= 0 then
   
        -- clr

        if cduDR_button[0] == 1 then
            MD80cduCLR:once()
        end

        -- slash
   
        if cduDR_button[0] == 2 then
            MD80cduBAR:once()
        end
   
        -- delete

        if cduDR_button[0] == 3 then
            MD80cduDEL:once()
        end
   
        -- space

        if cduDR_button[0] == 4 then
            MD80cduSPC:once()
        end
   
        -- Z

        if cduDR_button[0] == 5 then
            MD80cduZ:once()
        end
...
       
        -- ls_5l

        if cduDR_button[0] == 88 then
            MD80cduFL5:once()
        end
       
    end

end

Ces conditions vérifient l'appui sur une touche du CDU cduDR_button[0] == 88 alors elle indique au MD-80 de déclencher la commande MD80cduFL5.

Code:
function cdu_dspl_lines()

    cduDR_color_line0  = "555555555555555555555555555555"
    cduDR_color_line1  = "555555555555555555555555555555"
...
    cduDR_color_line12 = "555555555555555555555555555555"
    cduDR_color_line13 = "555555555555555555555555555555"

Toutes mes lignes doivent être en vert sur fond noir.

Code:
 if battery == 2 then
        -- string.gsub: replace $ by -
        cduDR_dspl_line0  = string.gsub(MD80_cdu_DR_line_0,"%$","-")
        cduDR_dspl_line1  = string.gsub(MD80_cdu_DR_line_1,"%$","-")
...
        cduDR_dspl_line12 = string.gsub(MD80_cdu_DR_line_12,"%$","-")
        cduDR_dspl_line13 = string.gsub(MD80_cdu_DR_line_13,"%$","-")

J'affiche simplement sur le CDU les données lues sur les variables du MD-80 en substituant les $ (pas compris pourquoi) par des tirets (à défaut d'avoir réussi à mettre des ▯.

Code:
        -- if length is less than 30, add spaces after first string found (function xlarge)
       
        if string.len(cduDR_dspl_line1) < 30 then
            cduDR_dspl_line1 = xlarge(cduDR_dspl_line1)
        end
       
        if string.len(cduDR_dspl_line2) < 30 then
            cduDR_dspl_line2 = xlarge(cduDR_dspl_line2)
        end
...
       
        if string.len(cduDR_dspl_line12) < 30 then
            cduDR_dspl_line12 = xlarge(cduDR_dspl_line12)
        end
       
        -- if string.len(cduDR_dspl_line13) < 30 then
            -- cduDR_dspl_line13 = xlarge(cduDR_dspl_line13)
        -- end

Certaines lignes du MD-80 comportent que 24 caractères qui sont plus gros. Je ne sais pas simuler ce changement de taille. J'ai donc décidé de modifier à la vollée, ces lignes trop courtes pour aligner l'ensemble à l'aide de la fonction xlarge. Si ma ligne ne fait pas 30 caractères, c'est qu'elle en fait 24 et j'applique xlarge (voir ci-dessous).

Code:
    else
        cduDR_dspl_line0  = " "
        cduDR_dspl_line1  = " "

        cduDR_dspl_line12 = " "
        cduDR_dspl_line13 = " "
    end
   
end

Si la batterie est sur off, pas d'affichage sur le CDU

Code:
function xlarge(s)
    local deb =  string.find(s, "%s")
    local res =  string.sub(s, 0, deb) .. "      " .. string.sub(s, deb+1)
    return res
end

La fonction qui tue ;) : Je trouve la position du premier espace dans la chaîne puis je reconstitue la chaine de caractère de 0 à la position trouvée auquel j'ajoute 6 espaces puis, je rajoute le reste de la chaine. Vous remarquerez que je ne l'ai pas fait pour cduDR_dspl_line13 (qui est commentée) car d'après mes tests, ce n'était ni utile ni souhaitable.

Code:
--*************************************************************************************--
--**                                XLUA EVENT CALLBACKS                                **--
--*************************************************************************************--

function before_physics()
   
    cdu_leds()
    cdu_buttons()
    cdu_dspl_lines()
   
end

before_physics est la fonction qui est exécutée avant tout autre chose. C'est donc là que nous faisons appel aux fonctions gérant notre CDU.

En définitve, un CDU n'est pas très difficile à gérer. Le programme est long mais c'est surtout car, il y a beacoup de boutons. J'ai aussi commencer à interfacer le MCP OC de type Boeing mais c'est bien plus complexe à réaliser.
 

Fichiers joints

  • MD80_opencockpits_cdu_cpt.lua.txt
    23.6 KB · Affichages: 7
Retour
Haut