Développement IoT à base d'Orange Pi, Arduino (Firmata), Nodejs, Blynk et Johnny-Five • Domotique et objets connectés à faire soi-même

nwapltev7jf5fokkugtl-9146509

Dans ce tutoriel, je vous propose de combiner Nodejs/Johnny-Five avec Blynk pour piloter à distance le GPIO de l’Arduino/Firmata depuis un smartphone ou une tablette et faire remonter des mesures (température et pression atmosphérique d’un BMP180 en I2C). Dans l’article précédent, nous avons vu qu’il était très facile d’utiliser un Arduino (on choisira le modèle en fonction du nombre d’E/S nécessaires) pour remplacer le GPIO d’origine de l’Orange Pi. On s’affranchit ainsi du manque (actuel) de librairies permettant d’exploiter le GPIO. Ce projet fonctionnera à l’identique sur n’importe quel Raspberry Pi. L’intérêt est moindre, Johnny-Five étant capable d’exploiter le GPIO de tous les modèles de Raspberry Pi.

Architecture du projet

Le schéma ci-dessous présente l’architecture du système que nous allons mettre en place :

  • On installera le firmware Firmata sur un Arduino Nano v3
  • L’Arduino/Firmata sera relié à l’aide d’un câble USB à un Orange Pi Lite (version WiFi, 512Mo de Ram, Armbian server).
  • Le script écrit en Javascript est interprété (exécuté) par Node.js.
    • Ce script utilise la librairie Blynk pour communiquer avec le serveur local Blynk (ou le serveur officiel, c’est égal).
      • Il publie les mesures sur les broches virtuelles V0 (température) et V1 (pression atmosphérique).
      • Il reçoit le changement d’état du GPIO permettant d’allumer ou d’éteindre la Led
    • Ce script utilise la librairie Johnny-Five pour piloter le GPIO de l’Arduino/Firmata
      • L’objet Led permettra de piloter la Led sur la broche indiquée
      • L’objet Multi permettra de récupérer les mesures du BMP180 sur le bus I2C

En vidéo, voici ce que ça va donner

Un peu de lecture avant de commencer

Avant de vous lancer (surtout si vous avez loupé les épisodes précédents), voici une liste d’articles pour débuter :

Installer Node.js sur Armbian ou Raspbian

Node.js est un moteur d’exécution (runtime) qui permet de faire fonctionner des scripts Javascript sur un ordinateur ou un mini-PC (Raspberry Pi, Orange Pi…). C’est un moteur multi-plateforme, c’est à dire que le code écrit sur un environnement pourra fonctionner à l’identique (à condition que les ressources matérielles existent également) sur un autre environnement. Node.js est disponible pour Windows, macOS, Linux (x86 et ARM).

Commencez par vérifier que Node.js n’est pas déjà installé sur votre distribution

# node -v && npm -v
v5.12.0
3.8.6

Si vous obtenez un message d’erreur, installez Node.js 4.x (suffisant) ainsi que Python et Build

curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
sudo apt-get install -y build-essential python-dev nodejs

Pourquoi Johnny-Five ?

hrfbb2jmrof21ixxojbw-8276572

Johnny-Five est un projet Open Source très populaire destiné à la programmation d’objets connectés ou robotique en Javascript (page officielle). Le nom a été inspiré du personnage du film Short Circuit dont voici un petit extrait pour le plaisir de re-découvrir.

Johnny-Five ajoute une couche d’abstraction à vos projets. On utilise des objets (Led, Servo, Multi…) que l’on configure (broche, nom du capteur, position d’origine…) et des fonctions (led.blink(), servo.to(position)…).

En quelques lignes de code, vous pouvez piloter un servo moteur. Vous n’avez même pas à vous soucier du port série sur lequel l’Arduino est branché, Johnny-Five s’occupe de tout ! C’est tout simplement magique. Ca permet de considérablement simplifier le codage. Vous pouvez vous concentrer sur votre projet plutôt que de passer du temps à chercher les erreurs.

Matériel nécessaire

Installer le firmware Firmata sur l’Arduino

