Un pseudo terminal pour le Yocto-Serial

Un pseudo terminal pour le Yocto-Serial

Beaucoup de projets de domotique utilisent des mini-PCs qui tournent sous Linux. Certains de ces mini-PCs possèdent une sortie HDMI, mais d’autres, comme le OLinuXino, ne possèdent pas de sortie vidéo. Dans ce cas, la solution pour configurer ces boards est d'utiliser une console série. Le problème est que plus aucun PC de possède de port série, et si vous avez un ordinateur suffisamment vieux pour avoir un port RS232, il n'est pas utilisable car le port RS232 travaille en 12 volts. La solution traditionnelle est d'utiliser un adaptateur USB-serial vendu par le constructeur. Mais il est aussi possible d'utiliser un Yocto-Serial.



Pour cet article, nous allons utiliser un OLinuXino RT5350F. C'est un petit board qui utilise un CPU mips et est livré préinstallé avec la distribution OpenWRT. Hélas, par défaut, le réseau WiFi est désactivé et les ports Ethernet ne sont pas routés. Pour accéder à l'interface de OpenWRT, il faut donc commencer par modifier la configuration réseau ce qui n'est pas facile car le board n'a pas de sortie écran. La seule solution est d'activer le réseau à l'aide de la console série.

Pour accéder à cette console série, il faut connecter le Yocto-Serial aux trois pins GND, UART_TXD2 et UART_RXD2 du board. Attention, il faut brancher la ligne UART_TXD2 du board sur la ligne RX du Yocto-Serial et vice versa sinon la communication ne fonctionnera pas.

Le câblage entre le Yocto-Serial et le OLinuXino
Le câblage entre le Yocto-Serial et le OLinuXino



Ensuite, il faut déterminer les paramètres de communication du port série. En examinant le board et la documentation du OLinuXino, on devine qu'il faut configurer le Yocto-Serial de la manière suivante:

  • 57600 Bauds
  • 8 bits de donnée
  • pas de bit de parité
  • un stop bit
  • pas de contrôle de flux
  • utiliser les niveau TTL (3.3V)


Il est possible de vérifier ces paramètres facilement avec le VirtualHub. La fenêtre de configuration du Yocto-Serial permet de rentrer les paramètres listés plus haut. Pour que le VirtualHub affiche correctement les caractères envoyés par le OLinuXino, il faut utiliser le protocole "Generic ASCII Stream".

La configuration du Yocto-Serial pour communiquer avec le OLinuXino
La configuration du Yocto-Serial pour communiquer avec le OLinuXino



Une fois ces paramètres sauvés, on peut communiquer avec le OLinuXino depuis la fenêtre détail du Yocto-Serial. Étant donné que cette fenêtre est très petite et ne gère pas les séquences d'échappement, le résultat n'est pas très lisible, mais cela permet de vérifier que le câblage est correct.

La fenêtre détail du Yocto-Serial
La fenêtre détail du Yocto-Serial



Il est possible d'envoyer quelques commandes à l'aide du champ "Send", mais c'est vraiment pour dépanner.

La bonne solution est d'écrire un petit programme qui affiche correctement les données envoyées par le OlinuXino et transmet les entrées claviers au board OLinuXino. En gros, il s'agit d'écrire un "pseudo" terminal VT100.

Nous avons choisi d'écrire ce programme en Python car c'est un langage relativement simple et portable, mais on pourrait utiliser n'importe quel autre langage que nous supportons.

La première chose que doit faire ce pseudo terminal est d'instancier un objet YSerialPort correspondant au Yocto-Serial et de le configurer pour utiliser les paramètres que nous avons déjà utilisés plus haut. Si on utilise le même Yocto-Serial, ce n'est pas vraiment nécessaire car ces paramètres sont sauvegardés dans le module, mais c'est une bonne pratique de s’assurer que le module travaille dans le bon mode.

errmsg = YRefParam()
if YAPI.RegisterHub("usb", errmsg) != YAPI.SUCCESS:
    sys.exit("init error" + errmsg.value)

serialPort.set_voltageLevel(YSerialPort.VOLTAGELEVEL_TTL3V)
serialPort.set_serialMode("57600,8N1")
serialPort.set_protocol("Char")
serialPort.reset()
serialPort.registerValueCallback(new_data_cb)



Nous enregistrons une fonction de callback new_data_cb pour afficher les données reçues. Cette fonction sera appelée par la librairie Yoctopuce à chaque fois que de nouvelles données sont disponibles.

unhandled_esc_sequ = ''

def new_data_cb(serial_port, value):
    global unhandled_esc_sequ
    read_str = serial_port.readStr(65535)
    if read_str == '':
        return
    out_str, unhandled_esc_sequ = handle_esc_seq(unhandled_esc_sequ + read_str)
    sys.stdout.write(out_str)



