Robot raspberry pi node js

Un robot connecté avec NodeJS et Raspberry Pi

NodeJS est un langage de développement orienté serveur, qui permet de coder en Javascript dans un environnement léger et performant. Propulsé par l'interpréteur V8 de Google, il offre un large choix de librairies bas niveau, et bénéficie d'une communauté activé, qui publie régulièrement de nombreux modules additionnels.

Le (ou la) Raspberry Pi est un ordinateur de la taille d'une carte de crédit, embarquant un processeur 4 coeurs et 1Gb de RAM. Il exécute une distribution linux dédiée, et profite de nombreuses ressources logicielles et matérielles.

Comment exploiter le langage nodeJS sur une carte RaspberryPi dans le cadre de la fabrication d'un robot connecté ? Ce billet est une synthèse de la présentation proposée par Nicolas Giraud le 20 octobre 2015 dans le cadre des événements de la Tech Amiénoise.

Robot raspberry pi node js

Objectifs

Nous souhaitons réaliser un robot capable de se déplacer dans une pièce, de filmer et diffuser les images, le tout pilotable via internet. Le robot sera construit autour d'une carte Raspberry Pi connectée en Wifi, il exploitera une caméra, et pilotera deux servo moteurs via une carte arduino. Il devra respecter les contraintes suivantes :

  • Disposer d'une caméra embarquée
  • Etre accessible via Internet
  • Fonctionner sur piles ou batterie
  • Exploiter un maximum de briques open source
  • Ne pas dépasser 150€ de budget

Raspberry Pi

Une carte Raspberry Pi 2

Raspberry Pi est une petite carte électronique (de la taille d’une carte de credit) embarquant un ordinateur complet (Single Board Computer). Facile d’accès, peu onéreux et propulsé par une communauté très active, les ressources logicielles et pédagogiques autour de cette carte ne manquent pas. Ses principales caractéristiques :

  • Processeur ARM Dual Core
  • 1Gb de RAM
  • 4 ports USB
  • 1 port Ethernet
  • 1 port HDMI
  • 1 port CSI (Camera Serial Interface) pour exploiter une caméra
  • 1 port DSI (Display Serial Interface) pour exploiter un écran LCD
  • Fonctionne sous Linux ou Windows 10
  • Alimentation 5V (via un chargeur de tablette ou une batterie mobile)

NodeJS

le logo nodejs

NodeJS est une solution de développement serveur fondée sur l’interpréteur de Javascript V8 édité par Google. En plus des fonctionnalités de base du JS, il propose nativement de nombreuses librairies “bas niveau”, qui permettent d’accéder à la couche réseau, au système de fichiers, à la gestion de processus… 

De nombreux modules additionnels sont proposés par la communauté, via l’utilitaire NPM (Node Package Manager). Malgré sa relative jeunesse, le riche écosystème disponible permet de rivaliser avec les environnements les plus aboutis, en terme de performances et de temps de travail.

Configuration du Raspberry Pi

Système d'exploitation

Télécharger et installer l'image Raspbian (Jessie) sur une carte MicroSD 4Gb classe 10. Les images officielles sont disponibles à l'adresse https://www.raspberrypi.org/downloads/raspbian/ NB :Une carte de classe 10 garantit des débits suffisants et une durée de vie prolongée.

Brancher un clavier et une souris et un adaptateur wifi sur les ports USB, un écran sur le port HDMI.

Prévoir une alimentation 5V qui puisse fournir 1A au moins. Un chargeur de smartphone ou de tablette devrait faire l'affaire. Evitez les chargeurs low cost.

Premier démarrage

Lors du premier démarrage, l'écran suivant s'affiche. Cet utilitaire permet de configurer quelques paramètres de base. 

Capture d'écran de l'utilitaire raspi-config. Il se lance automatiquement au premier démarrage.

Utilisez cet écran pour régler les paramètres suivants, puis redémarrez le raspberry pi.

  • Configuration du clavier
  • Démarrage par défaut sur le bureau
  • Activation de la camera, du SSH, de l'I2C

