Commander un Arduino avec une tablette Android

- Etude de cas -


précédentsommairesuivant

IV. Programmation des Arduinos

Nous nous intéressons ici à l'écriture du code C des Arduinos :

Image non disponible

A lire

  • dans [ref2] : l'utilisation de bibliothèques JSON (Annexes, paragraphes 11.1 et 11.2) ;
  • dans l'IDE de l'Arduino, tester l'exemple d'un serveur TCP (le serveur web par exemple) et celui d'un client TCP (le client Telnet par exemple) ;
  • les annexes sur l'environnement de programmation des Arduinos au paragraphe , page .

IV-A. Les spécifications de la couche [Arduino]

Image non disponible

Un Arduino est un ensemble de pins reliées à du matériel. Ces pins sont des entrées ou des sorties. Leur valeur est binaire ou analogique. Pour commander l'Arduino, il y aura deux opérations de base :

  • écrire une valeur binaire / analogique sur une pin désignée par son numéro ;
  • lire une valeur binaire / analogique sur une pin désignée par son numéro ;

A ces deux opérations de base, nous en ajouterons une troisième :

  • faire clignoter une led pendant une certaine durée et avec une certaine fréquence. Cette opération peut être réalisée en appelant de façon répétée les deux opérations de base précédentes. Mais nous verrons aux tests que les échanges de la couche [DAO] avec un Arduino sont de l'ordre de la seconde. Il n'est alors pas possible de faire clignoter une led toutes les 100 millisecondes. Aussi implanterons-nous sur l'Arduino lui-même cette fonction de clignotement.

Le fonctionnement de l'Arduino sera le suivant :

  • les communications entre la couche [DAO] et un Arduino se font via un réseau TCP-IP par échanges de lignes de texte au format JSON (JavaScript Object Notation) ;
  • au démarrage, l'Arduino vient se connecter au port 100 d'un serveur d'enregistrement présent dans la couche [DAO]. Il envoie au serveur une unique ligne de texte :
 
CacherSélectionnez

C'est une chaîne JSON caractérisant l'Arduino qui se connecte :

  • id : un identifiant de l'Arduino, ici son adresse IP ;
  • desc : une description de ce que sait faire l'Arduino. Ici on a simplement mis le type de l'Arduino ;
  • mac : adresse Mac de l'Arduino ;
  • port : le numéro du port sur lequel l'Arduino va attendre les commandes de la couche [DAO].

Toutes ces informations sont de type chaînes de caractères sauf le port qui est un nombre entier.

  • une fois que l'Arduino s'est inscrit auprès du serveur d'enregistrement, il se met à l'écoute sur le port qu'il a indiqué au serveur. Il attend des commandes JSON de la forme suivante :
 
CacherSélectionnez

C'est une chaîne JSON avec les éléments suivants :

  • id : un identifiant de la commande. Peut être quelconque ;
  • ac : une action. Il y en a trois :
  • pw (pin write) pour écrire une valeur sur une pin,
  • pr (pin read) pour lire la valeur d'une pin,
  • cl (clignoter) pour faire clignoter une led ;
  • pa : les paramètres de l'action. Ils dépendent de l'action.
  • l'Arduino renvoie systématiquement une réponse à son client. Celle-ci est une chaîne JSON de la forme suivante :
 
CacherSélectionnez

  • id : l'identifiant de la commande à laquelle on répond ;
  • er (erreur) : un code d'erreur s'il y a eu une erreur, 0 sinon ;
  • et (état) : un dictionnaire toujours vide sauf pour la commande de lecture pr. Le dictionnaire contient alors la valeur de la pin n° x demandée.

Voici des exemples destinés à clarifier les scpécifications précédentes :

Faire clignoter la led n° 8 10 fois avec une période de 100 millisecondes :

Commande

{"id":"1","ac":"cl","pa":{"pin":"8","dur":"100","nb":"10"}}

Réponse

{"id":"1","er":"0","et":{}}

Les paramètres pa de la commande cl sont : la durée dur en millisecondes d'un clignotement, le nombre nb de clignotements, le n° pin de la pin de la led.

Ecrire la valeur binaire 1 sur la pin n° 7 :

Commande

{"id":"2","ac":"pw","pa":{"pin":"7","mod":"b","val":"1"}}

Réponse

{"id":"2","er":"0","et":{}}

Les paramètres pa de la commande pw sont : le mode mod b (binaire) ou a (analogique) de l'écriture, la valeur val à écrire, le n° pin de la pin. Pour une écriture binaire, val est 0 ou 1. Pour une écriture analogique, val est dans l'intervalle [0,255].

Ecrire la valeur analogique 120 sur la pin n° 2 :

