mardi 1 septembre 2015

52pi's 5 inch HDMI Touch Screen

Un écran 5 pouces HDMI à une trentaine d'euros pour mon Raspberry Pi, difficile de résister...

Il y avait un petit risque parce que la documentation est un peu lacunaire. Difficile de savoir s'il faut absolument un 'custom kernel' fourni par le constructeur ou si modifier /boot/config.txt suffit pour l'affichage. Pour la partie 'touch', je n'ai pas encore regardé (et je compte continuer à utiliser mon clavier Bluetooth IPazzPort). Après avoir un peu chipoté, sans succès, de manière générale en regardant la doc RPi. Je suis tombé sur ce forum où quelqu'un propose :
#increase HDMI signal strength (just a black screen if not set!)
config_hdmi_boost=4

#remove black borders
disable_overscan=1

#set specific CVT mode
hdmi_cvt 800 480 60 6 0 0 0

#set CVT as default
hdmi_group=2
hdmi_mode=87
Et, de fait, cela fonctionne maintenant.


Alimenté par le port USB (micro), il semble consommer 0.38 Ampère (0.23 quand le Pi est éteint; d'après mon 'charger doctor' (non qualibré)).

Voilà qui est beaucoup plus confortable que mon écran SPI 2.5 pouces 320x240 MZTX-PI-EXT, bien que le touchscreen reste résistif. C'est un peu plus encombrant avec les deux câbles en plus mais on récupère les GPIO. (Bien sûr, une tablette ou un smartphone...)

Lsusb donne :
0eef:0005 D-WAV Scientific Co., Ltd
Sur mon desktop Ubuntu, dmesg donne :
$ dmesg
[ 1965.392282] usb 1-1.4: new full-speed USB device number 4 using ehci-pci
[ 1965.486613] usb 1-1.4: New USB device found, idVendor=0eef, idProduct=0005
[ 1965.486618] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1965.486621] usb 1-1.4: Product: By ZH851
[ 1965.486623] usb 1-1.4: Manufacturer: RPI_TOUCH
[ 1965.486625] usb 1-1.4: SerialNumber: @\x18B547044417
[ 1965.488263] hid-generic 0003:0EEF:0005.0003: hiddev0,hidraw1: USB HID v1.10 Device [RPI_TOUCH By ZH851] on usb-0000:00:1a.0-1.4/input0
(mais ne permet pas encore de modifier la position du curseur ni de cliquer...; Cela donne néanmoins le sentiment qu'il devrait être possible de le faire fonctionner assez facilement...)

Pas encore testé mais la solution semble se trouver ici (en Python). En effet, /dev/hidraw1 donne des séquences de 22 caractères du type
170   1   1 115  14  73 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   1   1  90  14  70 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   0   0   0   0   0 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   1   1  93   2  70 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   0   0   0   0   0 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   1  14 200   2 105 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   1  14 194   2  98 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
170   1  14 200   2 113 187   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
où on devine un marqueur de début, un marqueur de fin, un indicateur de 'touché' et des xy sur deux caractères. En ne gardant que ces trois derniers, on lit des choses comme :
1 283 535
1 285 537
0   0   0
1 3790 3732
1 3795 3748
1 3795 3753
Les coordonnées sont comprises entre 0 et 4096. Il va donc falloir adapter le bidule... J'ai mis un court programme en 'C' sur https://github.com/xofc/hidraw2uinput. Aucun paramètre, tout est 'hardcodé' mais le programme n'est pas très long et devrait être facile à adapter et à installer. Sinon, il reste la solution en Python... (interprété, donc plus lourd et avec plus de dépendances (voir le script d'installation; le programme 'C' ne dépend de rien de particulier))

À noter que le Raspberry Pi possède un 'écran officiel' depuis le 08 septembre 2015.

Pour regarder de la vidéo, Xbmc (maintenant Kodi) est préférable à Vlc (qui manque de ressources sur un Pi-1).

5" HDMI LCD de Waveshare

On trouve un autre écran du même type qui s'enfiche sur le connecteur P1 des Raspberry (fabriqué par WaveShare). Il est fourni avec un adaptateur en 'U' pour le HDMI. Il est bien en face avec le Pi-2. Pour l'autre modèle que je possède (B rev 2?), il n'est pas en face mais cela fonctionne car le début du connecteur est compatible. Le connecteur HDMI est sur le grand côté, au dessus.
Sur certaines photos, il semble également avoir un connecteur micro-USB mais, en fait, il est factice (!) et la communication avec le 'touch' (XPT2046 ?) s'effectue via les GPIO de P1 (notamment SPI). J'ignore s'il est possible d'adapter le kernel, ils fournissent une image complète (que je ne compte pas utiliser). J'utiliserai la souris. Ou, peut-être regarder ici (mais je ne suis pas sûr qu'il y ait bien un XPT2046 et, en tout cas, les pins GPIO ne semblent pas correspondre... Mais cela vaudrait la peine de creuser la question et, éventuellement de faire une émulation de souris comme avec l'autre.

On peut déjà vérifier que P1-22 change d'état quand on touche l'écran avec WiringPi (apt-get install wiringpi) et la commande 'gpio readall' :
On voit également que les connexions annoncées par WaveShare correspondent effectivement à MISO, MOSI, SCLK et CE1. Le pas suivant est d'utiliser spincl(1) pour entrer en communication avec l'éventuel contrôleur XPT2046 (nécessite la libbcm2835).

En fait, spincl(1) est tellement simple qu'il est possible de tester la communication SPI directement en 'C', en quelques lignes. Quelque chose comme :
#include "bcm2835.h"                    

#define MAX_LEN 4
                                         
#define START   0x80    
#define XPOS    0x50
#define YPOS    0x10                    

int getit(int cmd)
    {
    char rbuf[MAX_LEN];
    char wbuf[MAX_LEN];
        
    memset(wbuf, 0, sizeof(rbuf));
    memset(rbuf, 0, sizeof(rbuf));
    wbuf[0] = cmd;
    bcm2835_spi_transfernb(wbuf, rbuf, sizeof(wbuf));
    return((rbuf[1]<<8)+rbuf[2]);
    }
int getxy(int *xp, int *yp)
    {
    bcm2835_spi_begin();
  
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_1024);
    bcm2835_spi_chipSelect(BCM2835_SPI_CS1);
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS1, LOW);
        
    *xp = getit(START | XPOS); 
    *yp = getit(START | YPOS); 
        
    bcm2835_spi_end();
    return(1);
    }
donne des valeurs de XY dans l'intervalle 0..32768 quand l'écran est touché. Un petit programme qui envoie les données du XPT2046 dans /dev/uinput se trouve ici. À noter qu'un échange de 3 octets (et non 4) devrait suffire...

En fait, il est difficile de calibrer et ensuite de pointer exactement de petits 'contrôles' sur un écran 'résistif'. Il est probable qu'une émulation de souris (événements relatifs) soit plus efficace qu'une gestion avec des événements absolu. L'écran se comportant alors comme un 'touchpad'. Il n'y a plus qu'à...; le plus dur/incertain est fait.

À suivre...