Configuration du réseau

Dans un terminal, demandez l'édition du fichier de configuration des interfaces réseau :

sudo leafpad /etc/network/interfaces

Forcer l'obtention d'une adresse IP fixe sur le réseau local via le Wifi. Choisir une adresse compatibles avec la plage autorisée par le routeur (ex :192.168.1.120, 192.168.0.120) 

auto lo
iface lo inet loopback

auto eth0
allow-hotplug eth0
iface eth0 inet manual

auto wlan0
allow-hotplug wlan0
#iface wlan0 inet manual
iface wlan0 inet static
address 192.168.1.120
netmask 255.255.255.0
gateway 192.168.1.254
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

auto wlan1
allow-hotplug wlan1
iface wlan1 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Configuration du WIFI

Dans un terminal, demandez l'édition du fichier de configuration du Wifi :

sudo lefpad /etc/wpa_supplicant/wpa_supplicant.conf

Fixer le mode d'authentification, le nom du réseau et la clé :

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid="TNCAP66A0B5"
psk="C466B3644A"
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
auth_alg=OPEN
}

Puis redémarrez

sudo reboot

Mises à jour

Obtenir et installer les dernières mises à jour du système, installer quelques outils de développement.

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential

Utilitaires I2C

Installer les outils I2C officiels, ils permettent d'exploiter la communication I2C via un terminal

sudo apt-get install i2c-tools

Demander à charger les modules i2c au démarrage

sudo leafpad /etc/modules

Ajouter les lignes relatives aux modules i2c

snd-bcm2835
i2c-bcm2708
i2c-dev

Redémarrer

sudo reboot

Connexion SSH

A partir de maintenant, votre raspberry pi peut être démarré sans écran ni clavier. Il est accessible via le réseau et le protocole SSH. A l'aide d'un client SSH (WinSCP, putty, Bivise SSH Client), établir une connexion vers le raspberry pi avec les paramètres suivants:

  • Adresse : 192.168.1.120
  • Port : 22
  • Login : pi
  • Mot de passe : raspberry

NodeJS sur Raspberry Pi

Installation de NodeJS

Pour obtenir une version de nodejs fonctionnelle sur raspberry pi et Raspbian Jessie, suivre les indications fournies par node-arm.herokuapp.com.

Télécharger les sources

wget http://node-arm.herokuapp.com/node_latest_armhf.deb

Installer nodejs

sudo dpkg -i node_latest_armhf.deb

Vérifier le bon déroulement de l'installation en demandant le numéro de version de nodejs

node -v
v4.2.1

Hello World

Créer un dossier attribué à l'utilisateur "pi"

sudo mkdir /var/www
sudo chown pi /var/www

Créer le fichier /var/www/hello.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(80);
console.log('Server running');

Lancer le serveur

sudo node /var/www/hello.js

Lancement du serveur nodejs

Accéder au serveur via un navigateur, le texte "Hello world" est correctement envoyé par le serveur.

Réponse du serveur dans un navigateur

Exploiter la camera du Raspberry pi

Module caméra officiel pour raspberry pi

Un capteur CMOS dédié au raspberry pi est disponible dans le commerce. Il se connecte au port CSI (Camera Serial Interface) du raspberry pi, et permet de prendre des photos ou de filmer en haute définition. 2 Utilitaires permettent d'exploiter cette camera : 

Il est possible d'exploiter ces utilitaires directement dans nodeJS.

Capturer une image avec NodeJS

Créer le fichier /var/www/camera.js

// on doit accéder au réseau
var http = require('http');

// on doit exécuter des commandes system
var child_process = require('child_process');

// on doit accéder aux fichiers
var fs = require('fs');

