LOCODUINO

Aide
Forum de discussion
Dépôt GIT Locoduino
Flux RSS

mardi 19 mars 2024

Visiteurs connectés : 80

Piloter son Arduino avec son navigateur web et Node.js (1)

.
Par : bobyAndCo

DIFFICULTÉ :

Pour piloter votre Arduino, vous pouvez utiliser des boutons, des interrupteurs ou encore des potentiomètres. Ils font d’ailleurs partie de tous les bons kits de démarrage.

JPEG - 60.6 kio

Mais vous pouvez aussi rêver d’interfaces graphiques riches et esthétiques avec lesquelles vous pourriez commander votre Arduino depuis votre ordinateur, votre tablette ou encore votre téléphone portable. C’est par exemple le cas d’un TCO qui vous permettrait de commander tous les aiguillages de votre réseau ou de manettes pour piloter vos locomotives.

PNG - 477.2 kio

<

Processing est l’une des alternatives pour réaliser des interfaces graphiques dont la programmation s’apparente à celle de l’Arduino. Son utilisation se fait en lignes de code et repose sur Java.

Mais ce que je vous propose ici, c’est de recourir aux outils de création graphique du web qui sont particulièrement conçus pour produire facilement des contenus graphiques très esthétiques. Par ailleurs, il existe une multitude de bibliothèques qui vous offrent des contenus déjà créés, permettant de simplifier grandement le travail. Vous connaissez tous les glyphicons de Bootstrap sans savoir peut-être que ceux-ci proviennent de bibliothèques : plus d’infos sur les glyphicons

L’application de pilotage de locomotives que j’ai déjà présentée sur Locoduino (copie d’écran ci-dessus) n’utilise que des bibliothèques graphiques. A aucun moment je n’ai utilisé le moindre outil de dessin.

JPEG - 11.3 kio

Et Node.js dans tout cela ?

Eh bien, c’est Node qui, installé sur votre ordinateur (ou tout ordinateur en réseau), va servir d’interface réseau entre la page web que vous aurez créé avec ses boutons et potentiomètres et la ou les cartes Arduino que vous souhaitez piloter. Notez que Node fonctionne sur Mac, Windows et Linux.

PNG - 227.9 kio

Node va-t-il m’obliger à ajouter un shield Ethernet sur mon Arduino ?

Non ! Node peut communiquer avec vos Arduino via le port série. A partir de là, votre Arduino équipé par exemple d’une carte CAN pourra relayer les messages à d’autres Arduino également équipés en CAN.

Mais au fait, c’est quoi Node ?

Tenter de définir Node en quelques lignes est impossible. Wikipédia nous donne la définition suivante : « une plate-forme logicielle libre et événementielle en JavaScript orientée vers les applications réseau qui doivent pouvoir monter en charge »

En réalité, Node offre côté serveur un environnement qui utilise le JavaScript et permet grâce à de très nombreuses bibliothèques de faire tourner des applications qui communiquent en réseau. Des serveurs web, mais pas que…

Par conséquent Node est une façon de développer une interface Web dans un serveur qui commande directement votre Arduino.

Pourquoi Node est-il autant plébiscité ?

Node est simple, puissant et rapide. C’est un environnement de bas niveau comme peut l’être le langage C par exemple. Node.js utilise le moteur d’exécution ultrarapide V8 de Google Chrome. Node s’est ainsi imposé sur des sites aussi célèbres que PayPal, Groupon ou Linkedln pour n’en citer que quelques uns.

Chez PayPal, on considère que Node c’est un tiers de lignes de code en moins, deux fois plus de requêtes traitées par seconde et la réduction d’un tiers du temps de réponse moyen.

Mais dans le contexte qui nous intéresse ici, à savoir, piloter un Arduino à partir d’un navigateur web, on va voir que son point fort est bien la simplicité. A peine une quarantaine de lignes de codes, programmées pratiquement une fois pour toute, quelque soit l’évolution de notre interface graphique ou les nouvelles pages que nous allons créer.

Avertissement : Node nécessite de travailler à l’intérieur du terminal en lignes de commandes. Cela demande une certaine connaissance de l’informatique. Néanmoins, une fois que votre serveur sera installé, vous n’aurez plus à y revenir. Par ailleurs, si vous êtes bien attentif et un peu motivé vous ne devriez pas rencontrer de difficultés particulières. Suivez précisément les consignes qui vous sont données.