Le firmware Firmata permet d’accéder à toutes les fonctionnalités de l’Arduino via le port série (à l’aide d’un câble USB). Connectez la carte à l’ordinateur et ouvrez l’IDE Arduino. Dans le menu des examples, vous trouverez un sous-menu nommé Firmata. Sélectionnez le firmware qui correspond à votre besoin. Le plus courant est d’utiliser le firmware Standard. Il existe également une version Plus qui permet de communiquer avec des périphériques par liaison série UART, USART ou SoftwareSerial. Téléversez simplement le firmware sur la carte. C’est prêt ! Pour personnaliser le firmware, lisez cet article.

fqf4ugocbdig9obbk9mw-8937508

Projet Blynk

Lancez Blynk sur votre smartphone ou tablette. Si vous disposez d’un serveur local, connectez vous à celui-ci en modifiant la source comme indiqué sur la copie d’écran ci-dessous.

x5aqmu05o9dxqobhvxqk-7199426

Créez un nouveau projet puis ajoutez 2 jauges. Choisissez le Virtual Pin V0 pour la température et le V1 pour la pression atmosphérique.

Placez ensuite un bouton. Choisissez le Pin V2. Il existe 2 modes de fonctionnement pour le bouton Blynk :

  • Push : l’état ON est maintenu durant tout le temps ou l’on reste sur le bouton. Lorsqu’on relâche le bouton, il repasse à OFF.
  • Switch : c’est un interrupteur normal. Il passe à ON lorsqu’on le touche. Il faut appuyer de nouveau dessus pour éteindre.

Choisissez le mode Switch.

Ajoutez un second bouton (V3) pour tester le mode Pulse de Johnny-Five. Vous avez reçu un email avec le Token du projet lorsqu’il a été créé. Si vous avez perdu le Token, retournez sur la page de configuration du projet (bouton en forme d’hexagone) puis appuyez sur E-Mail.

hpbijbgpfrktl141ztui-6651716

Installation des plugins Node.js

Pour ce projet, nous aurons besoin d’installer les packages Blynk (pour Nodejs) et Johnny-Five. Exécutez cette commande pour les installer. La commande sudo est préférable sur les systèmes Unix. L’option -g permet d’installer glabalement les packages, permettant ainsi de les utiliser dans tous les scripts. Les dépendances nécessaires aux packages seront automatiquement installées en même temps (la magie npm).

npm install -g blynk-library johnny-five

Code Javascript du projet (Node.js)

Votre environnement doit être prêt avant de continuer. Connectez-vous à l’Orange Pi (ou au Raspberry Pi) en SSH (ou en direct). Créez un nouveau répertoire (nodebot) et placez vous à l’intérieur

cd ../..
mkdir nodebot && cd nodebot;

Créer un nouveau script javascript

nano j5BMP180.js

En début de script, nous allons appeler les différents librairies nécessaires :

  • Blynk : blynk-library
  • Johnny-Five
  • Events : permet d’envoyer et de recevoir des événements. C’est la force  (les puristes diront N’IMPORTE QUOI!!!) du javascript.
var Blynk = require('blynk-library');
var five = require("johnny-five");
var EventEmitter = require('events').EventEmitter;

Ensuite, nous allons créer plusieurs objets :

  • board : c’est l’objet de base qui permet d’utiliser l’API Johnny-Five, par exemple pour commander les servos, allumer les Led…
  • event : cet objet permet d’émettre et de recevoir des événements Javascripts
  • blynk : permet d’utiliser l’API Blynk
  • connector : objet contenant la connexion HTTP au serveur Blynk local
  • Vx: objects to exchange data with the Blynk server
var board = new five.Board();                   // Objet permettant l'appel à l'API J5 - Object to call J5 API
var AUTH = 'b065eb0a6e36434da42367b3fa7c3340';  // Remplacer par votre Token Blynk - Replace by your Blynk Token

var event = new EventEmitter();                 // Evenements javascript - Javascript Events
var DEBUG = true; //false;