// on créer un serveur qui répondra aux requêtes
http.createServer(function (req, res) {

  // la commande à exécuter
  var cmd = '/opt/vc/bin/raspistill --output /var/www/image.jpg --timeout 100 --nopreview';

  // on lance la commande
  child_process.exec(cmd, function(error, stdout, stderr){

    if(error)
    {
      // on affiche l'erreur dans la console
      console.log(error);

      // on alerte le visiteur
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('execution impossible');
      return;
    }

    fs.readFile('/var/www/image.jpg', function(error, data){

      if(error)
      {
        console.log(error);
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('lecture impossible');
        return;
      }

      res.writeHead(200, {'Content-Type': 'image/jpeg'});
      res.end(data);
    });
  });
}).listen(80);

console.log('Server running');

Lancer le serveur

sudo node /var/www/camera.js

lancer le serveur camera

Tester le serveur dans un navigateur

Test du serveur camera dans un navigateur

Créer un flux MJPG

Pour obtenir simplement une vidéo plutot qu'une image, on utilise le "format" mjpg. Il s'agit d'une suite d'images JPG affichées successivement par le navigateur. La majorité des navigateurs supporte nativement cette mode d'affichage. L'utilitaire raspistill est en outre capable de prendre des photos en continu.

Créer un dossier en RAM

Pour préserver la carte SD et éviter d'écrire continuellement dessus, on créer un dossier dans la mémoire vive.

Créer un dossier à la racine :

sudo mkdir /ram

Définir une partition en RAM pour ce dossier

tmpfs /ram tmpfs nodev,nosuid,size=1M 0 0

Monter cette partition

sudo mount -a

Capturer un flux mjpg avec NodeJS

Créer le fichier /var/www/mjpg.js

var http = require('http');
var CameraStream = require('./cameraStream');

// gestionnaire de camera raspistill
var camera = new CameraStream();
camera.doStart(320,240,6);

// on créer un serveur qui répondra (res) aux requêtes (req)
http.createServer(function(req, res){

  // entêtes HTTP indiquant un contenu non-fini
  res.writeHead(200, {
    'Cache-Control': 'no-cache',
    'Cache-Control': 'private',
    'Pragma': 'no-cache',
    'Content-Type': 'multipart/x-mixed-replace; boundary=myboundary',
  });

  // envoyer les images à mesure qu'elles arrivent
  var consume = function(buffer)
  {
    res.write("--myboundary\r\n");
    res.write("Content-Type: image/jpeg\r\n");
    res.write("Content-Length: " + buffer.length + "\r\n");
    res.write("\r\n");
    res.write(buffer,'binary');
    res.write("\r\n");
  }

  // tenter d'envoyer chaque image dès qu'elle arrive
  camera.on('image', consume);

  // la connexion a été coupée
  res.connection.on('close', function(){
      camera.removeListener('image', consume);
  });

}).listen(8080, function(){
  console.log('mjpeg server started');
});

La gestion de la capture des images est assurée par la librairie cameraStream.js. Pour tester ce script, vous devez télécharger cette librairie et la placer dans le dossier /var/www.

Lancer le serveur

sudo node /var/www/mjpg.js

lancer le serveur mjpg

Tester dans un navigateur

Tester le serveur mjpg dans un navigateur

Matériel & Composants

La plupart des composants du robot provient d'Europe, des USA et de Chine. En octobre 2015, le montant total de cette liste avoisine les 150€, hors frais de port.

Raspberrypi2

Raspberry Pi 2

Héberge le serveur nodeJS

fr.rs-online.com

42€

Module caméra officiel pour raspberry pi

Module Camera

Capteur Full HD, se connecte au port CSI du Raspberry Pi

fr.rs-online.com

23€

Adaptateur wifi

Adaptateur WIFI

Pas tous compatibles, privilégier les officiels

fr.rs-online.com

10€

Arduino nano

Arduino Nano, Pro Mini, Pro Trinket...

Microcontrolleur 5V pour piloter les moteurs

adafruit.com

10€

 

Arduino screwshield

Carte d'accueil

Pour connecter plus facilement l'arduino

aliexpress.com

5€

Servo

Servomoteur 360°

Modifiés pour tourner en continu

adafruit.com

2 x 10€

Battery holder

Boîtier à piles

Pour 6 piles AA