Sous Windows, cela s’appelle l’invite de commande :

JPEG - 23.7 kio

Sous Mac OS X ou Linux, cela s’appelle Terminal :

JPEG - 31.5 kio

Installer Node.js

Pour l’installation de Node, je vous renvoie au site OpenClassRooms qui décrit tout ceci de manière claire et facile.

Vous y trouverez, en fonction de votre système :

  • Où le télécharger.
  • Comment l’installer.
  • Comment tester qu’il fonctionne.

Pour commencer rapidement, nous allons reprendre les exemples d’OpenClassRooms. Avec n’importe quel éditeur de texte, vous allez créer un fichier en copiant le code suivant :

var http = require('http');
var server = http.createServer(function(req, res) {
  res.writeHead(200);
  res.end('Salut Locoduino !');
});
server.listen(8080);
console.log("Server Ok");

Ensuite, vous allez l’enregistrer au premier niveau de votre session. Pour Linux ou Mac, ça se passe dans le répertoire « user », au même niveau que le dossier « node_modules » (pas dedans). Pour Windows, il s’agit de « c :\Utilisateurs\VotreNom », ou « c :\Users\VotreNom » à partir de l’invite de commande, et le répertoire « node_modules » n’existe pas encore. Nommez le nouveau fichier « startNode.js ». Maintenant, dans le terminal, vous allez taper « node startNode.js ». Dans mon cas, sur mon ordinateur qui s’appelle Christophe, voici le message qui s’affiche :

PNG - 9.6 kio

Si tout c’est bien déroulé, vous allez ensuite avoir le message suivant :

PNG - 18.9 kio

Important : Pour ouvrir le terminal sous Windows, allez chercher Node dans vos programmes, puis développez avec la flèche à droite pour obtenir les différentes options (comme le montre la figure ci-dessous) et sélectionnez Node.js command prompt. L’autre solution est de n’importe où taper une fois sur la touche ’Windows’ à gauche de la barre espace pour ouvrir le menu ’Démarrer’, et sans rien sélectionner taper directement ’node’. Toutes les applications dont le nom commence par ’node’ s’afficheront, il suffira de lancer la bonne ! Une fois dans le terminal, pour récupérer l’invite de commande, il suffit de taper le raccourci clavier CTRL + C. Pour fermer le terminal, et donc sortir du programme Node, il suffit de taper exit suivi de la touche Entrée (Return).

Dans votre navigateur, entrez http://localhost:8080 comme url. Vous devriez voir apparaître le texte : Salut Locoduino !

Nous venons de créer un serveur web qui « écoute » sur le port 8080 et qui, quand on l’interroge, retourne un header 200 qui signifie « communication établie » et un texte qui s’affiche dans la page « Salut Locoduino ».

J’ai envie de dire, le plus dur est fait ! Nous allons maintenant faire évoluer le code exécuté par Node. Notez à la première ligne du code l’expression require('http'). C’est en quelque sorte l’équivalent de include en C. On demande à l’application de charger une bibliothèque particulière (pour Node, cela s’appelle un module). Ici, le module http qui fournit tout un certain nombre de fonctions. Nous allons utiliser d’autres modules pour simplifier la rédaction de notre code.

Pour qu’un module soit utilisable par Node, il devra avoir été chargé au moins une fois sur votre ordinateur. Pour ce faire, on tape dans la fenêtre du terminal npm install puis le nom du module. Ici, nous allons installer le module socket.io dont nous allons avoir besoin. Soit :

npm install socket.io.

Une petite précision concernant les installations de modules sur Mac. Il se peut que l’installation ne se soit pas bien déroulée simplement parce que vous ne disposez pas avec votre session des droits suffisants. Pour Linux ou Mac, il vous faudra alors taper sudo puis npm install socket.io soit en entier et sur une ligne :

sudo npm install socket.io.

Il vous sera alors demandé d’entrer le password d’administrateur et si celui-ci est correct, l’installation se poursuivra normalement. Pour Windows, la fenêtre de demande de confirmation d’accès administrateur s’affichera et vous n’aurez qu’à valider.