// Setup Blynk
var blynk = new Blynk.Blynk(AUTH, options = {
  // Connecteur au serveur Blynk local - Local Blynk server connector
  connector : new Blynk.TcpClient( options = { addr:"xxx.xxx.xxx.xxx", port:8442 } )
});
var V0 = new blynk.VirtualPin(0);  // Pin virtuel temperature - Virtual Pin for temperature (BMP180)           
var V1 = new blynk.VirtualPin(1);  // Pression atmosphérique - Atmospheric pressure (BMP180)
var V2 = new blynk.VirtualPin(2);  // Bouton ON/OFF pour la Led - ON/OFF button for the led
var V3 = new blynk.VirtualPin(3);  // Start/Stop Pulse Led

var temp;                          // Contiendra la dernière mesure de température - Will store last Temperature value
var pa;                            // idem pour la PA - The same for Atm. Pressure

Il est très facile de surveiller l’état de la connexion au serveur Blynk à tout moment et “branchant” une fonction qui est déclenchée lorsqu’un événement est émis par l’objet. On peut par exemple surveiller que l’on est bien connecté (connect) au serveur, ou au contraire que l’on est déconnecté. On pourra par exemple réaliser un traitement en cas de déconnexion. Ici, nous allons simplement afficher un message lorsqu’on sera connecté au serveur, ou si le script est déconnecté.

blynk.on('connect', function() { console.log("Blynk ready."); });
blynk.on('disconnect', function() { console.log("DISCONNECT"); });

Il faut attendre que la communication avec la carte Arduino soit établie avant de pouvoir utiliser l’API de Johnny-Five. Pour cela, on va se brancher sur l’événement ready comme ceci. L’événement ready ne renvoi aucune information.

board.on("ready", function() {
  // code
  console.log("J5 Board is Ready");
})

Pour gérer la Led, on a besoin de créer un objet led. Toutes les options de l’API Led se trouvent ici. Au minimum, on doit lui indiquer la broche sur laquelle la led est branchée.

Pour pouvoir utiliser la classe pulse, il faut que la Led soit branchée sur une sortie PWM. Par exemple la 11.

var led = new five.Led(11);

Le BMP180 est rangé dans la catégorie Multi, les capteurs renvoyant plusieurs mesures. L’API est détaillée sur cette page. Au minium, on doit lui indiquer le contrôleur à utiliser (ici BMP180). Johnny-Five prend en charge les capteurs (controler) suivants. Utilisez la propriété entre parenthèse pour récupérer la mesure.

Capteur Altimètre

(altimeter)

Baromètre

(barometer)

Hygromètre

(hygrometer)

Température

(thermometer)

BMP180 X X
BMP280 X X
BME280 X X X
HTU21D X X
HIH6130 X X
MPL115A2 X X
MPL3115A2 X X X
SI7020 X X
SI7021 X X
MS5611 X X X
TH02 X X
var multi = new five.Multi({
  controller: "BMP180"
});

On peut maintenant récupérer les mesures à chaque changement (“change“). On va copier la valeur dans une variable intermédiaire.

multi.on("change", function() {
  temp = this.thermometer.celsius;  // copie la valeur de la température - Make a copy of the temperature value
  pa = this.barometer.pressure * 10 // idem pour la pression atmosphérique - Same thing for atm. pressure
});

Comment allumer et éteindre une Led avec Johnny-Five ?

Pour allumer et éteindre la Led, nous allons brancher une fonction sur l’objet event (créé au début du programme) qui sera exécutée lorsque l’événement V2 est émis. Il suffira de tester l’état d’un paramètre pour allumer ou éteindre la Led. Nous allons voir un peu plus loin comment émettre un événement. Ici, nous allons utiliser les propriétés on() et off(). Johnny-Five propose d’autres propriétés pour gérer les leds :

  • toggle : inverse l’état
  • strobe(ms, callback) : fait clignoter la led à une certaine fréquence (durée d’allumage en millisecondes). Il est possible d’arrêter le clignotement avec la fonction led.stop(). Une fonction callback peut être appelée à chaque fois que la Led est éteinte (off).
  • blink(ms, callback) : identique à strobe
  • brightness(0-255) : change la luminosité. La led doit être branchée sur une sortie compatible PWM
  • fade(brightness, ms, callback) : fait varier la luminosité du niveau actuel au niveau indiqué en un temps indiqué en ms. Une fonction callback peut être appelée à la fin de la variation. On peut stopper la fonction avec led.stop().
  • fade(animation options) : variation de luminosité animée. Voir l’API pour plus de détail
  • fadeIn(ms, callback)
  • fadeOut(ms, callback)
  • pulse(ms, callback)
  • pulse(animation options)