aliexpress.com

5€

Piles

6 piles NiMh

2500mAh ou +, privilégier les marques

En grande surface : 25€

Buck converter

Convertisseur de tension

Pour abaisser la tension du pack de piles à 5V

aliexpress.com

5€

Jumpers

Jumpers

câbles de prototypage, longueur, couleur et connectique variées.

disponible partout

 

Cablage

Alimenter le Raspberry Pi

Raspberry pi power

Attention : Il est impératif d'appliquer une tension d'EXACTEMENT 5V aux bornes GPIO du raspberry Pi, car le seul circuit de protection/régulation de la carte se trouve au niveau de la prise micro USB. Ce schema montre simplement les broches à utiliser pour alimenter la carte.

VCC (5V) : GPIO 6

GND (0V) : GPIO 4

Alimenter l'Arduino

Nano power

GND (0V) : GND

VCC (5 - 12V) : VIN

Alimenter les servos

Servo power

Les servos fonctionneront sans problème de 4.8 à 6V.

Raspberry Pi et Arduino en I2C

Nano raspberry pi

SDA : GPIO 3 > A4

SCL : GPIO 5 > A5

GND : GPIO 9 > GND

Pilloter les servos avec Arduino

Nano servos

Servo L > D9

Servo R > D10

Communication I2C entre Raspberry Pi et Arduino

Le raspberry Pi ne propose pas de sorties dites "PWM" indispensables pour piloter les servo moteurs. Cette tâche est donc déléguée à une carte Arduino. Voici un exemple simple de communication I2C Maître-Esclave entre un raspberry pi et un arduino.

Câblage I2C

communication I2C maître-esclave entre raspberry pi et arduino

Code Arduino

Dans cet exemple, l'arduino est configuré comme esclave I2C. Il attend d'être contacté à l'adresse 0x04, et pilote la led intégrée à la sortie 13 en fonction des instructions qu'il reçoit.

#include 
#define ADDRESS 0x04
void setup()
{
  pinMode(13, OUTPUT);
  Wire.begin(ADDRESS);
  Wire.onReceive(onRecieve);
}

void onRecieve(int len)
{
  while(Wire.available())
  {
    int data = Wire.read();

    if(data==1)
    {
      digitalWrite(13, HIGH);
    }
    else
    {
      digitalWrite(13, LOW);
    }
  }
}
void loop()
{
  delay(100);
}

Détecter les esclaves I2C

Dans un temrinal, lancer la commande suivante

sudo i2cdetect -y 1

Qui dévoilera la liste des appareils I2C connectés au port 1 du raspberry pi

Détection des périphériques I2C

L'arduino est bien visible à l'adresse 0x04

Lancer des commandes I2C

Allumer la diode de l'arduino :

sudo i2cset -y 1 0x04 0x01

Eteindre la led:

sudo i2cset -y 1 0x04 0x00

Design du châssis

A l'aide d'un logiciel de dessin vectoriel (inkscape est disponible gratuitement et en open source), dessiner chaque face du robot, en pensant aux encoches pour l'assemblage, et en prévoyant la place pour chaque composant (piles, raspberry pi, arduino, etc...) Utilisez une même couleur pour toutes les faces de chaque composant et reportez la sur chaque face du robot.

Implantation des composant sur le chassis

Quelques points de reflexion :

  • Prévoir la place pour chaque composant
  • Prévoir les trous de fixation des composants
  • Prévoir les passages de cables
  • Gérer le centre de gravité du robot
  • Prévoir un design facilitant les montages/démontages successifs

Découpe laser

Une fois le design validé, préparer un fichier vectoriel adapté aux machines à commande numérique. Dans le cadre de la réalisation de ce robot, une découpe laser sera utilisée.

Fichier vectoriel pour la découpe laser

  • Penser à vectorier toutes les lignes
  • Penser à dédoubler les lignes
  • Penser à espacer suffisament chaque pièce (de quelques mm)

Montage du robot

Une fois les pièces découpées, il ne reste qu'à visser/coller/ajuster les composants.

