Écran multifonction pour simulateur de vol (MFD)

Introduction

L’accès à certaines fonctionnalités embarqués sur un avion de combat (navigation, systèmes d’armes, désignateur, …) passe par un écran multifonctions (MultiFunction Display). Bien que certains simulateurs proposent un cockpit cliquable, il est toujours embêtant de devoir orienter le champ de vision à chaque fois que l’on souhaite effectuer une action. Du coup, l’utilisation d’un périphérique matériel augmente l’immersion et améliore l’expérience de jeu.

Les solutions commerciales existantes (ThrustMaster Cougar Pack) ne m’ayant pas impressionné, j’ai décidé de concevoir un écran multifonction fonctionnant sur USB.

Le projet que je présente est conçu pour fonctionner avec DCS. Cependant, comme il utilise un écran HDMI et des contrôles type joystick, il n’y a pas de raisons pour que ça ne marche pas avec d’autres simulateurs.

Principes de fonctionnement

L’idée consiste à configurer DCS pour envoyer l’image des MFD gauche et droite sur deux écrans supplémentaires. Pour ce faire, il faut créer un fichier de configuration dans le dossier MonitorSetup du jeu et ajouter ces deux paramètres (il faut bien évidemment ajuster les offsets pour tomber dans les bons écrans) :

_  = function(p) return p; end;
name = _('MFD_Display');
Description = 'Config maison'
Viewports =
{
     Center =
     {
          x = 1920;
          y = 0;
          width  = 1920;
          height = 1080;
          viewDx = 0;
          viewDy = 0;
          aspect = 1.6;
     }
}

LEFT_MFCD =
{
    x = 1920*2+(1024/2-768/2);
    y = 0;
    width  = 768;
    height = 768;
}

RIGHT_MFCD =
{
    x = 1920*2+1024+(1024/2-768/2);
    y = 0;
    width  = 768;
    height = 768;
}

UIMainView = Viewports.Center
GU_MAIN_VIEWPORT = Viewports.Center

L’assignation des touches se fait simplement dans DCS, comme n’importe quel autre périphérique d’entrée.

Pour l’affichage, j’ai choisi un écran LCD 4:3 de 8 pouces. Il a une résolution de 1024×768 :

​​

Son prix et sa taille en font une solution intéressante : https://fr.aliexpress.com/item/32325920866.html?spm=a2g0s.9042311.0.0.d0dd6c37EdzyS4​

L’électronique

Conception

Pour simplifier l’intégration matérielle, j’ai choisi d’utiliser un petit microcontrôleur de chez Microchip capable de faire de l’USB et de l’I2C : le PIC18F25K50. Il communique avec 4 cartes filles qui s’occupent chacune de 7 boutons.

La séparation en plusieurs cartes répond à deux impératifs :

  1. Rentrer dans une conception Autodesk EAGLE version gratuite
  2. Diminuer les coûts de fabrication en réduisant la surface de circuit imprimé

La carte mère sera montée au dos du MFD :

Deux cartes en angle et deux cartes droites permettent de former un cadre autour de l’écran LCD :

 

La carte mère

La carte mère du MFD se contente de faire le lien entre les différentes cartes filles (I2C) et le PC (USB). Le schéma est donc des plus simples, il reprend celui de la boite à boutons ou de l’interface HID, mais avec un composant différent :

​On retrouve une horloge, un circuit de reset, le connecteur USB, un connecteur pour l’I2C et un connecteur de programmation. Pour changer mes habitudes, j’ai réalisé mes cartes avec des composants à montage en surface (CMS) :

Les cartes filles

Bien que 2 formes différentes soient nécessaires, elles ont toutes le même schéma (à la différence de l’adresse). Il s’agit d’un multiplexeur 8 entrées tout ou rien vers I2C MCP23008. Les résistances de tirages sont intégrées dans la puce. Les cartes sont adressées par un pont à souder pour le bit de poids faible et câblé en dur à 1 pour les cartes en L (0 pour les cartes en I).

Deux connecteurs I2C permettent de former une chaine avec les 4 cartes. Un troisième permet de relier la carte mère sur l’une des cartes filles.

La configuration des boutons à bascules présents aux 4 coins du MFD oblige à avoir deux formes de cartes:

Les dimensions sont adaptées à la taille de l’écran de 8 pouces et au boitier imprimé en 3D dessiné tout spécialement.

Réalisation

J’ai sous-traité la fabrication des PCB (double couches) à NextPCB.

