Aller au contenu


Information tutoriel

  • Ajouté le: mars 24 2016 10:55
  • Date Updated: juil. 24 2016 02:58
  • Lectures: 13889
 


* * * * *
0 Notes

Introduction à Node JS sur PI

Mettre un V8 dans le raspberry PI

Posté par Path on mars 24 2016 10:55

nodejs-logo.png raspberry_pi_logo.png

 
C'est quoi Nodejs ?
 
Nodejs, c'est un portage open source en C++ du moteur d'interpretation et d'exécution javascript que l'on trouve habituellement dans les navigateurs (chrome) : le V8 de google. Nodejs permet de sortir le javascript des navigateurs pour l'exécuter sur une machine windows, mac ou linux en standalone (desktop, serveur ou embarqué). 
 
Les navigateurs étant sécurisés, par exemple, on ne peut pas accéder aux fichiers, à la ligne de commande ou écouter un port. Nodejs ajoute au javascript les fonctions  d'accès au système qui lui faisaient défaut. Nodejs suis les évolutions de la norme ECMAScript (spécifications du langaue) et est devenu une plateforme à la fois simple, léger et mature. Surtout depuis ES6. La doc de l'API exposée par NodeJS en plus du Javascript : https://nodejs.org/d...-v6.x/docs/api/
 
NodeJS est maintenant couramment utilisé dans le monde de l'IT pour des middleware, des web services temps-réel ou en full-stack (coté serveur et coté client) pour des applications web. On le voit aussi beaucoup dans le monde des objets connectés. Il arrive naturellement sur le raspberry PI pour piloter un robot. 
 
Le langage javascript n'est pas un langage simple contrairement à ce qu'on pense généralement. Ce tuto ne couvre pas le javascript. Il faudra pour cela voir de ce coté : http://javascript.de...ppez.com/cours/. C'est faux de croire que l'on connait javascript si on a affiché un bouton dans une page web. En effet le navigateur masque toute la partie interessante de javascript : sa boucle d'évènements. Le code javascript est exécuté dans un seul thread. Mais derrière tous les appels asynchrones, la mécanique du V8 est parallélisée. Mieux que des mots, la meilleure video que je connaisse pour expliquer comment fonctionne javascript.
 

 
Par exemple, hello.js

// attends 1s et affiche le texte
setTimeout (function() {
  console.log("les makers");
},1000);
console.log ("Hello");

$node hello.js (ou C:\node.exe hello.js)

hello.js affiche :
Hello
​les makers
(et pas "les makers Hello")
 
Avertissement
 
Le tuto qui suit montre comment piloter un robot avec NodeJS. Vous l'aurez compris, NodeJS devient intéressant quand on connait javascript.
 
Ce tuto pré-suppose que le raspberry est installé avec la raspbian : https://www.raspberr.../documentation/
 
Ce tuto est destiné aux débutants en robotique. Il est réalisé dans le cadre de la conception du robot Ash : http://www.robot-mak...alancing-robot/
 
Pourquoi PAS NodeJS ?
 
Javascript n'est pas un langage temps-réel.
Javascript n'est pas compilé. Il n'y a pas de vérification du code avant l'exécution.
Javascript est faiblement typé. Il demande un peu d'attention.
 
Alors, plus concrètement,
 
Pourquoi NodeJS ?

  • javascript n'attend pas

Il continue à exécuter le code pendant qu'une instruction asynchrone est en attente. Une lecture de ficher, d'un port série ou réseau. Cela le rend bien plus efficace et performant qu'un système multi-threadé.

  • javascript est un langage à évènements.

Ce n'est pas avec une librairie ou un addon. C'est au coeur du langage.

  • Les streams

L'API stream de NodeJS combine la puissance des évènements avec celle des pipes d'unix. Si vous connaissez les pipes entre les commandes unix, vous savez que c'est une aide précieuse et facile à mettre en place.

  • javascript est full stack

Un seul langage pour le serveur, pour le client et pour les middlewares orienté messages (évènements). 

 
Si on connait son langage, NodeJS est un pont facile à mettre en place entre arduino et une interface de contrôle web. Et disposer d'une interface web permet de ne rien installer sur le terminal de commande (sauf un navigateur) et il est compatible avec tous les smartphone et sur toutes les machines desktop habituels.
 
 
tutorials-9452-0-82260000-1462831177.png
 
NodeJS ouvre le raspberry (et donc le robot qui en est doté) à tout l'Internet domestique ou extérieur.
 
Enfin, Nodejs bénéficie d'une très large communauté. Il est accompagné d'un gestionnaire de packages (librairies) npm. Pour vous faire une idée, voilà ce qu'on trouve déjà concernant le port gpio chez nodejs : https://www.npmjs.com/search?q=gpio
  
  
NPM
 
Node s'install avec son gestionnaire de packages. Voir : https://docs.npmjs.com/
On se contentera de faire des npm install pour obtenir des modules. 
 
Installation de NodeJS et NPM sur Raspberry PI
 
Ajouter le repository nodesource :

sudo curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -

Cette commande va aussi  mettre à jour le catalogue.
 
NB. Adafuit mets aussi node à disposition sur un repository similaire. Avec nodesource, on a une version plus à jour. 
NB. Quand la version 8 de NodeJS sera disponible, l'url ci-dessus devra être adaptée. Voir https://github.com/nodejs/LTS/.
 
