OpenHMD – le casque VR do-it-yourself, Mark I : préparation

Parfois Souvent, il me prend une pulsion… Genre le coyote veut choper bip-bip, et se réveille avec une idée alakon… Et on imagine la suite… Bref, tout pareil…

Voila donc l’idée : je rêve depuis que je suis gosse d’avoir un casque, qui me superposerait des infos par dessus la vision « normale ». En 2015, on appele ça de la réalité augmentée. Cool. Sauf que les seuls qui, selon moi, ont réussi à exploiter le concept, sont les designers des interfaces du film Iron Man, et dans une autre mesure, Microsoft et leur HoloLens. J’aimerai avoir un Oculus DK2 à disposition pour voir ce qui est possible avec, mais malheureusement ce n’est pas le cas.

Donc voyons ce que je peux fabriquer avec ce que j’ai sous la main :

– 2 écrans hy28b avec touchpanel, 2.8″ 320×240, interface SPI. Ils ont l’air exactement identiques, donc j’imagine qu’ils le sont. Très bon point.
– 1 raspberry pi-1 B. C’est ce que j’ai de plus compatible avec les 2 écrans sus-mentionnés.
– une camera ps3 eye. 120 fps en 320×240, ca parait sympa.
– une coque ColorCross avec 2 lentilles à focale ~7cm. Fonctionne super bien avec mon Galaxy S3 et les applis Google Cardboard. Mais, qu’est-ce que c’est ennuyeux, après les 12 premières secondes…

Donc l’idée, dans un premier temps, est de faire fonctionner les 2 écrans en mode clone.
Dans un second temps, je fabriquerai des adaptateurs pour connecter les écrans au raspberry pi et tenterai d’assembler un bidule utilisable.
Dans un troisième temps, j’installerai le tout dans la coque colorcross, avec la camera ps3 eye.
Enfin, si tout fonctionne, je coderai une appli pygame pour faire du camera pass-through.

On verra le résultat…

1- Installation de l’image de base

Mes écrans SPI fonctionnent avec l’excellent kernel FBTFT. J’utilise depuis assez longtemps une vieille image précompilée, donc pas forcément optimisée. On va donc repartir de zéro.

On télécharge donc l’image Raspbian officielle : lien

Une fois l’image installée sur la carte SD, on la configure grâce à la commande « sudo raspi-config ». Il est important de redimentionner la partition, changer le mot de passe, les locales, et désactiver le démarrage automatique de X.

Après le reboot, il s’agit maintenant de faire fonctionner les écrans SPI.

2- Faire fonctionner les écrans SPI

1- Le hardware

Etant donné que les écrans, d’origine, utilisent les 2 cable select (CS, ou SP) du seul canal SPI disponible, l’idée est donc de supprimer les touchpanels, ce qui libérera un CS par écran, et permettra donc d’utiliser nos 2 écrans.

Les connexions communes aux 2 écrans seront donc :

  • MOSI (broche 19)
  • MISO (broche 21)
  • SCLK (broche 23)
  • 3.3v
  • GND

Les seules connexions indépendantes seront donc :

  • SP0 et SP1, qui correspondent aux 2 CS du canal SPI (broches 24 et 26) et qui seront câblées aux SP0 de chaque écran (broche 24),
  • les GPIOs 24 (broche 18) et 25 (broche 22), qui seront câblés sur la broche 22 de chaque écran.

2- Le software

Les versions récentes de raspbian utilisent un nouveau système pour charger certains pilotes, les « overlays » : la plupart du temps, il n’est plus nécessaire de passer par les modules ou une reconfiguration du noyau. Une simple modifications du/des overlays suffit.

Si nous voulons utiliser les écrans SPI hy28b à leurs performances maximales, nous aurons besoin du DMA. Le support du DMA n’est pas présent dans le kernel classique, nous installons donc donc le kernel FBTFT de Notro, qui permet d’utiliser l’overlay hy28b en mode DMA :

sudo REPO_URI=https://github.com/notro/rpi-firmware rpi-update

Après le reboot :

On peut vérifier que /boot/ contient un dossier « overlays », qui contient lui-même des fichiers .dtb. Ces « overlays », que l’on peut activer, désactiver, paramétrer depuis /boot/config.txt, contrôlent certains périphériques.

Nous allons créer un nouvel overlay sur la base de l’overlay existant « hy28b », en lui enlevant le touchscreen, et en le remplaçant par un second écran hy28b. En effet, le Raspberry Pi embarque un seul canal SPI avec 2 lignes chip select. A l’origine, un écran et son touchscreen occupent les 2 seules lignes chip select, donc nous devons supprimer les touchscreen pour activer les 2 écrans.

Les fichiers overlay .dtb sont des fichiers .dts compilés. nous aurons donc besoins du compilateur :

wget -c https://raw.githubusercontent.com/RobertCNelson/tools/master/pkgs/dtc.sh
chmod +x dtc.sh
./dtc.sh

Voici donc le fichier « dual_hy28b_nots.dts » écrit avec l’aide de notro, qui permet l’activation de 2 écrans SPI hy28b :

/boot/overlays/dual_hy28b_nots.dts

/* 
 * Device Tree overlay for HY28A display shield by Texy 
 * 
 */ 
 
/dts-v1/; 
/plugin/; 
 