Commande

{"id":"3","ac":"pw","pa":{"pin":"2","mod":"a","val":"120"}}

Réponse

{"id":"3","er":"0","et":{}}

Lire la valeur analogique de la pin 0 :

Commande

{"id":"4","ac":"pr","pa":{"pin":"0","mod":"a"}}

Réponse

{"id":"4","er":"0","et":{"pin0":"1023"}}

Les paramètres pa de la commande pr sont : le mode mod b (binaire) ou a (analogique) de la lecture, le n° pin de la pin. S'il n'y a pas d'erreur, l'Arduino met dans le dictionnaire "et" de sa réponse, la valeur de la pin demandée. Ici pin0 indique que c'est la valeur de la pin n° 0 qui a été demandée et 1023 est cette valeur. En lecture, une valeur analogique sera dans l'intervalle [0, 1024].

Nous avons présenté les trois commandes cl, pw et pr. On peut se demander pourquoi on n'a pas utilisé des champs plus explicites dans les chaînes JSON, action au lieu de ac, pinwrite au lieu de pw, parametres au lieu de pa, ... On va découvrir qu'un Arduino a une mémoire très réduite. Or les chaînes JSON échangées avec l'Arduino participent à l'occupation mémoire. On a donc choisi de raccourcir celles-ci au maximum.

Voyons maintenant quelques cas d'erreur :

Commande

xx

Réponse

{"id":"","er":"100","et":{}}

On a envoyé une commande qui n'est pas au format JSON. L'Arduino a renvoyé le code d'erreur 100.

Commande

{"id":"4","ac":"pr","pa":{"mod":"a"}}

Réponse

{"id":"4","er":"302","et":{}}

On a envoyé une commande pr en oubliant le paramètre pin. L'Arduino a renvoyé le code d'erreur 302.

Commande

{"id":"4","ac":"pinread","pa":{"pin":"0","mod":"a"}}

Réponse

{"id":"4","er":"104","et":{}}

