Petit point sur l’avancement en attendant l’arrivée des dernières pièces:
J’ai reçu la batterie NiMH 12V 4000 mAh et son chargeur. Pour des raisons esthétiques, j’ai refait le packaging grâce à de la gaine thermo noire. De plus, j’ai raccourci les fils car ils étaient un peu trop longs. J’ai fixé la batterie grâce à des bandes velcros.
J’ai acheté 2 boutons anti-vandalisme (aluminium) pour pouvoir mettre sous tension la carte arduino d’une part, mais aussi la carte contrôleur des moteurs. Ainsi, je pourrais travailler sur la programmation de la carte arduino sans forcément alimenter la partie moteur.
Par ailleurs, j’ai réalisé l’ensemble du câblage. J’ai essayé de faire quelque chose de propre grâce à de la gaine thermo.
Côté programmation, j’ai remis au propre le code côté arduino, et j’ai réalisé une petite interface côté Java. Sur cette interface, on retrouve un bouton pour la connexion série, un bouton pour l’activation du futur mode automatique, un bouton permettant d’activer le mode manuel, un bouton permettant d’activer la reco vocale, et enfin en dessous, un système de monitoring des futurs capteurs (gauche / droit / avant pour les 3 capteurs IR et un système radar pour le scan du capteur ultrason). Pour les jauges et le radar, j’utilise une API proposant des composants swing Steelseries.
Comme évoqué dans un article précédent, le viliv S5 est équipé d’une puce GPS Sirf Star3. J’ai donc voulu voir ce que la bête avait dans le ventre, en ayant en tête une future commande du genre « Quel temps fera t-il demain Daryl? » et bim Daryl va voir sur le net la météo concernant la ville où il se trouve…
J’ai donc cherché a little sur le net et… le GPS peut être directement attaqué sur son port COM… Cela ne vous rappelle pas quelque chose?
Seule la ligne GPGGA nous intéresse. En effet elle contient les données GPS. En faisant une petite recherche sur le net, on apprend que le flux est défini selon la norme NME 0183, soit:
Height over geoid, minus height over ellipsoid, with unit
Checksum
Dans mon code Java, je filtre donc sur les lignes GPGGA, je split sur « , » et dans un premier temps je récupère la 6ième valeur (0 si pas de fix GPS, 1 si fix satellite OK)
Ensuite, si on a un fix, on découpe le reste pour faire ressortir:
la latitude
la lat direction Nord ou Sud
la longitude
la long direction Est ou Ouest
Bon à savoir: les latitudes et longitudes ne sont pas directement exploitables, elles sont au format 4825.1857 or la plupart des applications utilisent le format du style 48° 25.1857′
Pour cela j’ai récupéré une petite class qui prend en entrée toute la ligne GPGGA et renvoie des informations bien formatées.
Bon, le résultat sur le viliv S5 est un peu décevant car il y a un petit blackout entre le moment où l’on se connecte au port, et le moment où l’on obtient les 1ères données (1min approx), du coup on ne sait pas trop ce que fait le programme. De plus la réception du viliv S5 n’est pas extraordinaire en intérieur. Je peine à fixer les satellites à 1m de la fenêtre. Quand je vois cela, je me dis que le GPS de l’iphone est vraiment pas mal…
Je viens d’effectuer une avancée majeure dans mon projet: La réalisation de l’interface permettant la communication entre le PC (le viliv S5 dans mon cas) et l’arduino, via le port série (USB).
En effet, comme évoqué dans le billet listant mes objectifs et contraintes, je me suis donné pour but de développer Daryl avec mon langage de prédilection, c’est-à-dire Java. Or l’arduino n’est pas directement programmable en Java, mais en C/C++ uniquement.
Je me suis donc orienté vers l’architecture suivante: Intelligence de Daryl côté PC via une application Java, partie gestion des moteurs et senseurs côté arduino.
Après pas mal de recherche, j’ai constaté qu’il était possible de faire communiquer le PC et l’arduino via le port série (USB), et donc d’envoyer ou recevoir des données depuis l’arduino (afin de récupérer les données des senseurs et/ou de donner des ordres aux moteurs).
J’ai trouvé une API Java rxtx (http://rxtx.qbang.org/wiki/index.php/Main_Page) permettant d’établir une connexion avec le port COM série de l’arduino puis la communication avec celui-ci en envoyant/recevant des données. On trouve facilement des exemples simples sur le net expliquant comment envoyer/recevoir des données au travers du port série.
Par exemple, je peux envoyer TOTO côté PC et je constate que j’ai bien reçu TOTO côté arduino. Les exemples sont sympas mais ils n’expliquent pas comment dire à l’arduino « donne la valeur 255 pour la pin de la LED ». Je pourrais envoyer PINLED255, mais comment lire cette information dans un flot de données constant?! Et bien c’est là tout le problème! De plus, sur ce point, il n’y a plus rien en terme exemple sur net!
J’ai donc conçu un système d’identification des trames permettant une lecture du flot de données de manière à pouvoir l’interpréter par la suite. J’ai mis en place ce système côté montant comme descendant (PC et arduino).
Exemple: Si je veux allumer ma LED côté arduino (donc valeur 255) alors j’écris les caractères suivants sous forme de bytes au travers du flux ~L0255$
L’arduino étant en écoute sur le port série, il va donc dépiler la stream byte par byte et par conséquent:
Si l’arduino constate l’arrivée du flag ~ , alors il sait qu’une nouvelle donnée interprétable va arriver. On enregistre donc les prochains bytes dans un tableau.
Lorsque l’arduino constate l’arrivée du flag $ , alors il sait que la donnée est complète… et interprétable.
On va donc récupérer le flag de la commande à exécuter (ici L pour… LED) et reconstituer sa valeur (en effet à ce moment précis, elle est encore sous forme de CHAR).
Donc pour résumer: on lit séquentiellement le flux et on interpréte les données grâce aux flags de début (~) et de fin ($).
On fait strictement la même manipulation côté PC pour recevoir les données de l’arduino 😉
Voili voilo, je ne vous cache pas que je me suis arraché les cheveux quelques soirées (couché à 6h du mat) sur ce point.
Comme vous pourrez le voir dans la vidéo, j’ai pu:
Allumer/éteindre une LED (~L0000$ ou ~L0255$)
Récupérer la valeur d’un potentiomètre côté interface (~P0000$ à ~P1023$)
Envoyer à l’arduino la valeur angulaire pour le servo moteur (~S0000$ à ~S0180$)
Obtenir un niveau de réponse excellent
Exécuter cet exploit depuis le viliv S5
NB: Vous pourrez constater sur l’interface, les deux panels affichant le flot de données (input) en provenance de l’arduino, et le flot de données (output) envoyé vers l’arduino.
Côté Java les sources sont organisées de cette manière:
J’ai pensé qu’il serait sympa que Daryl me prévienne lorsque ses batteries sont déchargées. J’ai donc cherché comment récupérer le statut de la batterie d’un portable (pour rappel le cerveau de Daryl se trouvera sur un micro PC avec batterie).
En cherchant un peu, j’ai découvert que le statut de la batterie était uniquement accessible via la DLL KERNEL32 native de Windows.
Il existe bien une API appellée JNI (Java Native Interface) qui permet à du code Java d’appeler ou d’être appelé par du code natif. Il n’existe pas réellement de bibliothèque à télécharger pour faire du JNI puisque cette couche de programmation est fournie par défaut dans le JDK. Seulement cette couche de programmation est compliquée à mettre en place.
Je me suis donc tourné vers l’API JNA (Java Native Access) qui permet d’accéder à du code natif sans faire appel explicitement à la couche de programmation JNI. Le développement nécessite une interface Java pour décrire le prototype les fonctions et les structures contenues dans le code natif à appeler.