Exemple sous ARM Linux

Exemple sous ARM Linux

Cette semaine, nous allons réaliser deux jauges qui vont afficher le taux d'utilisation du CPU et du disque d'une machine sous Linux, mais on va le faire à la Yoctopuce: deux jauges physiques contrôlées par deux servomoteurs! Comme beaucoup de clients nous ont demandé si nous supportions les architectures ARM, nous allons réaliser ce projet sur un "ordinateur" qui utilise cette architecture.



Parmi toutes les plateformes disponibles, nous avons choisi un serveur NAS (merci à DonPwaro pour l'idée) QNAP TS-219P II. L'intérêt de cette solution est qu'en plus de toutes les fonctionnalités que l'on attend d'un disque réseau, on a la possibilité d'avoir un accès SSH et il est possible de faire compiler et fonctionner ses propres programmes. De plus un NAS est typiquement le genre de machine qui est allumé en permanence, qui ne consomme pas trop et est relativement silencieuse.

Le QNAP utilise un Noyau Linux en interne, il "suffit" donc de compiler un petit programme en C++ qui prend 4 arguments sur la ligne de commande et qui met à jour la position des servomoteurs. Les quatre arguments que nous devons passer à ce programme sont:
- 1 où est branché le Yocto-Servo (sur USB ou sur un machine distante)
- 2 la valeur de la jauge d'utilisation du CPU (de -1000 à +1000)
- 3 la valeur de la jauge d'utilisation du disque (de -1000 à +1000)
- 4 le nombre de millisecondes pour déplacer les servomoteurs (cf. plus bas)

une vue explosée de notre jauge d'utilisation du CPU
une vue explosée de notre jauge d'utilisation du CPU



La logique qui consiste à calculer le pourcentage d'utilisation du CPU et du disque sera quant à elle calculée dans un petit script python. Ce dernier appellera périodiquement notre programme C++ pour mettre à jour la position des servomoteurs. J'entends déjà la remarque "Si vous aviez une API en python, ça serait plus simple...", et vous avez tout à fait raison! L'API python est prévue pour... bientôt. On n'aime pas promettre des dates, mais ne vous en faites pas dès que nous aurons fini la librairie Java on commence la librairie Pyhton.

voilà nos deux jauges montées
voilà nos deux jauges montées



Déplacer les servomoteurs

Commençons par la partie difficile, le C++:

On va partir de l'exemple qui est fourni dans la documentation du Yocto-Servo et en faire une fonction qui va prendre trois arguments :
-1 le nom du servomoteur
-2 la position (de -1000 à 1000)
-3 un délai en ms

L'utilisation du délai mérite une petite explication. La boucle en Python va appeler notre programme toutes les 0.5 secondes. L'approche naturelle serait d'appeler la méthode set_position(int position) qui va mettre à jour la position du servomoteur immédiatement. Cela fonctionne très bien, mais le rendu final n'est pas très joli: les aiguilles se déplacent de manière saccadée. Au lieu de mettre à jour immédiatement la position, nous allons utiliser la méthode move(int position, int ms) qui déplace l'aiguille pour qu'elle atteigne la position après X millisecondes. Ainsi, si on utilise un délai de 500 ms, le servomoteur sera toujours en mouvement et les changements de position seront naturellement lissés. Le désavantage de cette méthode est que la valeur affichée a toujours un retard de 500 millisecondes.

  
différence entre set_position et move



static int updateServoPos(string name,int pos,int delay)
{

    YServo *servo;

    servo =  yFindServo(name);
    if(servo->isOnline())
        if(delay>0)
            servo->move(pos,delay);
        else
            servo->set_position(pos);
    else {
        cerr << "ERROR: servo "<<name <<" is not online"<<endl;
        cerr << "       check your cable and your device configuration (IE: function name)"<<endl;
        return 1;
    }
    return 0;
}



Le code est très simple: il suffit de trouver le servomoteur qui porte le bon nom avec yFindServo(name);. Pour faire propre, on vérifie que le servomoteur est connecté avec la méthode isOnline(); si tout est bon, on appel la méthode move ou set_position. Le main du programme n'a qu'à parser les arguments passés sur la ligne de commande, appeler yRegisterHub(), puis appeler deux fois updateServoPos pour les deux servomoteurs.

La compilation

La première difficulté est d'installer GCC sur le QNAP. Sans trop rentrer dans les détails de configuration du QNAP, il faut tout d’abord installer le module Optware IPKG pour pouvoir installer tout un tas d'applications (GCC entre autre) via le gestionnaire ipkg. Ceci fait, il suffit de se loger par SSH sur le QNAP.

Pour installer gcc et make avec le gestionnaire ipkg, il suffit de taper la commande:

ipkg install gcc make



Si vous avez l'habitude de compiler votre code et de le linker avec nos librairies déjà compilées (disponibles dans le répertoire /Binaries), il n'est pas nécessaire d'installer les sources de la librairie libusb 1.0, sinon vous devrez installer à la main les sources de cette librairie afin de pouvoir tout compiler depuis les sources.

Les sources, la librairie déjà compilée et le makefile sont disponibles ici.

Le script python

On trouve de nombreux exemples de code qui calculent l'utilisation du CPU ou du disque sur internet.

Pour calculer ces deux valeurs, le principe est le suivant:
- 1 mémoriser les statistiques CPU en analysant /proc/stat
- 2 mémoriser les statistiques des accès disque en analysant /proc/diskstats
- 3 attendre X millisecondes
- 4 mémoriser à nouveau les statistiques CPU en analysant /proc/stat
- 5 mémoriser à nouveau les statistiques des accès disque en analysant /proc/diskstats
- 6 calculer la différence entre les deux mesures pour avoir une mesure actuelle

Une fois les deux statistiques calculées, il suffit de faire une règle de trois pour étendre les valeurs sur une échelle de -1000 à +1000.

    global MAX_DISK_USAGE
    cpu_pos = (cpu *2000/100) -1000
    if disk>MAX_DISK_USAGE:
        MAX_DISK_USAGE = disk
    disk_pos = (disk*2000/100) -1000


Il ne reste qu'à appeler notre petit programme C++ que nous avons compilé plus tôt. On passe en argument "usb" (car notre Yocto-Servo est connecté directement sur le QNAP), les deux valeurs pour le CPU et le disque et enfin "500" millisecondes pour lisser les mouvements des deux servomoteurs.

    subprocess.call(["./updateGauge","usb",str(cpu_pos),str(disk_pos),"500"])


Les sources sont aussi disponibles ici.

Il n'y a plus qu'à lancer le script python en tâche de fond et voilà, nous avons nos deux jauges qui fonctionnent.

  
Et voila ce qu'il se passe lorsque qu'on recompile notre librairie sur le QNAP...

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.