Les soudures des composants CMS sont réalisées au fer à souder, avec une panne fine. Pour rendre cela possible, j’ai choisi des boitiers SOIC (gros composants CMS, pas de 1.27mm) et des formats 0805 pour les résistances et condensateurs. Finalement, le composant le plus petit et le plus difficile à souder est la LED indiquant la mise sous tension.

NB : une bonne pince brucelles est nécessaire !

Intégration mécanique

J’ai fait découper au LASER des tôles d’inox pour réaliser les faces avant (https://www.metal-laser.com/). Le boitier plastique qui accueille ​les cartes filles ainsi que les différentes touches sont imprimés en 3D. La conception mécanique et l’intégration des cartes électroniques a été réalisée à l’aide Fusion 360. Cet outil permet de facilement faire converger les CAO électroniques et mécaniques.

Il est important de pouvoir vérifier la profondeur du boitier plastique, notamment pour que les boutons poussoirs tombent en dessous des touches plastiques.

L’écran LCD est fixé (scotché ou collé) à l’arrière du cadre. La face avant est également collée au boitier plastique.

Le logiciel

Une fois n’est pas coutume, le code du microcontrôleur a été écrit en C à l’aide de MikroC. Outre l’initialisation de la puce et le driver des multiplexeurs, la boucle principale se contente de lire les 4 ports d’entré sur l’I2C et d’envoyer le rapport USB HID.

/**
* Version IO Expander MCP23018
**/

#include "MCP23008.h"

#define USB_BUFFER_LEN       4
#define NB_MCP               4

unsigned char readbuff[USB_BUFFER_LEN] absolute 0x500;
unsigned char writebuff[USB_BUFFER_LEN] absolute 0x540;

int reset_mcp23017 = 1;

void interrupt() {
    USB_Interrupt_Proc();        // USB servicing is done inside the interrupt
    USBIF_bit = 0;
}

// define callback function
void I2C1_TimeoutCallback(char errorCode) {
   if (errorCode == _I2C_TIMEOUT_RD) {
     //LED0 = 1;
     // do something if timeout is caused during read
   }

   if (errorCode == _I2C_TIMEOUT_WR) {
     //LED1 = 1;
     // do something if timeout is caused during write
   }

   if (errorCode == _I2C_TIMEOUT_START) {
     //LED0 = 1;
     // do something if timeout is caused during start
   }

   if (errorCode == _I2C_TIMEOUT_REPEATED_START) {
     //LED1 = 1;
     // do something if timeout is caused during repeated start
   }
   
   reset_mcp23017 = 1;
}
          
void main() {
    int i = 0;
    int cpt = 0;
    
    uint16_t temp;

    ANSELA = 0;
    ANSELB = 0;
    ANSELC = 0;
    SLRCON = 0;

    ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
    CM1CON0 |= 7;                           // Disable comparators

    TRISB = 0xff;
    TRISB.f2 = 0;
    LATB.f2 = 1;

    I2C1_Init(400000);         // initialize I2C communication
    
    // set timeout period and callback function
    I2C1_SetTimeoutCallback(40000, I2C1_TimeoutCallback);

    reset_mcp23017 = 1;

    FSEN_bit = 1;
    UPUEN_bit = 1;
    HID_Enable(&readbuff,&writebuff);
    
    // Enable USB device interrupt
    IPEN_bit = 1;
    USBIP_bit = 1;
    USBIE_bit = 1;
    GIEH_bit = 1;

    while (1) {
        if (reset_mcp23017) {
           LATB.f2 = 0;       //RESET MCP23017
           Delay_ms(250);
           LATB.f2 = 1;
           Delay_ms(250);

           for (i=0; i<NB_MCP; i++) {
            MCPreset(i);
            Delay_ms(5);
           }
          reset_mcp23017 = 0;
        }

        memset(writebuff, 0x00, USB_BUFFER_LEN);
    
        for (i=0; i<NB_MCP; i++) {
          temp = MCPread(i, GPIO);
          writebuff[i] = ~temp;
          Delay_ms(5);
          if(reset_mcp23017) break;
        }
        
        HID_Write(writebuff, USB_BUFFER_LEN);
        Delay_ms(5);
    }
}

 

Le premier test

Un dock USB 3.1 peut servir pour gérer le HDMI et l’USB simultanément, ce qui permet d’avoir une unique prise USB occupée sur le PC. Si la configuration de DCS est correcte et que l’écran est bien détecté, voici le résultat que l’on peut obtenir :

La même chose en vidéo :

 

 

Conclusion

Il me reste encore à imprimer des touches propres et à finir l’état de surface de la face avant. Pour le reste, le rendu est vraiment sympa. Reste à tester réellement sur une session de pilotage plus longue.

Laisser un commentaire