Le module socket.io va nous permettre de créer une communication synchrone et permanente avec le serveur. Ainsi, il vous sera possible d’envoyer des ordres à votre Arduino, mais cela nous permettra aussi de voir dans votre page web les messages que l’Arduino va retourner via la fonction Serial.print (ou Serial.println).

Nous allons en profiter pour installer deux autres modules dont nous allons avoir besoin. Un pour la manipulation de fichiers sur disque qui s’appelle fs et l’autre serialport qui va servir à envoyer les données par le port série à l’Arduino.

Nous allons également avoir besoin de modules pour la gestion des différentes pages web que nous allons créer. Ce sont les modules path et url.

Dans la fenêtre du terminal, nous allons donc taper :

npm install fs puis
npm install serialport puis
npm install path et enfin
npm install url.

A chaque installation vous verrez peut-être des lignes s’afficher telles que :

JPEG - 19.5 kio

Vous pouvez ensuite vérifier que les modules sont présents dans le dossier « node_modules ».

Vous allez maintenant placer tous les fichiers téléchargeables ici :

archive1

dans le répertoire où se trouve le dossier « node_modules », là où vous avez déjà placé « startNode.js ».

Avant d’aller plus loin, vous allez devoir modifier le fichier « serialport.js » qui est situé à l’intérieur des dossiers suivants :
node_modules -> serialport -> lib -> serialport.js.
Ligne 32, vous allez entrez baudRate: 115200 au lieu de 9600 comme actuellement.
Enregistrez et fermez ce fichier.

Ouvrez dans l’IDE d’Arduino le sketch « power1.ino » et téléversez le dans votre Arduino.

Au passage, notez le port série auquel est connecté votre Arduino.
Dans le fichier « arduino.js », la première ligne indique :
var usbserial = '/dev/cu.usbmodem1451';
Si le port série de votre Arduino ne coincide pas exactement avec cette ligne, alors changez le nom du port série dans cette ligne. Par exemple, sous Windows, si le module Arduino utilise le port COM4, vous aurez à changer cette ligne pour :
var usbserial = 'COM4';

Dans la fenêtre de votre terminal, vous allez entrer « node arduino.js ». Le message Communication serie Arduino 115200 bauds : Ok vous indique que Node a réussi à communiquer avec la carte. Sinon, vérifiez la connexion de la carte au port USB.

ALLUMER OU ÉTEINDRE LA LED DE VOTRE ARDUINO A PARTIR DE VOTRE NAVIGATEUR

Dans votre navigateur, vous allez entrer l’url : http://localhost:8080/power1.html

Sur la page qui apparaît, quand vous cliquez sur le bouton « on », la LED de la carte doit s’allumer et inversement quand vous cliquez sur le bouton « off ».

La ligne de logs sous les boutons affiche les messages retournés par l’Arduino. Ici 1 ou 0 selon que la LED est allumée ou éteinte.

PNG - 30.4 kio

Regardons tout d’abord le code de l’Arduino :

/*
 * Eteindre ou allumer la LED_BUILTIN d'un Arduino en fonction du message reçu
 * d'un navigateur web par l'intermédiaire de Node.js.
 * Christophe BOBILLE juin 2017
 */