Montage du robot

Le robot terminé

Voici à quoi ressemble notre robot, complètement assemblé et équipé.

Robot connecté avec raspberry pi et nodejs

Interface de pilotage du robot

Nous créeons un simple fichier HTML qui propose un écran de connexion, permettant à l'utilisateur de configurer la taille et la qualité de l'image. Cette page HTML communique en temps réel avec le raspberry pi via l'API Websocket des navigateurs récents. L'ensemble des fichiers est disponible dans le dernier chapitre.

Interface

Questions & Réponses

L'utilisation de l'I2C entre arduino et raspberry pi est-elle sans risque ?

Dans le cadre de ce robot, le Raspberry Pi s'adresse à l'Arduino, la tension maximale qui circule sur l'I2C est donc celle du raspberry pi, soit 3.3V. Par chance, l'arduino -qui fonctionne sous 5V- interprète le 3.3V comme un état haut. Le bus fonctionne donc normalement et sans dager, uniquement dans ce sens.

6 piles AA suffisent-elles pour alimenter le raspberry pi ?

Nous utilisons ici 6 piles rechargeables NIMH d'une capacité de 2500mAh. La tension nominales de ces piles est de 1.2V, le pack complet délivre donc 7.2V, ramenés à 5V par le convertisseur de tension. On peut calculer approximativement l'autonomie de la façon suivante :

En série, les tensions s'ajoutent, pas les capacités, on a donc une batterie de 7.2V capable de délivrer 2500 mA pendant une heure. En abaissant la tension a 5V, on multiplie la capacité par 7.2 / 5 = 1.4. La capacité du pack de batterie atteint donc 2500 x 1.44 = 3600 mAh sous 5V. En considérant une consommation globale de 600mA (mesurée grossièrement) sous 5V, le robot pourra en théorie fonctionner 3600 / 600 = 6 heures.

Peut on utiliser une version du Raspberry Pi plus ancienne ?

L'intérêt du Raspberry pi dans le cadre de ce robot est double : Il propose un port CSI pour piloter la camera, et il permet d'exécuter du code complexe et gourmand, tel que celui d'un petit serveur web. Les versions précédentes de la carte sont sensiblement identiques, à l'exception de la quantité de mémoire vive, et de la gestion de l'USB. Il est donc tout a fait possible de réaliser ce robot avec une version précédente. 

La qualité de l'image peut-elle être améliorée ?

La qualité d'une image influe directement sur son poids, et dans notre cas, sur le débit sortant de l'adaptateur Wifi. Malheureusement, ces petits adaptateurs sont rarement performants. Il faudrait passer par une solution réseau plus aboutie, ethernet ou routeur WIFI, qui impacterait directement la consommation électrique.

Ressources et liens

Les fichiers réalisés dans cette présentation :

Les liens relatifs à la présentation :

  • www.raspberrypi.org Le site officiel de la communauté, propose de nombreuses ressources pédagogiques
  • www.nodejs.org Le site officiel du projet nodejs, propose les packets d'installation et une documentation exhaustive
  • www.npmjs.org La plus grosse collection de packets additionnels pour nodejs
  • fr.rs-online.com Un magasin d'électronique proposant de nombreux produits de l'écosystème Raspberry pi
  • www.adafruit.com Un magasin d'électronique pour les hackers, le DIY. Il propose de nombreus tutos et librairies
  • node-arm.herokuapp.com Propose les dernières versions de nodejs compilées pour raspberry pi
  • www.fritzing.org Un logiciel de conception électronique qui peremt de produire des schémas
  • www.arduino.cc Le site de la communauté arduino
  • inkscape.org Logiciel de dessin vectoriel open source
  • lamachinerie.org Coworking, Fablab, et découpe laser à Amiens
  • latechamienoise.com Association destinée à fédérer les acteurs du numérique amiénois

Nicolas Giraud

Développeur web, chef de projet technique. PHP, NodeJS, OSHW, Raspberry Pi, Arduino ...

 

Makers