Les propriétés sont disponibles pour les leds simples, les Leds RGB, les matrices de leds…

event.on('V2', function(param){
  if ( param == 1 || param == true ) {
    if ( DEBUG ) { console.log("Power ON Led on (V2 Pin)"); }
    led.on();
  } else {
    if ( DEBUG ) { console.log("Power OFF Led (V2 Pin)"); }
    led.off();
  }
});

Comment envoyer régulièrement des mesures sur le serveur Blynk ?

Pour publier a intervalle régulier les mesures, nous allons utiliser la fonction javascript setInterval qui permet d’exécuter du code ou d’appeler une fonction à intervalle régulier. Elle est de la forme suivante

setInterval(function() {
  // code ou fonction - code or function
}, duration),

Par exemple, on va envoyer les mesures toutes le 2 secondes (2000 millisecondes). Blynk intègre un système de vérification des donnés mais ça ne coute rien de faire un petit test pour ne rien faire si la variable ne contient rien. En javascript, une variable vide est de type undefined. On publie sur une variable virtuelle à l’aide de la fonction write (comme sur la librairie Arduino).

setInterval(function() {
    if ( temp != undefined ) {
      if ( DEBUG ) { console.log('Temperature:', temp + ' C'); }
      V0.write(temp);
    }
    if ( pa != undefined ) {
      if ( DEBUG ) { console.log('Humidity:   ', pa + ' hPa'); }
      V1.write(pa);
    }
}, 2000);

Comment recevoir l’ordre d’allumage/extinction de la led envoyé depuis l’appli Blynk ?

Il ne reste plus qu’à émettre un événement lorsqu’on appuie sur le bouton ON/OFF depuis l’appli Blynk. On récupère un événement “write” sur l’objet V2. Il suffit ensuite d’émettre notre propre événement sur l’objet event comme ceci

event.emit("EVENT", param);

On peut passer des paramètres lorsqu’on émet l’événement. Ici, on va juste recopier la variable param qui contient l’état de la led désiré (1 ou 0). Ce qui donne

V2.on('write', function(param){
  if ( DEBUG ) { console.log("V2 ", param); }
  event.emit('V2',param);
});

Pourquoi ne pas directement appeler directement les objets Johnny-Five ?

On pourrait effectivement penser qu’il est possible d’allumer ou éteindre la led à chaque changement d’état. Comme ceci par exemple.

V2.on('write', function(param){
  if ( DEBUG ) { console.log("V2 ", param); }
  if ( param == 1 || param == true ) {
    led.on();
  } else {
    led.off();
  }
});

Seul problème, l’objet led est créé lorsque la carte (board) est prête (ready), donc lorsque le script est lancé, il n’existe pas encore lorsque Node.js créé “l’événement” V2.on. Vous aurez donc une belle erreur javascript qui ferra planter le script dès que vous appuierez sur le bouton ON/OFF !

Code complet du script javascript

Collez le code suivant dans le fichier ouvert précédemment sans oublier de modifier l’adresse IP de votre serveur Blynk local et le Token du projet.

var board = new five.Board();                   // Objet permettant l'appel à l'API J5 - Object to call J5 API
var AUTH = 'b065eb0a6e36434da42367b3fa7c3340';  // Remplacer par votre Token Blynk - Replace by your Blynk Token

var event = new EventEmitter();                 // Evenements javascript - Javascript Events
var DEBUG = true; //false;