void process(unsigned char inChar) {
  switch (inChar) {
    case 48:
      digitalWrite(LED_BUILTIN, LOW);
      Serial.print("0");
      break;
    case 49:
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.print("1");
      break;
    default:
      Serial.print("error");
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  while (Serial.available()) {
     unsigned char inChar = (unsigned char)Serial.read();
     process(inChar);
  }
}

Dans le loop, la boucle while (Serial.available()) ligne 28 attend que quelque chose soit présent sur le port série. Quand c’est le cas, le caractère reçu est stocké dans la variable inChar. Je ne parle bien que d’un seul caractère, ce qui va être largement suffisant pour l’instant. Puis la fonction void process(unsigned char inChar) est appelée avec en paramètre le caractère reçu.

Dans cette fonction process, j’utilise un switch qui est beaucoup plus rapide et beaucoup plus clair quand vous souhaitez traiter un nombre important de cas. Si le caractère reçu est 48 alors on éteint la LED, si c’est 49, on l’allume. Et comme dans tout swich qui se respecte, je prévois tous les autres cas avec default qui signifie que si le message reçu ne correspond à rien de ce qui est attendu on retourne un message « error ».

Pourquoi case 48 ou case 49 dans le switch alors que nous verrons par la suite que ce sont les caractères « 0 » ou « 1 » qui vont être envoyés. C’est que dans la variable inChar, c’est la valeur ASCII du caractère que je récupère et non la valeur du caractère. Ce qui m’arrange beaucoup car il y a 127 codes ASCII pour 127 caractères. Un seul caractère me permet donc d’avoir un codage en 7 bits (127 possibilités différentes). En décimal, avec 1 caractère je ne couvre que la plage 0 à 9 puis il me faut 2 caractères pour 10 à 99 ce qui reste encore inférieur à mes 127 possibilités précédentes.

L’Arduino ne peut utiliser que les 127 premiers caractère de la table ASCII et ne connaît pas ce que l’on appelle la table ASCII étendue qui comprend en plus et entre autres les caractères accentués.

Mais j’aurais tout aussi bien pu écrire :

switch (inChar) {
    case '0':
      digitalWrite(LED_BUILTIN, LOW);
      Serial.print("0");
      break;
    case '1':
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.print("1");
      break;
    default:
      Serial.print("error");
  }

’0’ ou ’1’ entre simple quote sont la représentation du caractère. En effet char ’0’ est équivalent à char 48. Par contre "0" ou "1" entre double quote n’auraient pas fonctionné car ils représentent des chaines de caractères (string). Retenez qu’avec Arduino (et les langages C ou C++) un caractère s"écrit ’A’ alors qu’une chaîne s’écrit "A" même si elle n’a qu’un caractère.

Concernant le code JavaScript « arduino.js » qui sert à faire fonctionner notre application sur Node, je ne m’y attarderai pas. En effet, vous pouvez le considérer comme une bibliothèque sans savoir ce qu’il y a dedans. Aucune modification ne sera nécessaire pour tous les exemples que nous aborderons et bien probablement tout ce que vous voudrez créer par la suite. Mais je répondrai volontiers à tous ceux qui souhaiteraient avoir des informations complémentaires.

Comme indiqué plus haut, vous devrez tout de même régler un paramètre à la ligne 1 de ce fichier en entrant votre port série spécifique. Pour mon Uno ou mon Mega sur Mac, ce réglage est : var usbserial = '/dev/cu.usbmodem1451';. Sur Windows, cette variable sera du type var usbserial = 'COM3'; ou COM4...

var usbserial = '/dev/cu.usbmodem1451'; // Pour mon UNO et mon MEGA
//var usbserial = '/dev/cu.usbserial-AL02VFGY'; // Pour mon NANO

var http = require('http');
var fs = require('fs');
var path = require("path");
var url = require("url");

// Gestion des pages HTML
function sendError(errCode, errString, response) {
  response.writeHead(errCode, {"Content-Type": "text/plain"});
  response.write(errString + "\n");
  response.end();
  return;
}

function sendFile(err, file, response) {
  if(err) return sendError(500, err, response);
  response.writeHead(200);
  response.write(file, "binary");
  response.end();
}

function getFile(exists, response, localpath) {
  if(!exists) return sendError(404, '404 Not Found', response);
  fs.readFile(localpath, "binary",
   function(err, file){ sendFile(err, file, response);});
}

function getFilename(request, response) {
  var urlpath = url.parse(request.url).pathname; 
  var localpath = path.join(process.cwd(), urlpath); 
  fs.exists(localpath, function(result) { getFile(result, response, localpath)});
}

var server = http.createServer(getFilename);

// -- socket.io --
// Chargement
var io = require('socket.io').listen(server);

// -- SerialPort --
// Chargement
var SerialPort = require('serialport');
var arduino = new SerialPort(usbserial, { autoOpen: false });

/************ IMPORTANT ********
Pour fonctionner correctement, le fichier 'serialport' @ Users/node_modules/serialport/lib/serialport.js
à été modifié à la ligne 32
baudRate: 115200,

La communication série dans les sketches arduino doit être paramètrés à 115200 bauds : Serial.begin(115200);  
*/


// Overture du port serie
arduino.open(function (err) {
  if (err) {
    return console.log('Error opening port: ', err.message);
  }
  else {
    console.log ("Communication serie Arduino 115200 bauds : Ok")
  }
});


// Requetes
io.sockets.on('connection', function (socket) {
	// Message à la connexion
  console.log('Connexion socket : Ok');
  socket.emit('message', 'Connexion : Ok');
    // Le serveur reçoit un message" du navigateur    
    socket.on('message', function (msg) {
    	//console.log(msg);
      socket.emit('message', 'Veuillez patienter !');
      arduino.write(msg, function (err) {
		  if (err) {
		  	io.sockets.emit('message', err.message);
		  	return console.log('Error: ', err.message);
		  }
		});
	});
});

arduino.on('data', function (data) {
  let buf = new Buffer(data);
  io.sockets.emit('message', buf.toString('ascii'));
  console.log(buf.toString('ascii'));
  //console.log(buf);
});

server.listen(8080);
console.log("Serveur : Ok");

Voyons maintenant le premier fichier HTML, power1.html correspondant à notre première application. Elle est très simple et contient deux boutons qui servent à allumer ou éteindre la LED de la carte reliée à la sortie 13 (LED_BUILTIN).

<!DOCTYPE html>
<html>
        <head>
            <meta charset="utf-8" />
            <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
            <script src="./socket.io/socket.io.js"></script>
            <script>
                //$(document).ready(function() {
                $(function() {	
                            var socket = io.connect('http://localhost:8080');
                            socket.on('message', function(message) {
                                $('#logs').html(message);
                            });
                
                            $('#btn_on').click(function () {
                                socket.emit('message', '1');
                            });
                
                            $('#btn_off').click(function () {
                                socket.emit('message', '0');
                            });

                            // Initialisation
                            socket.emit('message', '0');
                });
            </script>
        </head>

        <body>
            <h1>Communication avec Arduino !</h1>
            <table width="100%" border="1">
              <tr>
                <td><input type="button" value="On" id="btn_on" /></td>
                <td><input type="button" value="Off" id="btn_off" /></td>
              </tr>
            </table>
            <p>Logs : <span id="logs"></span></p>
        </body>
</html>

Information pratique. Pour avoir le rendu en temps réel du code HTML que vous rédigez, utilisez un éditeur on-line (et gratuit) comme celui de Mozilla qui est vraiment très bien. https://thimble.mozilla.org/fr/

A partir de la page d’accueil, cliquez sur créer un nouveau projet.

Un fichier HTML se structure autour de 2 balises principales, <head> jusqu’à </head> et <body> jusqu’à </body>. Dans le body se trouve le code de la partie visible de la page alors que dans le head se trouvent les « utilitaires ».

Dans le body, j’ai mis un texte entre balises <h1>Communication avec Arduino !</h1> qui va lui donner un aspect gros caractères en gras. Ensuite, j’ai créé un tableau entre les balises <table> et </table>. Je vous conseil de procéder ainsi surtout si vous n’êtes pas familier avec le HTML. Le tableau va vous aider considérablement à réaliser la mise en page de tous vos éléments graphiques. A ce tableau j’ai donné les propriétés width="100%" qui fait qu’il occupe toute la largeur de la page et border="1" qui place une bordure de 1 pixel autour. Pas très jolie je vous l’accorde mais qui nous permet pour l’instant de mieux repérer nos objets dans la page.

Un tableau HTML est toujours constitué d’au moins 1 série de balises <tr> </tr> qui permettent de créer des lignes au tableau. Ensuite, on créé les colonnes du tableau avec les balises <td> </td>.

Ici nous n’avons 1 ligne et 2 colonnes. Dans la première colonne, j’ai placé le code pour 1 bouton : <td><input type="button" value="On" id="btn_on" /></td>.

<input type="button" /> désigne un objet servant à recevoir une information « input » et que le type de l’objet est un bouton « type="button" ». « Value » est le texte apparaissant dans le bouton. Enfin, id="btn_on" est une information très importante. Cela sert à identifier de manière unique cet objet dans la page grâce à son « id ». Ici, c’est moi qui ai choisi le nom « btn_on ». Cela aurait pu être tout autre chose mais ne doit pas porter le même id qu’un autre objet de la page.

Dans la seconde colonne du tableau, j’ai un autre bouton : <input type="button" value="Off" id="btn_off" /> qui se distingue du précédent par son texte et aussi par son id="btn_off" qui précise bien je crois ce que fait le bouton.

Pour finir sur la partie affichage de cette page, on trouve en bas une zone de paragraphe entre <p> et </p> avec un texte « Logs : » est une zone dans laquelle viendra s’afficher entre <span> et </span> le message renvoyé par la fonction Serial.print de l’Arduino. De la même façon, vous remarquez que j’ai donné in « id » à cette zone : id="logs".

Dans le <head> je trouve un lien : <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> qui va charger une bibliothèque JavaScript externe très puissante nommée Jquery. Elle est chargée par internet.

La seconde bibliothèque : <script src="./socket.io/socket.io.js"></script> est aussi externe mais présente dans le dossier des modules de Node. Elle sert à la communication avec Node.

Enfin, une troisième balise <script> </script>. Ici, le code est interne à notre page car il est spécifique à notre application.

J’ai mis la première ligne en commentaire //$(document).ready(function() { car en Jquery ça veut dire exactement la même chose que $(function() { mais c’est plus explicite. Cela indique que le code sera exécuté quand la page HTML sera chargée (ready).

var socket = io.connect('http://localhost:8080'); sert à créer une instance pour la connexion avec Node. C’est un objet (au sens informatique) stocké dans une variable à laquelle j’ai donné le nom socket.

L’objet socket hérite d’un certain nombre de fonction dont .on(‘message’ qui se déclenche quand la page HTML reçoit un message du serveur Node. $('#logs') avec Jquery fait référence à la zone dont on parlait un peu plus haut. Celle à laquelle on a donné l’id=logs. $('#logs').html(message); indique d’écrire dans la zone « logs » le message qui sera reçu de Node, qui l’aura lui même reçu de l’Arduino.

Les lignes suivantes sont assez similaires dans leur compréhension. $('#btn_on').click indique un click sur le bouton ayant pour id « btn_on ».

socket.emit('message', '1'); appelle la fonction « emit » dont l’objet socket a hérité. C’est ici le second paramètre de la fonction qui nous intéresse, la valeur « 1 ».

De la même manière, le code suivant :

$('#btn_off').click(function () {
socket.emit('message', '0'); 
});

indique que quand on clique sur le bouton ayant pour id btn_off, alors on va envoyer un message dont le contenu est « 0 ».

Notez bien que les valeurs « 0 » ou « 1 » envoyées par le message auraient pu être toutes autres, « a » ou « b » par exemple. Simplement, nous avons vu dans le code de l’Arduino que quand celui-ci reçoit le message « 1 » la carte allume la diode, et elle l’éteint si elle reçoit le message « 0 ». Tout ceci est donc purement conventionnel.

Si vous ouvrez la page web dans votre navigateur avec l’url : http://localhost:8080/power1.html, vous devez donc voir s’allumer ou s’éteindre la LED selon que vous cliquerez sur on ou sur off.

Dans votre navigateur, lancez maintenant la page : http://localhost:8080/power2.html

PNG - 39.1 kio

Les boutons sont remplacés par des images mais quand on clique dessus, les effets sur l’Arduino sont les mêmes.

Regardons le code de cette page. Dans le <head>, on a ajouté un lien externe :

<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

Il s’agit ici d’une bibliothèque graphique dans laquelle je vais puiser les icônes dont j’ai envie pour ma page. Vous avez ici : http://getbootstrap.com/components/ un aperçu des icônes disponibles.

<body>
            <h1>Communication avec Arduino !</h1>
            <table width="100%" border="0">
               <tr>
                <td><span id="btn_off" class="glyphicon glyphicon-off btn_red"></span></td>
                <td><span id="btn_on" class="glyphicon glyphicon-off btn_green"></span></td>
              </tr>
            </table>
            <p>Logs : <span id="logs"></span></p>
</body>

Dans mes colonnes <td>, j’ai remplacé les boutons standards du HTML par des icônes et le curseur de la souris change au survol de ces icônes (cursor:pointer ;). Pour ce faire, j’ai créé deux divisions dans la page avec <span> et comme toute à l’heure, les id de ces <span> restent btn_on et btn_off.

Mais j’ai surtout ajouté des « class ». En fait, 3 classes par bouton. Les « class » glyphicon et glyphicon-off qui vont chercher dans la bibliothèque externe l’icône des boutons et les « class » btn_red et btn_green que j’ai créées dans le header entre les balises <style> et </style>. Ces classes déterminent, outre la couleur (red ou green) la taille (font-size:48px) et la modification de l’aspect du pointeur (cursor:pointer ;) au survol.

<style>
              html {
                  margin-left:20px;
              }
              .btn_red {
                  color: red;
                  font-size:48px;
                  cursor:pointer;
              }
              .btn_green {
                  color: green;
                  font-size:48px;
                  cursor:pointer;
              }
</style>

Tout le reste du code et en particulier le JavaScript est identique. Voici donc une évolution purement cosmétique avec par exemple un « margin-left:20px ; » appliqué au html qui décale la page du bord droit de 20 pixels.

html {
	margin-left:20px;
}

La page : http://localhost:8080/power3.html apporte un résultat plus ergonomique. Il n’y a plus qu’un seul bouton dont la couleur change en fonction de l’état de la LED de l’Arduino. Plus besoin non plus de ligne de logs puisque la couleur suffit à nous donner l’information "on" ou "off".

PNG - 34.8 kio

Ici, contrairement à la page 2, la différence graphique est obtenue essentiellement par le JavaScript et non le style. On a supprimé un bouton en supprimant une colonne du tableau. Il ne reste que celui dont la « class » est « btn_red ». Le bouton sera donc rouge au chargement de la page (initialisation).

A l’intérieur de la balise <script> </script>, sous le commentaire // Initialisation on trouve une nouvelle ligne. La déclaration et l’initialisation d’une variable globale « status » à « 0 ». Puisqu’il n’y a plus qu’un seul bouton, la variable status enregistre l’état du bouton.

<script>
   //$(document).ready(function() {
   $(function() {
					

	// Ouverture d'un socket avec le serveur
	var socket = io.connect('http://localhost:8080');

	// En cas de réception d'un message du serveur
	socket.on('message', function(message) {
		status = message;
		if(status == "1") {
			$("#btn").removeClass("btn_red");
			$("#btn").addClass("btn_green");
		}
		else {
			$("#btn").removeClass("btn_green");
			$("#btn").addClass("btn_red");
		}
	});
	    			
					
	// Sur click
	$('#btn').click(function () {
	if(status == "0") {
		status = "1";
	}
	else {
		status = "0";
	}
	socketEmit(status);
	}); 

	var socketEmit = function(status) {
	        var statusAscii = String.fromCharCode(status);
	         socket.emit('message', statusAscii);
	}

	// Initialisation
	var status = "0";
	socketEmit(status);

    });
</script>

Pour la même raison, nous n’avons plus qu’une seule fonction « $('#btn').click(function () » qui modifie le statut du bouton à 1 s’il était à 0 et inversement. La fonction appelle non plus directement « socket.emit(’message’, value) ; » comme avant mais une fonction nouvelle « socketEmit (status) » que l’on retrouve juste en dessous. La chose la plus importante et nouvelle dans cette fonction est la ligne : var value = String.fromCharCode(status) ; Nous n’allons plus envoyer à l’Arduino le caractère « 0 » ou « 1 » mais grâce à « String.fromCharCode » directement le code ASCII 1 ou 0.

Nous verrons dans le fichier « power2.ino » que le switch est aussi modifié puisque c’est bien le code ASCII « 0 » ou « 1 » qui est reçu.

void process(unsigned char inChar) {
  switch (inChar) {
    case 0:
      digitalWrite(LED_BUILTIN, LOW);
      Serial.print("0");
      break;
    case 1:
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.print("1");
      break;
    default:
      Serial.print("error");
  }
}

Bien évidemment, c’est le fichier « power2.ino » qu’il faut téléverser sur l’Arduino pour fonctionner avec ce fichier « power3.html ». Pour cela, il faut déjà libérer le port qui est utilisé par Node tout simplement en fermant le terminal ou en tapant ^C (control/C) ; une fois le téléversement terminé, vous pourrez rouvrir le terminal et entrer "node arduino.js" pour essayer ce nouvel exemple.

Dans le <body>, l’id de la <span> devient id="btn" puisqu’il n’y a plus qu’un bouton. Dans le JavaScript, dans la fonction sur click, la variable status change de valeur et c’est cette nouvelle valeur qui est envoyée à l’Arduino via Node.

// En cas de réception d'un message du serveur
socket.on('message', function(message) {
	status = message;
	if(status == "1") {
		$("#btn").removeClass("btn_red");
		$("#btn").addClass("btn_green");
	}
	else {
		$("#btn").removeClass("btn_green");
		$("#btn").addClass("btn_red");
	}
});

Plus haut dans le JavaScript, à la réception du message retourné par l’Arduino, la variable status prend la valeur retournée : status = message;. Ce qui est surtout intéressant, c’est que l’on va ici modifier les class par programmation. En effet, si la LED est allumée if(status == "1"), on va supprimer la class btn_red $("#btn").removeClass("btn_red"); et ajouter la class btn_green » $("#btn").addClass("btn_green"); ce qui va avoir pour conséquence de donner au bouton la couleur verte.

Puis en dessus dans le JavaScript, l’effet inverse, $("#btn").removeClass("btn_green"); et $("#btn").addClass("btn_red"); si la LED est éteinte.

Nous avons donc modifié le style (css) de la page par programmation en fonction de la valeur de variables.

A la fin de cette expérimentation, n’oubliez pas d’arrêter le serveur node, soit en tapant ^C dans la fenêtre du Terminal, soit en quittant l’application Terminal, ce qui affichera la message suivant :

JPEG - 22.6 kio

Voilà pour ce premier article, surement le plus difficile. Dans l’article suivant, nous nous intéresserons aux potentiomètres et ensuite encore, au pilotage d’un servomoteur pour terminer par une application très complète : Une manette de pilotage de locomotives avec DCC++.

N’hésitez pas à me poser toutes vos questions et j’essayerai d’y répondre au mieux.

67 Messages

Réagissez à « Piloter son Arduino avec son navigateur web et Node.js (1) »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Programmation »

Le monde des objets (1)

Le monde des objets (2)

Le monde des objets (3)

Le monde des objets (4)

Les pointeurs (1)

Les pointeurs (2)

Les Timers (I)

Les Timers (II)

Les Timers (III)

Les Timers (IV)

Les Timers (V)

Bien utiliser l’IDE d’Arduino (1)

Bien utiliser l’IDE d’Arduino (2)

Comment gérer le temps dans un programme ?

La programmation, qu’est ce que c’est

Types, constantes et variables

Installation de l’IDE Arduino

Répéter des instructions : les boucles

Les interruptions (1)

Instructions conditionnelles : le if ... else

Instructions conditionnelles : le switch ... case

Comment concevoir rationnellement votre système

Comment gérer l’aléatoire ?

Calculer avec l’Arduino (1)

Calculer avec l’Arduino (2)

Les structures

Systèmes de numération

Les fonctions

Trois façons de déclarer des constantes

Transcription d’un programme simple en programmation objet

Ces tableaux qui peuvent nous simplifier le développement Arduino

Les chaînes de caractères

Trucs, astuces et choses à ne pas faire !

Processing pour nos trains

Arduino : toute première fois !

Démarrer en Processing (1)

TCOs en Processing (1)

TCOs en Processing (2)

L’assembleur (1)

L’assembleur (2)

L’assembleur (3)

L’assembleur (4)

L’assembleur (5)

L’assembleur (6)

L’assembleur (7)

L’assembleur (8)

L’assembleur (9)

Les derniers articles

L’assembleur (9)


Christian

L’assembleur (8)


Christian

L’assembleur (7)


Christian

L’assembleur (6)


Christian

L’assembleur (5)


Christian

L’assembleur (4)


Christian

L’assembleur (3)


Christian

L’assembleur (2)


Christian

L’assembleur (1)


Christian

TCOs en Processing (2)


Pierre59

Les articles les plus lus

Les Timers (I)

Les interruptions (1)

Instructions conditionnelles : le if ... else

Ces tableaux qui peuvent nous simplifier le développement Arduino

Comment gérer le temps dans un programme ?

Bien utiliser l’IDE d’Arduino (1)

Les structures

Les Timers (II)

Calculer avec l’Arduino (1)

Instructions conditionnelles : le switch ... case