/ { 
    compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; 
 
    fragment@0 { 
          target = <&spi0>; 
          __overlay__ { 
             status = "okay"; 
 
             spidev@0{ 
                status = "disabled"; 
             }; 
 
             spidev@1{ 
                status = "disabled"; 
             }; 
          }; 
       }; 
 
    fragment@1 { 
        target = <&spi0>; 
        __overlay__ { 
            /* needed to avoid dtc warning */ 
            #address-cells = <1>; 
            #size-cells = <0>; 
 
            hy28a@0{ 
                compatible = "ilitek,ili9320"; 
                reg = <0>; 
 
                spi-max-frequency = <32000000>; 
                spi-cpol; 
                spi-cpha; 
                rotate = <180>; 
                bgr; 
                fps = <30>; 
                buswidth = <8>; 
                startbyte = <0x70>; 
                reset-gpios = <&gpio 25 0>; 
                led-gpios = <&gpio 18 1>; 
                debug = <0>; 
            }; 
             
            hy28a@1{ 
                compatible = "ilitek,ili9320"; 
                reg = <1>; 
 
                spi-max-frequency = <32000000>; 
                spi-cpol; 
                spi-cpha; 
                rotate = <180>; 
                bgr; 
                fps = <30>; 
                buswidth = <8>; 
                startbyte = <0x70>; 
                reset-gpios = <&gpio 24 0>; 
                /*led-gpios = <&gpio 23 1>;*/ 
                debug = <0>; 
            }; 
        }; 
    }; 
};

C’est ce fichier qui définit, entre autres, l’orientation de l’écran avec la variable rotate, exprimée en degrés.

Il est très certainement assez facile d’adapter ce code pour d’autre types d’écrans.

La commande pour compiler ce fichier dans le bon dossier est la suivante :

sudo dtc -@ -I dts -O dtb -o /boot/overlays/dual_hy28a-overlay.dtb dual_hy28a-overlay.dts

Activer l’overlay dans /boot/config.txt :

sudo nano /boot/config.txt

A la fin du fichier, rajouter :

dtoverlay=dual_hy28a-overlay,debug=3

Activer la console sur un des 2 écrans, pour vérifier que tout va bien :

sudo nano /boot/cmdline.txt

A la fin de la première ligne, ajouter :

fbcon:map=10

Rebooter
Si vous voyez votre console se lancer sur un des écrans, et en lançant la commande « ls /dev/ » vous voyez fb0, fb1, fb2, c’est gagné. fb0 est la sortie HDMI, les fb (framebuffers) suivants sont les écrans SPI.

3- Activer le mode clone

Je ne connais aucune méthode pour cloner l’affichage d’une console sur 2 écrans, à part fbcp. Cependant, fbcp consomme des ressources, et rajoute un delay de quelques dizaines de microsecondes entre l’affichage principal et l’affichage « cloné », ce qui est hors de question pour un casque de vision augmentée (les 2 yeux ont besoin d’être parfaitement synchronisés). De plus, je n’ai pas réussi à le modifier pour copier fb1 vers fb2. Il persiste à vouloir copier fb0 (la sortie HDMI).
Donc, nous allons activer proprement le mode clone dans X11, et nous lancerons notre application via xinit, ce qui aura pour effet de lancer les bases de X11, et donc, notre application en mode clone comme sous X11, mais sans bureau.

sudo nano /usr/share/X11/xorg.conf.d/99-fbturbo.conf

Remplacer le contenu du fichier par :

Section "Device"
        Identifier      "fbdev1"
        Driver          "fbturbo"
        Option          "fbdev" "/dev/fb1"
        Option          "SwapbuffersWait" "false"
EndSection

Section "Device"
        Identifier      "fbdev2"
        Driver          "fbturbo"
        Option          "fbdev" "/dev/fb2"
        Option          "SwapbuffersWait" "false"
EndSection

Section "Screen"
        Identifier      "lcd1"
        Device          "fbdev1"
        Monitor         "monitor1"
        SubSection "Display"
        Depth 24
        Virtual 800 600
        Modes "800x600@60"
        EndSubSection
EndSection

Section "Screen"
        Identifier      "lcd1"
        Device          "fbdev1"
        Monitor         "monitor1"
        SubSection "Display"
        Depth 24
        Virtual 800 600
        Modes "800x600@60"
        EndSubSection
EndSection

Section "Screen"
        Identifier      "lcd2"
        Device          "fbdev2"
        Monitor         "monitor2"
        SubSection "Display"
        Depth 24
        Virtual 800 600
        Modes "800x600@60"
        EndSubSection
EndSection

Section "ServerLayout"
        Identifier      "Default Layout"
        Screen          0 "lcd1"
        Screen          1 "lcd2"
        Option          "Xinerama" "on"
EndSection

Désormais, quand on lance « startx », le bureau devrait se lancer sur les 2 écrans, qui devraient être parfaitement synchronisés :

20150521_170228

Bon, ok, on peut déjà dire que vu le matos, ce ne sera jamais à la hauteur du casque d’Iron Man… Plastic Man, ca le ferait, pour cette v1 ?

Hop, à la volée, renommée Mark I…

About Captain Stouf

Spécialiste en systèmes informatiques, Développeur matériel et logiciel, Inventeur, Maker : électronique, Systems on Chip, micro-controlleurs, Internet of Things, Modélisation / Scan / Impression 3D, Imagerie...

3 thoughts on “OpenHMD – le casque VR do-it-yourself, Mark I : préparation

Laisser un commentaire