// Setup Blynk
var blynk = new Blynk.Blynk(AUTH, options = {
  // Connecteur au serveur Blynk local - Local Blynk server connector
  connector : new Blynk.TcpClient( options = { addr:"xxx.xxx.xxx.xxx", port:8442 } )
});
var V0 = new blynk.VirtualPin(0);  // Pin virtuel temperature - Virtual Pin for temperature (BMP180)           
var V1 = new blynk.VirtualPin(1);  // Pression atmosphérique - Atmospheric pressure (BMP180)
var V2 = new blynk.VirtualPin(2);  // Bouton ON/OFF pour la Led - ON/OFF button for the led
var V3 = new blynk.VirtualPin(3);
var temp;                          // Contiendra la dernière mesure de température - Will store last Temperature value
var pa;                            // idem pour la PA - The same for Atm. Pressure

blynk.on('connect', function() { console.log("Blynk ready."); });
blynk.on('disconnect', function() { console.log("DISCONNECT"); });

board.on("ready", function() {
  console.log("Board J5 Ready ");
  var led = new five.Led(11);    // PWM 

  var multi = new five.Multi({
    controller: "BMP180",
    freq: 2000
  });
 
  multi.on("change", function() {
   temp = this.thermometer.celsius;  // copie la valeur de la température - Make a copy of the temperature value (Celsius)
   pa = this.barometer.pressure * 10 // idem pour la pression atmosphérique - Same thing for atm. pressure (hPa)
  });

  event.on('V2', function(param){
    if ( param == 1 || param == true ) {
      if ( DEBUG ) { console.log("blink led V2"); }
      led.on();
    } else {
      if ( DEBUG ) { console.log("Stop Blink Led V2"); }
      led.off();
    }
  });
  
  event.on('V3', function(param){
    if ( param == 1 || param == true ) {
      if ( DEBUG ) { console.log("Pulse led"); }
      led.pulse(500);
    } else {
      if ( DEBUG ) { console.log("Stop Pulse Led"); }
        led.stop();
        led.off();
    }
  });
});

setInterval(function() {
    if ( temp != undefined ) {
      if ( DEBUG ) { console.log('Temperature:', temp + ' C'); }
      V0.write(temp);
    }
    if ( pa != undefined ) {
      if ( DEBUG ) { console.log('Humidity:   ', pa    + ' hPa'); }
      V1.write(pa);
    }
}, 2000);

V2.on('write', function(param){
  if ( DEBUG ) { console.log("V2 ", param); }
  event.emit('V2',param);
});

V3.on('write', function(param){
  if ( DEBUG ) { console.log("V3 ", param); }
  event.emit('V3',param);
});

Test en fonctionnement

Lancez le script avec la commande node j5BMP180.js , si vous avez activé le debug, la température et la pression atmosphérique vont commencer à défiler

root@orangepilite:~/nodebot# node j5BMP180.js
Connecting to TCP: 192.168.1.24 8442
Connected
1489765605100 Device(s) /dev/ttyUSB0  
1489765605167 Connected /dev/ttyUSB0  
Authorized
Blynk ready.
1489765606738 Repl Initialized 
>> Temperature: 21.7 C
Humidity:    974.42 hPa

Tout fonctionne parfaitement. Le script s’est correctement authentifié sur le serveur Blynk local (IP 192.168.1.24, port 8442). Johnny-Five a trouvé l’Arduino/Firmata sur le port USB /dev/ttyUSB0 et il est connecté. Les mesures de température et de pression atmosphérique sont correctes et sont envoyées régulièrement au serveur Blynk local.

Vous pouvez lancer l’application Blynk sur votre smartphone ou tablette. Vous devriez avoir un écran similaire à celui-ci

Vous pouvez maintenant allumer et éteindre la Led branchée sur le GPIO 11 depuis l’application mobile et récupérer les mesures de température et de pression atmosphérique du BMP180. Mais le mieux, c’est encore une petite vidéo pour résumer tout ça.

Si ce thème vous intéresse, vous pouvez également suivre cette série d’articles sur le pilotage d’un système articulé Pan/Tilt avec un ESP8266 avec Blynk, Cayenne ou Node-RED+MQTT.

Avez-vous aimé cet article ?