Installer nodejs :

sudo apt-get install nodejs

NB. npm (le gestionnaire de package de node) est installé automatiquement avec nodejs.
 
Vérification :

pi@raspberrypi:~ $ nodejs -v
v6.2.1
pi@raspberrypi:~ $ npm -v
3.9.3

Source : https://nodejs.org/e...x-distributions

 

Installation d'un module NPM

$npm install <nom du module>

npm va alors créer un répertoire module dans le répertoire courant. Vous devez donc vous placer à la racine de votre projet pour lancer cette commande.

 

Pour plus d'infos sur NPM : https://docs.npmjs.com/

Interface avec Arduino
 
Le plus simple est de conserver le câble USB entre le raspberry et arduino dans le montage définitif du robot. 
 
Compilation
Cela permet de compiler le code arduino sur le raspberry directement et d'uploader le programme compilé sur l'arduino directement depuis le raspberry. Voir http://www.robot-mak...ne-de-commande/
 
Communication
Pour communiquer avec arduino, on utilise toujours le câble USB.
 
Coté raspberry, on utilise le module NPM "serialport" dans une classe utilitaire qui fait l'interface avec Arduino :

Spoiler

 
On utilise cette classe comme ceci :
 

var Arduino = require('./modules/arduino.js');

 
Pour envoyer un message à arduino :

arduino.writeSerial('COMMANDE:DONNEE:DONNEE:DONNEE');

 
Pour recevoir des messages de arduino :
 

arduino.on('ready', function() {
  console.log('Arduino ready');
});

arduino.on('CONSOLE', function(data) {
  console.log('[ARDUINO CONSOLE]'+data.args);
});

arduino.on('COUNTCODER', function(data) {
  console.log('Arduino COUNT left: '+data.args[0])
  console.log('Arduino COUNT right: '+data.args[1])
  (...)
})

 
Du coté Arduino, pour écrire un message à raspberry, on utilisera simplement 

Serial.print();

Pour lire les message envoyé par raspberry, il faut les dé-sérialiser et dispatcher les commandes. Par exemple :



Spoiler

 
Alimentation
Le raspberry peut alimenter l'aduino par le port USB donc dans la limite de 500mA.
 
Note
Le montage par câble USB sera remplacé par un branchement I2C ou SPI pour des besoins plus spécifiques communication en réseau. Arduino pourra être alimenté différemment s'il a besoin de plus de 500 mA.
 
Interface avec les programmes en python
 
Par exemple, on va intercepter les valeurs qui arrivent du capteur IMU du senseHAT. Le senseHAT est fourni avec une API en python. On va appeler la librairie du senseHAT et écrire une valeur sur la sortie standard.

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sense_hat import SenseHat
import time
sense = SenseHat()
sense.set_imu_config(False, True, True)  # compass_enabled, gyro_enabled, accel_enabled
while True:
	# Get orientation from hat
	orientation = sense.get_orientation_degrees()

	roll = orientation["roll"]
	roll = round(roll, 2)
        print(roll)
	time.sleep(.005)
 

Dans NodeJS, on va utiliser le module "python-shell" pour instancier ce programme en python et lire la sortie standard.
 

var PythonShell = require('python-shell');

var pyOptions = {
  mode: 'text',
  pythonPath: '/usr/bin/python',
  pythonOptions: ['-u'],
  scriptPath: '/home/pi/SBR'//,
  //args: ['value1', 'value2', 'value3']
};

var imu = new PythonShell('imu.py', pyOptions);

imu.on('message', function(data) {
    console.log(data); // data contient une ligne de la sortie standard données par imu.py
  });
 

 
 
Interface web
 
Pour servir une page static HTML avec node, c'est très simple. On va utiliser le module "express" pour créer un mini serveur web sur le raspberry. On y ajoutera tout de suite une websocket pour obtenir des informations du robot sur la page web en mode push (à l'initiative du serveur).
 

var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);

io.on('connection', function(socket){

    socket.on('command', function(data) {
      // data contient les données envoyées depuis la page web
    });

    // Pour envoyer des données au navigateur
    io.sockets.emit("COMMAND", data);
});

// Pour servir la page static, on la place dans un répertoire dédié
app.use(express.static(__dirname + '/../static'));

server.listen(3000);

Placez une un fichier nommé index.html dans le répertoire static.
 
Pour se connecter l'interface web, il faudra se connecter à l'IP du raspberry sur le port 3000 depuis un navigateur. (http://w.x.y.z:3000/). Votre navigateur affichera le contenu html de votre index.html.
A noter, socket.io sert son client websocket au navigateur de façon transparente.
 
Votre fichier html de commande peut ressembler à ceci :

 

Sans titre.png

 

Spoiler

 

Pour plus d'infos sur la websocket : https://github.com/socketio/socket.io
Pour plus d'infos sur express : http://expressjs.com/fr/

NB. Il s'agit d'un embryon de serveur web. Mais suffisant pour les besoins de pilotage d'un robot.

 
Pour aller plus loin
 
Le V8 de google : https://fr.wikipedia...eur_JavaScript)
NodeJS : https://nodejs.org/en/about/
Liens utiles NodeJS : https://github.com/s...NodeJS-Learning
Javascript : https://developer.mo.../Web/JavaScript

Miniature(s) jointe(s)

  • Ash suite.png