On a envoyé une commande pinread inconnue (c'est pr). L'Arduino a renvoyé le code d'erreur 104.

On ne continuera pas les exemples. La règle est simple. L'Arduino ne doit pas planter, quelque soit la commande qu'on lui envoie. Avant d'exécuter une commande JSON, il doit s'assurer que celle-ci est correcte. Dès qu'une erreur apparaît, l'Arduino arrête l'exécution de la commande et renvoie à son client la chaîne JSON d'erreur. Là encore, parce qu'on est contraint en espace mémoire, on renverra un code d'erreur plutôt qu'un message complet.

IV-B. Enregistrement de l'Arduino

A lire

  • dans [ref2] : l'utilisation de bibliothèques JSON (Annexes, paragraphes 11.1 et 11.2) ;
  • dans l'IDE de l'Arduino, tester l'exemple d'un serveur TCP (le serveur web par exemple) et celui d'un client TCP (le client Telnet par exemple) ;
  • les annexes sur l'environnement de programmation des Arduinos au paragraphe , page .

IV-B-1. Le code

Image non disponible

Au démarrage, l'Arduino doit s'enregistrer auprès d'un serveur de la couche [DAO] sur le port 102 en lui envoyant une chaîne JSON de la forme :

 
CacherSélectionnez

Le code de démarrage de l'Arduino pourrait être le suivant :

 
CacherSélectionnez
  • lignes 1-4 : les fichiers headers des fonctions utilisées dans le code ;
  • ligne 1 : pour les fonction de base de l'Arduino ;
  • ligne 2 : pour les fonction réseau ;
  • ligne 3 : pour le type String des chaînes de caractères ;
  • ligne 4 : pour la bibliothèque JSON d'écriture / lecture des chaînes JSON ;
  • lignes 8-9 : adresse Mac de l'Arduino. Mettez votre propre adresse Mac ;
  • ligne 10 : idem sous forme de chaîne de caractères ;
  • ligne 12 : adresse IP de l'Arduino. Mettez votre propre adresse IP ;
  • ligne 14 : idem sous forme de chaîne de caractères ;
  • ligne 16 : description de l'Arduino ;
  • ligne 18 : le port du serveur de l'Arduino ;
  • ligne 20 : le serveur de l'Arduino ;
  • ligne 22 : l'adresse IP du serveur d'enregistrement. C'est l'adresse IP locale du PC auquel vous avez relié l'Arduino, normalement 192.168.2.1 ;
  • ligne 24 : port du service d'enregistrement des Arduinos ;
  • ligne 26 : le client Arduino du service d'enregistrement ;
  • ligne 29 : la fonction [setup] d'initialisation de l'Arduino ;
  • ligne 33 : la carte réseau de l'Arduino est initialisée ;
  • lignes 35-36 : on logue la mémoire disponible au démarrage de l'application ;
  • ligne 35 : on notera la notation F(chaîne). Cela met la chaîne de caractères dans la mémoire Flash de l'Arduino. Ainsi celle-ci n'est pas placée dans la même mémoire que les autres variables du programme. Cela contribue à libérer de la mémoire pour ces dernières ;
  • lignes 95-100 : la fonction freeRam rend le nombre d'octets disponibles dans la mémoire. Cette fonction a été trouvée sur internet. Au départ, on a environ 1100 octets disponibles sur un Arduino de type " uno " ou " duemilanove ". En-deça de 600 octets le programme " plante ". Il faudra appeler régulièrement cette fonction dans votre code pour voir comment évolue la mémoire ;
  • ligne 40 : la boucle infinie exécutée par l'Arduino ;
  • lignes 44-67 : ce code est exécuté tant que l'Arduino n'a pas réussi à s'enregistrer auprès du serveur d'enregistrement de la couche [DAO] ;
  • ligne 47 : on essaie de se connecter. Les paramètres sont les suivants :
  • l'adresse du client Arduino de la ligne 26,
  • l'adresse IP du serveur d'enregistrement,
  • le port du service d'enregistrement ;
  • ligne 91 : notez la façon dont on se connecte à un serveur ;
  • ligne 48 : lorsqu'on est là, c'est qu'on a réussi à se connecter au serveur d'enregistrement. On rappelle que l'Arduino doit alors envoyer une ligne JSON du genre :
 
CacherSélectionnez
  • ligne 51 : cette ligne est préparée ;
  • ligne 52 : elle est envoyée au serveur d'enregistrement ;
  • ligne 59 : on ferme la connexion avec le serveur d'enregistrement ;
  • ligne 68 : l'enregistrement est terminé. Maintenant l'Arduino va exécuter les commandes que va lui envoyer la couche [DAO]. Pour cela, on crée un serveur ;
  • ligne 75 : un serveur est lancé sur le port 102 de l'Arduino ;
  • lignes 81-84 : dans une boucle infinie, vous allez traiter les commandes envoyées au serveur.

IV-B-2. Les

Nous allons tester cette première mouture du code de l'Arduino. On va vérifier qu'il s'enregistre bien auprès du serveur d'enregistrement qui opère sur le port 100 de la machine hôte.

Tout d'abord, vérifiez votre réseau local. Il doit être le suivant :

Image non disponible

Ensuite, chargez dans l'IDE Arduino, le programme [arduino_1.ino] que vous trouverez dans le dossier [support] du TP :

Image non disponible

Téléversez-le sur l'Arduino, puis faites afficher la console de logs (Ctrl-M) :

Image non disponible

Toutes les secondes, l'Arduino essaie de se connecter au serveur d'enregistrement qui n'existe pas encore. Nous allons en créer un.

Sous Eclipse, importez le projet Maven [Serveur Tcp générique] du dossier [support] :

Image non disponible

Ce projet Maven crée un serveur générique sur un port de la machine hôte qu'on lui passe en paramètre. Ce serveur affiche sur la console toutes les commandes qu'il reçoit. Nous allons le lancer sur le port 100 de la machine hôte, là où doit opérer le serveur d'enregistrement des Arduinos. On va voir ainsi si l'Arduino arrive à se connecter et à envoyer la ligne de texte qui l'identifie.

Il nous faut configurer le projet Eclipse :

Image non disponible
  • en [1,2], créez une nouvelle configuration d'exécution de type [Java Application] [3] ;Image non disponible
  • en [4], sélectionnez le projet [serveurTcpGenerique] ;
  • en [5], sélectionnez sa classe principale, celle qui a la méthode [main] ;
  • en [6], donnez un nom à la configuration d'exécution que vous êtes en train de créer ;
  • dans l'onglet [Arguments] [7], mettez 100 [8] pour indiquer que le serveur doit s'exécuter sur le port 100 de la machine hôte ;

Exécutez la configuration [9]. Le serveur s'exécute et affiche des logs dans la console :

 
CacherSélectionnez
  • ligne 1 : le serveur a été lancé ;
  • entre les lignes 1 et 2, un client a été détecté : l'Arduino ;
  • lignes 2-3 : deux threads sont lancés : un pour lire les demandes du client (ligne 3), l'autre pour lire les lignes tapées par l'utilisateur au clavier (ligne 2). Ici, le client n'attend pas de réponse, donc nous n'aurons pas à taper une réponse au clavier ;
  • ligne 4 : le serveur affiche la commande que l'Arduino lui a envoyée. C'est bien la ligne attendue ;
  • ligne 5 : le client (l'Arduino) a fermé sa connexion. Ceci a pour conséquence de fermer le thread lancé ligne 3 ;

Maintenant consultons la console de logs de l'Arduino :

 
CacherSélectionnez
  • ligne 1 : toutes les secondes l'Arduino essaie de se connecter au serveur d'enregistrement ;
  • ligne 2 : il y arrive ;
  • ligne 3 : la ligne qu'il a envoyée au serveur d'enregistrement ;
  • ligne 4 : l'enregistrement est terminé. L'Arduino va fermer sa connexion avec le serveur d'enregistrement ;
  • ligne 5 : le serveur qui opère sur le port 102 de l'Arduino est alors lancé. Il va exécuter toutes les commandes que la couche [DAO] va lui envoyer ;
  • ligne 6 : la mémoire disponible. On a déjà perdu 1472-1286=186 octets ;

IV-C. Exécution des commandes de la couche [DAO]

Image non disponible

Le serveur qui vient d'être lancé sur le port 102 de l'Arduino va exécuter les commandes JSON que la couche [DAO] va lui envoyer.

A lire

Dans les exemples de l'IDE Arduino :

  • le code du serveur web [Ethernet / Webserver] ;
  • le code de l'exemple [aJson / Examples / MultiLevelParsing] ;

IV-C-1. Le code

Le traitement des commandes envoyées à l'Arduino pourrait ressembler à ce qui suit (cf while ligne 81 page  ):

 
CacherSélectionnez

1 : Ecrire le code complet de l'Arduino. Vous pouvez suivre l'ossature proposée ou bien opter pour votre propre solution qui devra respecter les spécifications.

Note : vous trouverez le code précédent dans le dossier [support du TP] :

Image non disponible

IV-C-2. de la couche [Arduino]

Pour tester la couche [Arduino], il faut lui envoyer des commandes JSON et voir comment elles sont traitées. On pourra procéder comme suit :

  • mettez en place le serveur Java qui va permettre l'enregistrement de l'Arduino (voir page , paragraphe ) ;

Vérifiez votre réseau local. Il doit être le suivant :

Image non disponible

Téléversez votre programme sur l'Arduino, puis faites afficher la console de logs (Ctrl-M) :

Image non disponible

Ci-dessus, l'Arduino s'est enregistré auprès du serveur d'enregistrement. Il attend désormais des commandes JSON sur le port 102 de l'Arduino.

Sous Eclipse, importez le projet Maven [Client Tcp générique] du dossier [support] :

Image non disponible

Ce projet Maven crée un client générique TCP pour une machine distante et un port qu'on lui passe en paramètres. Ce client permet d'envoyer des lignes de texte à la machine distante et affiche ce que celle-ci renvoie. Nous allons le connecter au port 102 de l'Arduino.

Il nous faut configurer le projet Eclipse :

Image non disponible
  • en [1,2], créez une nouvelle configuration d'exécution de type [Java Application] [3] ;Image non disponible
  • en [4], sélectionnez le projet [clientTcpGenerique] ;
  • en [5], sélectionnez sa classe principale, celle qui a la méthode [main] ;
  • en [6], donnez un nom à la configuration d'exécution que vous êtes en train de créer ;
  • dans l'onglet [Arguments] [7], mettez IPArduino 102 [8] où IPArduino est l'adresse IP de votre Arduino. Cela va connecter le client générique au port 102 de l'Arduino. C'est là qu'il attend les commandes JSON ;

Exécutez la configuration [9]. Si le client générique arrive à se connecter à l'Arduino, il affiche la chose suivante sur la console [1] :

Image non disponible

Maintenant dans la console, tapez la commande suivante qui fait clignoter la led de la pin n° 8 :

 
CacherSélectionnez

La led doit clignoter 10 fois et l'Arduino doit renvoyer la réponse JSON suivante :

 
CacherSélectionnez

qui indique que la commande a été exécutée correctement.

Sur la console de l'Arduino, des logs affichent l'échange qui vient d'avoir lieu :

 
CacherSélectionnez

Exécutez les commandes JSON que vous trouverez dans le dossier [support] du TP :

Image non disponible

Vous y trouverez les trois commandes attendues par l'Arduino ainsi qu'un lot de commandes erronées. Pour ces dernières, l'Arduino doit renvoyer un code d'erreur significatif de l'erreur faite. Pour chaque commande, consultez la console de logs de l'Arduino.

Nous avons terminé la programmation des Arduinos. Nous n'y reviendrons plus. Nous allons passer maintenant à la construction du serveur de l'application.


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 Serge Tahé. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.