Les paramètres de cette fonction de callback sont l'objet YSerialPort et une chaîne de caractères. Étant donné que le Yocto-Serial est capable de bufferiser jusqu’à 64K de données reçues, la chaîne value ne contient pas directement les données reçues mais la taille des données disponibles sur le Yocto-Serial et les deux derniers caractères. Dans cet exemple, on ne va pas utiliser ce paramètre et simplement appeler la méthode readStr() qui va retourner une chaîne de caractères d'au maximum 65535 caractères contenant les données disponibles qui n'ont pas encore été lues.

Il faut ensuite traiter correctement les séquences d’échappement ANSI pour avoir un affichage correct. C'est le rôle de la fonction handle_escape_sequence. Le code de cette fonction est disponible avec les sources de ce projet sur GitHub. La variable globale last_part est utilisée pour sauver l’éventuelle séquence d’échappement qui serait à cheval entre deux appels à readStr().

Pour finir, il reste à récupérer les touches pressées et les transmettre à l'OlinuXino. Malheureusement, il n'existe pas de module Python pour récupérer ces informations qui fonctionne à la fois sous Unix et sous Windows. Par conséquent, il est nécessaire d’écrire deux implémentations. Sous Windows, on utilise le module msvcrt qui est très simple à utiliser mais limité. Pour les autres plateformes, on utilise le module terminos pour désactiver l’écho et le buffering de l'entrée standard.

Ce code ne suffit pas pour réaliser un vrai terminal qui supporte complètement toutes les séquences d'échappement, mais cela suffit largement pour lire confortablement les logs de boot du kernel Linux et exécuter les quelques commandes pour configurer l'interface réseau.


# Setup terminal settings
colorama.init()
fd = None
old_settings = None
if platform.system() == 'Windows':
    import msvcrt
else:
    import tty
    import termios
    import select

    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    new_settings = termios.tcgetattr(fd)
    new_settings[3] = (new_settings[3] & ~termios.ICANON & ~termios.ECHO)
    termios.tcsetattr(fd, termios.TCSAFLUSH, new_settings)

ctr_c_pressed = False
while True:
    try:
        if kbhit():
            c = getch()
            ctr_c_pressed = False
            keycode = ord(c)
            if keycode == 224:
                c = getch()
                keycode = ord(c)
                if keycode == 72:
                    serialPort.writeStr(colorama.ansi.Cursor.UP())
                elif keycode == 77:
                    serialPort.writeStr(colorama.ansi.Cursor.FORWARD())
                elif keycode == 80:
                    serialPort.writeStr(colorama.ansi.Cursor.DOWN())
                elif keycode == 75:
                    serialPort.writeStr(colorama.ansi.Cursor.BACK())
                else:
                    print("Keyco (%X %c)" % (keycode, c))
            else:
                serialPort.writeByte(keycode)
        YAPI.HandleEvents()
        YAPI.UpdateDeviceList()

    except KeyboardInterrupt:
        if ctr_c_pressed:
            print("Exit serial_term")
            break
        else:
            print("\nPress a second time Ctr-C to exit serial_term")
            ctr_c_pressed = True

YAPI.FreeAPI()
# restore terminal settinsg
if platform.system() != 'Windows':
    termios.tcsetattr(fd, termios.TCSAFLUSH, old_settings)



Comme toujours, le code complet est disponible sur GitHub:
https://github.com/yoctopuce-examples/basic_serial_terminal

On peut stopper le VirtualHub et lancer notre pseudo terminal pour pouvoir confortablement lancer les quelques commandes pour activer l'interface réseau de OLinuXino. Nous n'allons pas détailler les commandes à exécuter pour configurer les interfaces réseau du OLinuXino car elles sont documentées sur le site d'OpenWRT et le but de cet article est de montrer comment exécuter une commande à l'aide d'un Yocto-Serial.


Ce pseudo terminal permet d'exécuter les quelques commandes nécessaires
Ce pseudo terminal permet d'exécuter les quelques commandes nécessaires




L'intérêt d'utiliser un Yocto-Serial au lieu d'un câble propriétaire est triple: Premièrement tous ces adaptateurs USB-Serie utilisent un chip FTDI qui nécessite l'installation d'un driver. Deuxièmement, ces adaptateurs créent des ports COM virtuels qui sont liés à un seul port USB. Donc, si l'on branche le même adaptateur sur la même machine mais sur un autre port USB un nouveau port COM virtuel est créé, et par conséquent il faut modifier la configuration du terminal pour utiliser ce nouveau port COM. Enfin, avec un Yocto-Serial, il est possible de le brancher sur un YoctoHub et il est ainsi possible de l'utiliser à travers un réseau Ethernet, WiFi ou GSM.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.