29 septembre 2015
TweeterVoici venu le troisième volet de la série de billets sur l’ESP8266, celui sur la programmation ! Pour les plus avertis, le SDK est directement disponible avec makefile et touti quanti ! Dans notre cas, nous allons passer par un IDE assez populaire, celui d’Arduino. En effet, à partir de la version 1.6.4 (assez récemment donc), l’IDE Arduino permet d’ajouter facilement le support de cartes tièrces.
Pour commencer, téléchargez l' IDE Arduino sur le site officiel et installez le dans le répertoire de votre choix.
Vous trouverez tout ce qu’il faut sur le repo github du projet de support de l’ESP8266 dans l’IDE Arduino. En fonction de votre humeur joueuse ou non, je vous laisse choisir l’URL de la dernière version stable ou celle de la version staging :
Version stable : http://arduino.esp8266.com/stable/package_esp8266com_index.json
Version staging : http://arduino.esp8266.com/staging/package_esp8266com_index.json
Suivez les étapes suivantes pour configurer votre IDE :
Ajouter l’URL ci-dessus dans les préférences de l’IDE (menu Fichier/Préférences → champ "Additional Boards Manager URLs").
Via le menu Outils/Type de carte/Boards manager, accéder à l’outil qui permet d’ajouter le support de l’ESP8266
Sélectionnez l’item ESP8266 et cliquez sur le bouton Install.
Cette phase d’installation va télécharger tout ce qu’il faut pour compiler et flasher votre microcontroleur préféré !
Sélectionner le type de carte adéquat avec le menu Outils/Type de carte (Olimex MOD-WIFI-ESP8266 dans mon cas)
Sélectionner le port série qui relie votre PC à votre ESP8266 (/dev/ttyUSB0 dans mon cas).
Vous devriez être maintenant prêt à coder et flasher votre micro-controlleur.
Pour faire simple, on va partir du classique Hello World du hardware : Faire clignoter une led !
Comme une image vaut largement mieux qu’un beau discours, voici le schéma Fritzing qui illustre le montage à cabler :
Les boutons Reset et Flash (sur le GPIO0) facilitent l’upload du programme sur le micro-contrôleur. Sans ces boutons, vous devriez faire des "shunts" à la main.
Voici le programme qui suit la structure standard des programmes Arduino (fontions setup et loop) :
int ledPin = 5;
void setup() {
// Initialisation du GPIO5 en sortie
pinMode(ledPin, OUTPUT);
// Initialisation de la sortie série (pratique pour débugguer)
Serial.begin(115200);
Serial.println();
Serial.println("Starting ...");
}
void loop() {
// On allume la led
digitalWrite(ledPin, HIGH);
Serial.println("Led on ...");
// Attente de 500 ms
delay(500);
// On éteind la led
digitalWrite(ledPin, LOW);
Serial.println("Led off ...");
// Attente de 500 ms à nouveau
delay(500);
}
En appuyant sur les 2 boutons Reset et Flash et en ne relachant que le bouton Reset, votre ESP8266 est prêt à être flashé. Cliquez sur l’icône Téléverser de l’IDE Arduino et le programme est compilé puis uploadé sur votre ESP8266. Le programme démarre tout seul lorsque l’upload est terminé.
Vous pouvez utiliser le terminal série de l’IDE Arduino (en 115200) pour vérifier les sorties Led on … et Led off …
Vous me direz, c’est bien beau de faire clignoter une Led mais pour le moment, on n’a pas encore utiliser la connectivité Wifi de notre ESP8266. Au delà du faible coût, c’est quand même cette fonctionnalité qui est super intéressante sur l’ESP8266.
Notre second programme va donc être de piloter la led à travers un serveur Web embarqué dans l’ESP8266. Une simple requête HTTP nous permettra donc d’allumer ou d'éteindre notre Led.
Pour cela, direction la doc officielle de l’API ! Vous pouvez aussi vous appuyer sur ce document plutôt complet : http://neilkolban.com/tech/wp-content/uploads/2015/09/Kolbans-Book-on-the-ESP8266-September-2015.pdf
Le code du second programme est ci-dessous. Il est assez simple pour être suffisament explicite. La console série vous permettra d’obtenir l’adresse IP de votre ESP8266 au démarrage.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
// Constantes Wifi
const char* ssid = "ssid";
const char* password = "password";
// Variables globales
int ledPin = 5; // Pin de pilotage de la lod
ESP8266WebServer server(80); // Instance du serveur Web
void handleRoot() {
Serial.println("HTTP GET /");
String message = "<html><body><h1>Bienvenue sur votre ESP8266 !</h1>";
message += "<ul><li><a href='/on'>Led on</a></li>";
message += "<li><a href='/off'>Led off</a></li></ul></body></html>";
server.send(200, "text/html", message);
}
void handleLedOn() {
Serial.println("HTTP /on -> Led on");
digitalWrite(ledPin, HIGH);
server.send(200, "text/html", "<html><body><h1>Led On !</h1></html>");
}
void handleLedOff() {
Serial.println("HTTP /off -> Led off");
digitalWrite(ledPin, LOW);
server.send(200, "text/html", "<html><body><h1>Led Off !</h1></html>");
}
void handleNotFound(){
String message = "<html><body><h1>Not Found !!</h1></body></html>";
server.send(404, "text/html", message);
}
void setup() {
// Initialisation du port série (pour débugguer)
Serial.begin(115200);
Serial.println();
Serial.println("Starting ...");com
// Initialisation du GPIO5 en sortie
pinMode(ledPin, OUTPUT);
// Initialisation de la connexion Wifi
WiFi.begin(ssid, password);
Serial.println("");
// Attente de la connexion
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connecté au SSID : ");
Serial.println(ssid);
Serial.print("Adresse IP : ");
Serial.println(WiFi.localIP());
// Routage des requêtes HTTP
server.on("/", handleRoot);
server.on("/on", handleLedOn);
server.on("/off", handleLedOff);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("Serveur HTTP démarré");
}
void loop() {
server.handleClient();
}
Pour le tester, vous pouvez utiliser les commandes Curl suivantes :
curl http://<ip>
curl -X POST http://<ip>/on
curl -X POST http://<ip>/off
Voilà ! Vous avez maintenant prêt à créer votre super montage que vous avez imaginer sur Arduino … en le connectant au Web très facilement. Vous pouvez continuer en regardant tous les exemples fournis. Vous verrez que vous pourrez même faire un portail captif très facilement.
A vous de jouer maintenant !
28 juin 2015
TweeterAprès une présentation générale de l’ESP8266, voici le second billet pour vous expliquer comment cabler et flasher un ESP8266. La programmation arrivera dans le billet suivant. Soyez patient !
Le cablage peut varier selon les modèles que vous utilisez. Dans mon exemple, je vais montrer le cablage d’un modèle de chez Olimex :
Olimex fait du hardware en Open Source. On peut donc retrouver les schémas sans soucis, dont celui qui montre le design. Quelque soit votre modèle, vous devez avoir un document qui devrait vous indiquer à quoi correspond chaque Pin.
Pour le module Olimex, voici le "pinout" :
Pour le moment, 6 pins vont nous intéresser :
pin 1: 3.3V
pin 2: GND
pin 3: TX / GPIO1
pin 4: RX / GPIO3
pin 13: RESET
pin 21: GPIO0 (permet de mettre l’ESP8266 en mode "flash")
L’ESP8266 utilise des niveaux de tension de 3.3v (comme sur les GPIO des Raspberry Pi). L’alimentation de la plupart des "modules" ESP8266 se fait également en 3.3v. C’est peut-être cet aspect qui va vous gêner le plus. En effet, les alimentations 5V sont courantes … celles en 3.3V le sont beaucoup moins ! Vous aurez donc sûrement besoin d’un régulateur 3.3V ou d’un converstisseur DC/DC du genre :
Tip
|
Si vous avez une carte Arduino dans un coin, vous pouvez vous servir des pins GND et 3.3V pour alimenter momentanément votre module ESP8266. |
Tip
|
Il existe des adaptateurs d’ESP8266 intégrant un régulateur 3.3V vous permettant d’alimenter votre montage en 5V. Cela permet également d’avoir un module avec des pins qui ont le même pas que les plaques d’essai. |
Une fois que vous avez votre alimentation en 3.3V, il n’y a plus qu'à brancher sur les Pins 1 et 2 :
Pour pouvoir communiquer en filaire avec l’ESP8266, vous avez une bonne vieille liaison série ! Les Pins 3 et 4 vous offre la connectivité pour cela.
Munissez-vous d’un convertisseur USB/UART au préalable. Vous en trouverez à pas cher sur ebay si vous n’avez pas cela sous le coude.
La seule chose à faire attention est de croiser les RX et TX entre votre convertisseur et l’ESP8266. Donc le RX de mon convertiseur USB/UART, je le branche sur le pin 3 (TX) et le TX de mon convertisseur sur le pin 4 (RX).
Dans la plupart des cas, les modules ESP8266 sont livrés avec un firmware qui permet de discuter sur l’UART en 115200 bps. Vous pouvez donc utiliser votre "moniteur série" préféré selon votre OS (minicom, screen, putty, …). Dans mon cas, j’utilise screen :
screen /dev/ttyUSB0 115200
Si vous faites un reset (en mettant le pin 13 à la masse et en le relachant), vous devriez voir des choses apparaître sur votre écran. Il y a même de forte chance que vous puissiez intéragir sur la console car la plupart du temps, le firmware installé par défaut est celui qui permet de se servir de votre ESP8266 en modem Wifi. Ci-dessous, vous voyez quelques commandes :
AT: Commande pour vérifier la connexion
AT+GMR: Donne la version du firmware
AT+CWMODE?: Donne le mode de fonctionnement : 1=STA(station), 2=AP(Access Point), 3=BOTH
AT+CWLAP: Donne la liste des SSID
ready
AT
OK
AT+GMR
00160901
OK
AT+CWMODE?
+CWMODE:1
OK
AT+CWLAP
+CWLAP:(0,"",0)
+CWLAP:(2,"home",-64)
+CWLAP:(0,"AI-THINKER_A11343",-8)
OK
Si, comme moi, vous souhaitez utiliser votre ESP8266 comme autre chose qu’un modem Wifi, vous allez devoir changer le firmware.
Il existe plusieurs outils selon l’OS que vous utiliser. Les plus répandus sont :
esptool : Disponible sur un repo GitHub - Outil Python multi-OS
flash_download_tool : Outil windows officiel disponible sur le forum Espressif
nodemcu-flasher : Outil spécifique Windows disponible sur un repo GitHub
Je vous fais confiance pour suivre la documentation qui va bien pour installer l’outil de votre choix. De mon coté, j’utilise l’outil python esptool (utilisé dans certains makefile).
Avant de flasher un firmware, il faut mettre votre ESP8266 en "mode flash". Pour cela, il faut mettre le GPIO0 (Pin 21 sur l’Olimex) à la masse puis faire un reset (Pin 13 à mettre à la masse et relacher). Quand vous avez flasher plusieurs fois votre ESP8266, vous comprenez l’intéret de certains modules qui comportent 2 boutons (Reset et Flash) !
Dans le cas le plus simple, vous aurez un fichier unique et une simple commande vous permettra de flasher votre ESP8266. Voici un exemple pour flasher la dernière version du firmware NodeMCU :
esptool.py --port /dev/ttyUSB0 write_flash 0x000000 ./nodemcu_float_0.9.6-dev_20150406.bin
Selon les firmwares, il est possible que vous ayez plusieurs fichiers. Dans ce cas, il faudra préciser l’offset où flasher chaque fichier.
18 mai 2015
TweeterDepuis la fin 2014, j’ai découvert un micro-contrôleur très abordable (<5€) avec connectivité WiFi intégré. Ses capacités en font un candidat de choix pour tous vos projets d’objets connectés !
Voici donc le premier billet d’une série sur ce micro-controleur aux multiples facettes :
Les cartes à base d’ESP8266 sont plus à comparer aux cartes de type Arduino qu’aux cartes de type Raspberry Pi. Il s’agit en effet d’un micro-controleur ayant comme atout principal une connectivité WiFi intégré. Ce qui est d’autant plus appréciable, c’est que la puce ESP8266 supporte de manière native le WPA et que le SSL est de la partie (Les spécialistes de la sécurité y trouveront encore d’autres atouts).
Espressif est le fabricant de la puce ESP8266. Les principales caractéristiques de ce SoC ("System On Chip") sont :
CPU Risc 32 bit @80MHz
WiFi 2.4 GHz (802.11 b/g/n)
64 Kb RAM (selon le wiki)
>512 Kb Flash SPI (dépend des versions de cartes)
GPIO / PWM / ADC
UART / I2C / SPI
Alimentation en 3,3V
De quoi connecter quelques capteurs et alimenter vos plate-formes "BigData" !
Selon vos besoins, il existe différentes versions avec plus ou moins de fonctionnalités (ie. nombre de pins disponibles). Les versions sont notées ESP-XX avec XX allant de 01 à 13.
La page de wiki suivante vous donnera un bon aperçu de cette diversité : http://www.esp8266.com/wiki/doku.php?id=esp8266-module-family
Pour vous donner une idée de la taille, voici quelques exemplaires à côté d’un cutter :
Comme il s’agit d’un micro-contrôleur, le terme "firmware" est souvent utilisé. Vous l’aurez compris, il s’agit du programme qui tourne sur cette carte. Et pour changer de "firmware", on va utiliser un outil de type "flash" est utilisé.
Pour faire court, côté applicatif, il y a plusieurs possibilités dont les utilisations les plus courantes sont :
Mode modem (Commandes AT) qui permet d’apporter une connectivité Wifi à une carte arduino par exemple
Interpreteur Lua avec le firmware NodeMCU (scripts LUA uploadés sur la flash SPI)
Coder en C votre propre firmware avec le SDK officiel et la toolchain GCC qui va bien !
C’est la 3ème solution que j’ai utilisé pour la démo du talk DevoxxFr 2015 animé en avril dernier avec Philippe Charrière :
La suite dans les prochains billets ;-)
31 octobre 2014
TweeterDans un article précédent, je présentais la carte Tessel permettant d'écrire des programmes en JavaScript. Cette carte disposant d’une puce Wifi, il est tentant de faire tourner un serveur Web !
Avant de pouvoir mettre un serveur Web sur la carte Tessel, il faut disposer d’une connexion réseau … et donc configurer l’accès Wifi. L’outil CLI fournit tout ce qu’il faut pour cela.
La première chose à faire est de vérifier que la carte voit bien votre SSID :
$ tessel wifi -l
TESSEL! Connected to TM-00-04-f0009a30-00584f4b-704e6249.
INFO Requesting wifi status...
Currently visible networks (1):
home (61/127)
INFO Connected: 0
Pour se connecter, vous pouvez utiliser l’API JavaScript (pour inclure la connexion dans votre code) ou l’outil en ligne de commande. C’est cette dernière option que j’ai choisi :
$ tessel wifi -n home -p <password> -s [wpa|wpa2|wep]
TESSEL! Connected to TM-00-04-f0009a30-00584f4b-704e6249.
INFO Connecting to "home" with [wpa|wpa2|wep] security...
INFO Acquiring IP address.
.
INFO Connected!
IP 192.168.0.8
DNS 212.27.40.241
DHCP 192.168.0.254
Gateway 192.168.0.254
Les informations de connexion sont persistantes et lorsque vous redémarrez la carte, la connexion Wifi s’active au démarrage.
Node.js offre l’API de base pour faire tourner un serveur HTTP. J’ai donc commencé par cela :
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
server.listen(80);
console.log("Server running ...");
Vous remarquerez qu’on peut utiliser le port 80 sans souci (pas de sécurité pour les ports inférieurs à 1024 !). Il n’y a plus qu'à lancer le programme :
$ tessel run http-server.js
TESSEL! Connected to TM-00-04-f0009a30-00584f4b-704e6249.
INFO Bundling directory /home/lhuet/dev/hardware/tessel/webserver
INFO Deploying bundle (1.25 MB)...
INFO Running script...
Server running ...
Le programme fonctionne très bien mais semble un peu lent. Effectivement, la simple requête GET met plus d’une seconde :
$ time curl http://192.168.0.8
Hello World
real 0m1.334s
user 0m0.012s
sys 0m0.004s
A comparer avec le même programme sur mon PC (core i7 qui n’a rien de comparable …) :
time curl http://127.0.0.1:8000
Hello World
real 0m0.007s
user 0m0.006s
sys 0m0.000s
Vous l’avez compris, on ne va pas utiliser la carte Tessel pour faire un bench. Elle n’est pas faite pour cela non plus.
Avec des ressources limitées et le résultat ci-dessus, la question d’utiliser ou non un framework est donc légitime. D’un côté, disposer d’un framework avec routeur et autres joyeusetés est appréciable pour code vite. D’un autre côté, comme dans tout framework, nous n’avons souvent besoin que d’un sous ensemble. Sur un serveur "classique", on ne se pose pas (assez ?) souvent la question mais sur microcontrolleur, c’est déjà beaucoup que de faire tourner du JavaScript … alors un framework !
Un tweet m’a donné l’espoir de faire tourner Express. Je suis vite tombé sur un bug bloquant pour faire tourner les versions récentes d’Express et n’ait pas trouvé une version fonctionnelle sur la carte Tessel. J’ai donc cherché une autre piste et trouvé rapidement la librairie tiny-router plus légère et ayant pour cible la carte Tessel.
Vite, un "Hello World" pour voir ce que ça donne :
var router = require('tiny-router');
router.get('/', function(req, res) {
res.send('Hello World');
});
router.listen(80);
console.log("Server running ...");
Un petit test pour vérifier que ça marche :
time curl http://192.168.0.8
Hello World
real 0m1.194s
user 0m0.000s
sys 0m0.010s
On voit qu’on n’est dans le même ordre de grandeur qu’avec l’API de base. Pour aller (un petit peu) plus loin, j’ai utilisé l’exemple qui permet de commencer à jouer avec les leds sur la carte et on retrouve une application qui ressemble à ce qu’on a avec Express:
var router = require('tiny-router'),
tessel = require('tessel');
var lights = {
green: tessel.led[0],
blue: tessel.led[1],
red: tessel.led[2],
amber: tessel.led[3]
};
router
.get('/', function(req, res) {
res.send('Simple light web API');
})
.get('/lights', function(req, res){
res.send(lights);
})
.get('/green', function(req, res){
var state = lights.green.read();
lights.green.write(state);
res.send({status: state});
})
.get('/green/{state}', function(req, res){
var state = parseInt(req.body.state);
lights.green.write(state);
res.send({status: state});
});
router.listen(80);
Avec ce programme, on peut jouer avec la led verte de la carte en utilisant les URLs :
http://192.168.0.8/green/0 pour allumer la led
http://192.168.0.8/green/1 pour éteindre la led
En conclusion, je dirais que cette librairie tiny-router est amplement suffisante pour utiliser la carte Tessel. Je n’ai pas fait de tests, mais je me demande si une simple carte arduino avec un shield Ethernet ne serait pas plus rapide car les temps de réponse, bien qu’acceptables, ne sont pas impressionnants.
18 octobre 2014
TweeterCoté matériel, elle dispose de quelques atouts intéressants :
Processeur Cortex M3 à 180 MHz
Puce WIFI TI CC3000
32 Mb RAM
32 Mb Flash
Si on compare à un Arduino, la carte Tessel est une bête de course et les 2 cartes ne jouent pas tout à fait dans la même cours ! Pour la mémoire, on parle en Mb coté Tessel et en Kb coté Arduino. Pour le microcontrôleur, l’Arduino UNO est à 16MHz et le Tessel à 180 MHz. On est clairement dans un autre monde.
En terme de connectivité, la carte Tessel dispose :
de bus classiques : 2 I2C, 1 SPI et 3 UART
de GPIO (General Purpose Input/Output) pour les entrées/sorties numériques (j’en ai compté 18 répartis sur les 5 connecteurs) dont 3 sont utilisables en PWM (Pulse Width Modulation).
d’entrées analogiques (j’en ai vu 6) avec un ADC 10 bits.
Un système de connecteur générique avec 3 GPIO, I2C, SPI, 3.3V et GND est utilisé pour mettre en place un écosystème de module. La photo suivante montre un exemple d’utilisation de plusieurs modules.
Voici quelques subtilités glanées dans la documentation :
Il y a 1 seul bus SPI partagées sur tous les connecteurs.
Il y a 2 bus I2C (le 1er partagé sur les connecteurs A, B et GPIO et le second sur les connecteurs C et D)
Seuls les connecteurs A, B et D disposent d’un UART hardware. Les UART des connecteurs C et GPIO sont software et seront intégrés dans un firmware futur.
Démarrer avec la Tessel est super simple, en particulier pour quelqu’un qui est familier avec Node.js. Tout est basé sur Node.js: les outils et le code à produire. Toutes les APIs core de Node.js ne sont cependant pas implémentées sur le Tessel comme l’indique une page dédiée de la documentation. Je n’ai pas regardé si c'était gếnant ou pas.
La page de démarrage vous prend la main pour commencer en douceur. Il faut commencer par installer l’outil CLI et les drivers USB. Sur linux, c’est assez simple :
sudo npm install -g tessel
suivi de
sudo tessel install-drivers
Cela se termine en suivant les instructions pour mettre à jour le firmware :
Pour vérifier que tout fonctionne, une commande permet d’exécuter un bout de code rudimentaire qui fait clignoter les leds sur la carte :
tessel blink
On fait son premier programme en suivant la doc. Un copier/coller du code suivant dans le fichier blinky.js et on est prêt !
// Import the interface to Tessel hardware
var tessel = require('tessel');
// Set the led pins as outputs with initial states
// Truthy initial state sets the pin high
// Falsy sets it low.
var led1 = tessel.led[0].output(1);
var led2 = tessel.led[1].output(0);
setInterval(function () {
console.log("I'm blinking! (Press CTRL + C to stop)");
// Toggle the led states
led1.toggle();
led2.toggle();
}, 100);
Il est possible de lancer le code depuis sa console :
tessel run blinky.js
Si on veut que son programme reste sur la carte, il faut "flasher" son code avec la commande :
tessel push blinky.js
That’all !
La carte est très simple d’accès. Reste à voir comment aller plus loin pour mieux exploiter ses capacités aussi bien au niveau réseau (via Wifi) qu’au niveau hardware. Mes premiers essais ont montrés qu’on peut facilement se connecter en Wifi mais je n’ai pas encore fait de serveur Web dessus par exemple (mon prochain article ?).
Malgré tout ces points encourageant, je ne sais pas si j’acheterais cette carte. Elle est assez cher (75 $ sur le site web officiel). Je n’ai pas une vision globale du marché pour comparer avec une carte équivalente. Dans mes cartons, j’ai une carte STM Nucleo qui se rapproche de la Tessel en terme de capacité hardware que j’ai achetée environ 11 € … Je ne suis peut-être pas non plus la cible des utilisateurs (JavaScript).
05 octobre 2014
TweeterUne installation domotique est constituée de multiples capteurs et autres objets connectés (buzzword oblige). L’aspect communication est un élément clé de ce type d’installation. J’ai cherché à résoudre ce problème dans l’esprit du DIY et vous restitue dans ce billet la solution que j’ai commencée à mettre en oeuvre.
Je n’ai pas retenu les solutions à base de bus "industriels" (KNX par exemple) ou de composants "sans fils" du marché (ZigBee, Wifi, …). En effet, ce type de solution requiert un composant de communication assez couteux. Ce surcoût dépend beaucoup de la technologie. Cela peut aller de 10/15€ à plusieurs dizaines d’euros. Pour du Wifi par exemple, on peut trouver des éléments à base de CC3000 chez SparkFun ou Adafruit pour une trentaine d’euros. Si vous avez juste besoin d’activer un relais ou de récupérer une température, le cout de l'élément de communication devient prépondérant !
Mon choix s’est porté sur une solution à base de RS485. En effet, il s’agit d’un bus série avec les caractéristiques suivantes :
32 "devices" possibles sur le même bus
Jusqu'à 100kbits/s sur une longueur d’environ 1000 m
Half-duplex (du full-duplex pourrait se faire en RS422)
Sa mise en oeuvre est plutôt aisée :
utilisation de cables simples (paires torsadées de cable téléphonique par ex.)
"transceiver" bon marché
liaisons série UART répandues (Raspbery Pi, Arduino, …)
J’ai choisi les composants MAX485 qui sont très courant :
Pour connecter les capteurs, j’ai choisi d’utiliser des arduinos dans la version "mini" pour son coût modique et sa très grosse communauté (et les librairies qui vont avec) !
Les arduinos permettent d’utiliser à peu près n’importe quel capteur en offrant :
une dizaine de GPIO (entrée/sorties digitales)
des entrées (6) et sorties analogiques (6 PWM)
de l’I2C / SPI / UART (utilisée pour la communication sur le bus RS485).
Le choix Arduino ouvre donc pas mal de possibilités.
Le bus RS485 n’apporte cependant que la partie physique du réseau sans aucun protocole de communication. Ce protocole doit donc être implémenté sur les cartes arduino.
Comme pour beaucoup de projet en DIY, le coût est très faible. Pour la liaison RS485, on peut trouver des MAX485 pour à peine plus d’1 € les 5 sur ebay.
Pour les arduinos, on peut trouver des "mini pro" à moins de 2 €.
Au final, la "stack" pour connecter un objet coute de l’ordre de 2 euros !
La mise en oeuvre d’un POC sera abordée dans mon prochain billet. En voici un aperçu pour vous donner l’eau à la bouche ;-)
23 juin 2014
TweeterGVM - the Groovy enVironment Manager is a great tool for managing multiple versions of Groovy, Grails, Gradle, … If you want to use Groovy, Vert.x and Gradle on Beaglebone like me, you have to check/install GVM dependencies.
Generally, Debian distrib. is used with Beaglebone and Raspberry Pi.
You can use the latest JDK from Oracle.
While the JDK tar.gz file is uncompressed, you can add the following lines on my ~/.profile
file
PATH="$PATH:$HOME/jdk1.8.0/bin"
JAVA_HOME="$HOME/jdk1.8.0/bin"
To check the JDK installation, use the java -version
command
debian@beaglebone:~$ java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode)
GVM is a bash tool and depends only on curl and unzip. Unfortunately, unzip is not installed by default. You’ll have to install these dependencies with a command like
sudo apt-get install curl unzip
You can now install GVM easily with the following command lines.
curl -s get.gvmtool.net | bash
source ~/.gvm/bin/gvm-init.sh
To check the installation, you can use the gvm version
command
debian@beaglebone:~$ gvm version
Groovy enVironment Manager 1.3.13
The latest version of Groovy, Gradle and vert.x can be installed with the following commands
gvm install groovy
gvm install vertx
gvm install gradle
The following command tells you which Vert.x versions are installed / available
debian@beaglebone:~$ gvm list vertx
================================================================================
Available Vertx Versions
================================================================================
> * 2.1
2.0.2-final
2.0.1-final
2.0.0-final
1.3.1.final
1.3.0.final
1.2.2.final
1.2.1.final
1.2.0.final
1.1.0.final
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
You can check Vert.x installation with the following command
debian@beaglebone:~$ vertx version
2.1 (built 2014-05-27 12:39:02)
And now, you are ready to use Vert.x on Beaglebone :-)
09 juin 2014
TweeterL'édition 2014 du BreizhCamp a été l’occasion pour la team d’innover en mettant en place un boitier de vote pour récupérer le feedback des participants à la sortie de chaque conférence. L’idée n'était pas si originale que cela puisque nous avons découvert en cours de réalisation que Devoxx France allait également avoir ce type de boitier. Bien évidemment, le notre était beaucoup mieux :-p
Dans cet article, je me focalise sur la partie technique à l’intérieur du boitier. Nicolas donne un autre point de vue sur la partie organisationnelle / habillage du hardware / marketing / whatever …
L’idée de départ était de voir ce qu’on pouvait mettre en place pour que les participants puissent s’exprimer autrement qu’en mettant une croix sur une feuille A3 (solution utilisée pour l'édition 2013). Intéressé par le hardware, c’est naturellement par ce coté que j’ai commencé. Le premier prototype fait sur un coin de table était à base d’arduino :
Le code n'était pas d’une finesse extrême, mais c'était un prototype fonctionnel ! Pour ceux que ça intéresse, vous pouvez le retrouver ici.
Au delà de l’aspect technique, ce prototype a été une base de discussion avec la team sur les fonctionnalités à mettre en oeuvre :
Nombre de boutons (2, 3, +) ?
Ecran texte ou Ecran graphique ?
Forme/Type de bouton ?
Intégration de l’ensemble
…
Globalement, les choix techniques du coeur du boitier ont été guidés par les compétences de l'équipe, le matériel dejà disponible et le coût. Le leitmotiv de l'équipe a été de faire simple et robuste.
La partie hardware est constitué de 3 élements principaux :
Les boutons de vote (interaction avec les utilisateurs … donc aspect fondamental du boitier)
L'écran de visualisation
La carte contenant pour faire tourner la partie software
Pour les boutons de vote, le bouton type "champignon" nous est paru essentiel. Cela a été le choix le plus difficile à faire compte tenu du nombre de boutons disponibles sur le marché et de la diversité des tarifs. Pour les côtés robuste et visuel, nous avons retenu des boutons métaliques industriels et passé commande chez Farnell.
Pour les écrans, j’ai fait quelques tests avec divers écrans LCD Texte 2/4 lignes, LCD graphique entre 2 et 3". Au final, nous avons retenu l'écran LCD Texte sur 4 lignes avec un fond bleu pour des questions de lisibilité et de simplicité. Une version avec bus I2C a été choisie dans un souci de simplicité de cablage.
Pour la carte principale, le choix a été rapide : Raspberri Pi. Nous n'étions pas nombreux à avoir de l’expérience sur Arduino et nous avions plusieurs Raspberry Pi (pas d’achat à prévoir de ce coté). L’arduino aurait été une solution plus robuste mais la Raspberry Pi apportait d’autres possibilités (sortie HDMI pour gérer un autre affichage, connectivité réseau intégré, …).
Allez hop, les commandes ont été passées et nous étions prêt pour notre soirée montage avec la matière première :
Alexandre a même optimisé / conçu le cablage pour avoir une mise en oeuvre la plus simple possible :
pas de condensateur anti-rebond (gestion coté soft)
boutons en mode pull up (plus de pins GND disponibles que de 3.3 V)
Les sources sont disponibles sur Github dans repo dédié. Dans le contexte du BreizhCamp, le développement a été guidé par la simplicité de mise en oeuvre et par la robustesse. En termes de spécifications, cela peut se traduire par :
je branche → ça marche
je m’endors sur le bouton → pas grave, un seul vote est pris en compte
tolérant aux pannes réseau (réseau filaire que la team a mis en place)
support des changements de programme de dernière minute
boitiers autonomes et envoi des votes régulièrement à un serveur si c’est possible
Il y a 2 parties software :
la partie cliente sur le boitier de vote
la partie serveur qui aggrège les données de l’ensemble des boitiers de vote (nous en avions 5) et les expose sous forme d’API REST.
Pour faire simple et léger (en particulier sur le Raspberry Pi), Node.js a été choisi. En plus de la légèreté, la diversité de ses modules, notamment pour l’interfaçage Hardware, a contribué à ce choix. Les principaux modules utilisés sont :
onoff pour gérer les boutons (GPIO)
lcd-pcf8574 pour gérer l'écran LCD 4 lignes
sqlite3 pour stocker localement les données de vote dans une base de données fichier SQLite3.
restler pour l’implémentation du client REST sur les boitiers
express pour la partie serveur
Les modules cités vous auront déjà donnés la puce à l’oreille. La communication entre les boitiers et le serveur se fait uniquement sur HTTP (simple API REST).
La restitution est réalisée avec une simple page Web sur laquelle on n’est pas peu fier de retrouver sa session ;-) :
Tout n’a pas été aussi rose, nous avions un peu sous-estimé le temps de mise en oeuvre, notamment des copies de cartes SD. En effet, copier une carte SD de 8Go peut parfois prendre plus de 40mn. Ceci étant, une fois les boitiers en place et les rares bugs corrigés (dont un souci de performances sur un module node … coté serveur), tout à fonctionné à merveille !
Au final, ce système a permis de prendre en compte près de 2500 votes !
Je tiens à conclure pour souligner que ceci résulte d’un véritable travail d'équipe :
Infrastructure réseau (5 routeurs configurés dans chaque salle sur lesquels les boitiers étaient reliés au réseau)
Montage de l’ensemble des boitiers en une soirée par toute l'équipe
Développement du code à 4 (je me compte dedans même si j’ai plus été "product owner" que développeur)
Préparation de l’intégration (plaques plexi, pieds, …) par Nicolas et son fils Julien
Montage de 3 TV en HDMI sur 3 des boitiers
Configuration système de l’ensemble des éléments (boitiers et serveur)
Prochaine étape : Diffusion du projet sur le portfolio du LabFab prêt à promouvoir notre LikeBox en vue d’une réutilisation sur d’autres évènements.
26 janvier 2014
TweeterVous avez lu attentivement mon post précédent sur le montage teleinfo, récupéré l’optocoupleur qui va bien et sorti votre Raspberry Pi du placard. Maintenant, vous être prêt à passer à la partie soft.
Le point de départ est la distribution raspbian officielle que vous devez télécharger. Pour flasher une carte SD, je vous suggère de suivre les instructions sur le site elinux.org.
Si vous êtes sous linux, vous pouvez utiliser une commande du genre :
dd bs=4M if=./2013-09-25-wheezy-raspbian.img of=/dev/sdb
Attention, dans mon cas, /dev/sdb
correspond à ma carte SD. Ne pas copier/coller cette ligne "à l’aveugle" … Si /dev/sdb
correspond chez vous à un disque dur, vous risquez d’avoir quelques sueurs froides !
La Raspberry Pi ne dispose que d’un seul port série. Celui-ci est utilisé par défaut pour avoir une console. Il faut donc libérer le port série pour le montage téléinfo.
Désactiver de la console série au boot en modifiant le fichier /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
à remplacer par :
dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Désactiver la console getty
en modifiant le fichier /etc/inittab
. Il suffit de commenter la dernière ligne du fichier (ajout d’un #
):
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Cette partie corresond à l’installation et la configuration d’un programme nodejs pour logguer les infos dans une base MongoDB. Dans mon cas, j’utilise une formule d’hébergement gratuite avec 512 Mo chez MongoLab. Vous pouvez choisir n’importe quel fournisseur à ce niveau (MongoHQ offre le même type de formule par exemple).
Il y a quelques temps, il était difficile de trouver une version nodejs pour processeur ARM. Il fallait donc compiler les sources sur Raspberry Pi (~45 mn de temps de compilation) ou, pour les plus avertis, en "Cross Compiling" (moins de 2mn sur mon core i7). Désormais, une version officielle est disponible mais pas toujours dans la dernière version. Il faut donc fouiller dans les répertoires http://nodejs.org/dist/. La dernière version à ce jour est la v0.10.24.
L’installation consiste uniquement à décompresser l’archive :
tar -xzvf node-v0.10.24-linux-arm-pi.tar.gz
Si vous installez nodejs dans le répertoire /opt
, vous pouvez ajouter les lignes suivantes au fichier /etc/profile
pour positionner les variables d’environnement pour node :
NODE_JS_HOME="/opt/node"
PATH="$PATH:$NODE_JS_HOME/bin"
NODE_PATH="$NODE_JS_HOME/lib/node_modules"
Vous pouvez commencer en utilisant mon application (en cours de développement) en clonant le repo git associé :
git clone https://github.com/lhuet/teleinfo-app.git
Pour obtenir les dépendances node, utilisez la commande classique node :
npm install -g
Le programme va chercher les éléments de configuration dans des variables d’environnement que vous pouvez positionner avec la commandes suivantes :
export MONGO_LOGIN="LOGIN_MONGOLAB"
export MONGO_PASSWORD="PASSWORD_MONGOLAB"
export MONGO_HOST="HOST_MONGOLAB"
export MONGO_PORT="PORT_MONGOLAB"
export MONGO_DATABASE="BASE_MONGOLAB"
Pour lancer l’application manuellement, vous devez positionner ces variables d’environnement et utiliser la commande :
node teleinfo-app.js
Lancer manuellement son application suffit en phase de développement. Pour être certain que le script se lance au démarrage de votre Raspberry Pi, vous devez faire un script du genre :
#!/bin/sh
#/etc/init.d/node-teleinfo
export PATH=$PATH:/opt/node/bin
export NODE_PATH=$NODE_PATH:/opt/node/lib/node_modules
export MONGO_LOGIN="LOGIN_MONGOLAB"
export MONGO_PASSWORD="PASSWORD_MONGOLAB"
export MONGO_HOST="HOST_MONGOLAB"
export MONGO_PORT="PORT_MONGOLAB"
export MONGO_DATABASE="BASE_MONGOLAB"
case "$1" in
start)
exec forever --sourceDir=/home/pi/teleinfo-app -p /tmp teleinfo-app.js
&
;;
stop)
exec forever stop --sourceDir=/home/pi/teleinfo-app teleinfo-app.js
;;
*)
echo "Usage: /etc/init.d/node-teleinfo {start|stop}"
exit 1
;;
esac
exit 0
La commande suivante permet de configurer votre système pour que le script se lance au démarrage :
sudo update-rc.d node-teleinfo defaults
Maintenant que les données sont stockées, il va falloir les restituer ! Je n’ai pas encore beaucoup avancé sur cette partie. J’ai commencé à intégrer express pour avoir des infos "live" (puissance instantanée, intensité instantanée et index) . Il reste toute la partie exploitation des données.
J’ai oublié de le préciser, mais j’accepte les pull-requests ;-)
A suivre donc.
19 janvier 2014
TweeterCela fait quelques mois que j’ai testé et mis en place un montage simple pour brancher mon compteur EDF sur Beaglebone et Raspberry Pi. Je vous restitue donc tout ce qu’il faut pour reproduire celui-ci chez vous. L’inspiration de ce montage provient du forum chaleurterre.com. J’ai finalisé ce montage avec l’aide de zzdomi du forum touteladomotique.com.
Le compteur EDF fourni un signal appelé téléinfo pouvant être transformé en signal série TTL compatible avec les cartes Raspberry Pi ou BeagleBone. Les spécifications du signal teleinfo et de son protocole sont disponibles sur le site d’ERDF en PDF.
L’objet du montage de ce post est de réaliser cette transformation pour obtenir un signal compatible avec les UART des cartes récentes de type Raspberry Pi / BeagleBone / … (niveaux en 3.3V).
Le signal teleinfo des compteurs EDF doit être activé (configuration interne du compteur). Si ce signal n’est pas activé, il faut demander à EDF de venir chez vous le configurer. En effet, la configuration est réalisée sur la partie haute du compteur … qui vous est interdite d’accès (plombage). Ayant un compteur configuré dès son installation, je ne pourrais pas vous guider plus sur la démarche à suivre.
Le bornier client du compteur EDF se situe sur sa partie basse comme le montre le schéma suivant :
Les bornes I1 et I2 fournissent le signal convoité. Vous pouvez utiliser du simple cable téléphonique et, dans des conditions optimales, la longueur de ce cable peut aller jusqu'à 500m (donnée des spécifications).
Le montage utilise uniquement uniquement 3 composants :
1 optocoupleur SFH620A
1 résistance 1.2k
1 résistance 3.3k
Attention à prendre la référence exacte de l’optocoupleur car les latences (de basculement) de celui-ci sont importantes. Inutile donc de chercher des équivalences avec le même montage.
Comme le montre le schéma suivant, le montage est assez basique :
Vous pouvez tester ce montage sur une carte d’essai (breadboard) avant de passer à la soudure. Pour cela, utilisez un logiciel capable de lire un port série (screen ou minicom par exemple). Les caractéristiques de la communication sont "1200 7E1", ie. 1200 bauds, 7 bits de données, parité paire, 1 bit stop.
Le schéma Fritzing suivant montre le cablage pour la Raspberry Pi :
La même chose avec la Beaglebone Black :
Après la partie hardware, il faut passer à la partie software. Vous pouvez utiliser les programmes Python ou JavaScript (node.js) que j’ai écrit par exemple.
14 décembre 2013
TweeterMon second post est une réponse détaillée à une question posée par @CodeStory sur twitter. 140 caractères étaient largement insuffisants ! Ma réponse va également un peu plus loin puisque je compare les performances du JDK7 et du JDK8.
La première question qu’on peut se poser est : Quelle version de JDK utiliser ?
Sur le site d’Oracle, on trouve 2 versions différentes pour le JDK 7:
"Linux ARM v6/v7 Hard Float ABI"
"Linux ARM v6/v7 Soft Float ABI"
Aucun JDK8 n’est proposé sur le site d’Oracle (pas encore de version finale). On trouve une "Early Access Release" sur jdk8.java.net sous le nom :
"Linux ARMv6/7 VFP, HardFP ABI"
Ces JDK peuvent être utilisés sur BBB (ARM v7) et sur Raspberry Pi (ARM v6) … mais pas sous n’importe quelle version d’OS.
"Hard Float" et "Soft Float" sont des termes utilisés pour des jeux d’instruction spécifiques des processeurs ARM. Historiquement, le JDK d’Oracle n'était disponible qu’en version "Soft Float".
Quelques éléments de réponses se trouvent également dans les slides de mon quickie de Devoxx France 2013 sur parleys.
Pour faire court, les JDK en version HFP (Hard Float) ne peuvent être utilisés que sur des OS compatible HFP.
La carte BBB est livrée avec une distribution Angström … qui est compilée en "Soft Float". Seul le JDK 7 "Soft Float" peut donc être utilisé avec cet OS. Aucune version "Soft Float" du JDK 8 n’est disponible à ma connaissance.
Pour utiliser les JDK 7 et 8 en version HFP, il faut un Linux compatible. C’est le cas d’Ubuntu. Vous pouvez vous inspirez du tutoriel d’Adafruit pour installer une nouvelle version d’OS sur la BBB ou, comme je l’ai fait, booter sur une microSD externe contenant Ubuntu.
J’ai repris les mêmes types de tests que pour mon quickie de Devoxx France 2013, à savoir, des tests dacapo (avrora, fop et xalan). Les scores sont ramenés sur une base 100 ayant pour référence les résultats sur JDK7 sur Rapsberry Pi de mon Quickie. J’ai consigné les valeurs brutes dans un fichier LibreOffice.
Ces tests ont seulement pour objectif de comparer grossièrement les JDK … et n’ont fait l’objet d’aucune méthodologie, analyse statistique, … Pour avoir des résultats indiscutables, il faudrait des tests réalisés par des spécialistes de JVM, ce que je ne suis pas ! |
Voici donc 2 graphes avec/sans référence à la Raspberry Pi.
En conclusion, les performances ne sont pas fondamentalement différentes. Si vous êtes sur l’OS de base sur la Beaglebone, vous n’avez donc pas besoin d’en changer … sauf si vous voulez tester les nouveautés du JDK8.
Autre enseingement : Si vous faites tourner du code Java sur une Raspberry Pi, vous auriez avantage à passer sur Beaglebone Black !
08 décembre 2013
TweeterMon premier post technique sera sur la carte BeagleBone Black (ma 3ème BeagleBone). Pas de Java pour le moment, mais ça va venir … Je préfère commencer par le Hard !
Il s’agit d’une carte à base de processeur ARMv7 avec un coût relativement modique (~45$) et une consommation électrique faible (de l’ordre du Watt). Cette carte est parfois appelée BeagleBone Next-gen car elle a été précédée par une première version très proche physiquement : la BeagleBone. Open source "sur toute la ligne" (hardware et software), vous pouvez retrouvez les plans complets sur GitHub.
Son rapport "coût/connectivité" est assez intéressant. Ceci en fait un choix pertinent pour des installations de type domotique, robotique, …
(possibilité de gérer de nombreux capteurs).
Avant d’aller plus loin, la voici en image :
On retrouve :
CPU ARM Cortex-A8 @1GHz
512 Mo RAM DDR3
2 Go eMMC (stockage interne)
Ethernet / 1xUSB / µHDMI / MicroSD / 2 ports d’extension 2x23 pins
Les ports d’extension méritent un détour. C’est d’ailleurs un atout majeur de cette carte :
65 GPIO (entrée/sortie numérique)
8 PWM ("Pulse Width Modulation" ~ sorties analogiques pour caricaturer)
7 entrées analogiques
5 UART (ports série)
Bus divers (3 I2C, 1 SPI, 1 CAN)
Il y a d’autres possibilités pour une utilisation plus avancée (PRU, Timers, …) sur lesquels je ne vais pas aller plus loin (pour le moment). Pour avoir plus de détails, vous pouvez consulter la dernière version de la documentation de référence disponible sur le projet GitHub.
Il ne s’agit pas d’une carte avec micro-controlleur (ARM Cortex-M, Atmel sur Arduino, …) mais d’une carte avec un micro-processeur. Cela signifie que cette carte fonctionne avec un OS. Même si cet environnement est restreint, vous êtes très proche de ce que vous pourriez avoir sur n’importe quel système avec OS.
Les OS connus pour fonctionner sont (liste non exhaustive) :
Linux (Angstöm, Debian, Ubuntu, …)
Android
QNX
FreeBSD
Les différences majeures portent sur:
le CPU : de génération différente (ARMv7 vs ARMv6), la beaglebone est un cran au dessus (non négligeable pour exécuter du Java !).
la connectique : Cf. la liste ci-dessus, il n’y a pas photo ! La beaglebone est beaucoup plus complète.
le GPU : Capable de décoder des vidéos HD, la RaspberryPi est par contre meilleure dans ce domaine.
Pour le reste, il y a eu plein d’articles comparatifs sur le web. Celui sur le site makezine.com me paraît pas trop mal.
Pour résumer, la beaglebone est plus puissante que la Raspberry Pi sauf pour une utilisation multimédia.
Le démarrage est extrêmement simple. En effet, la beaglebone est livrée avec une distribution Linux pré-installée (distribution Angstöm orientée embarqué). Pas besoin de préparer une carte SD comme avec la Raspberry Pi. Tout ce qu’il y a à faire, c’est de brancher l’alimentation ! Ecran/Clavier/Souris sont optionnels si vous utilisez une connexion réseau.
La BBB a besoin d’une alimentation en 5V. Pour faciliter le démarrage, vous n'êtes pas obligé d’avoir une alimentation externe. Vous pouvez utiliser le cable USB fourni pour le brancher directement sur votre PC en utilisant le connecteur mini-USB coté BBB. Dans ce cas, un disque partagé sera mis à disposition (USB Mass Storage) sur lequel vous trouverez la documentation et les éventuels drivers requis. Si vous êtes, comme moi, sous Linux, vous n’aurez besoin d’aucun driver pout disposer de l’interface réseau "USB to LAN".
Si vous utilisez un cable ethernet, la BBB utilisera votre DHCP pour obtenir une adresse IP. Si vous utilisez le cable USB fourni, vous aurez une interface réseau sur votre PC mise à disposition par la carte sur l’IP 192.168.7.1. La BBB aura l’IP 192.168.7.2. Le login root a un mot de passe vide par défaut. Vous pouvez donc vous connecter par SSH très facilement.
Un environnement de développement JavaScript (Cloud9) est également mis à disposition avec une version (un peu ancienne) de node.js. La librairie BoneScript fournie permet d’avoir une API "arduino like". Ce service est disponible sur l’URL http://192.168.7.1:3000 avec quelques exemples pour démarrer.
01 décembre 2013
TweeterCela faisait longtemps que je voulais créer ce blog. C’est maintenant chose faite !
Mon besoin principal (et oui, c’est un besoin !) est de partager diverses expériences à travers quelques billets. Comme elles sont souvent liées à du code, rien de plus naturel que de mettre ces billets à coté de celui-ci sur GitHub !
Coté hébergement, mon choix s’est donc rapidement porté sur GitHub pages … d’autant plus que ce service est gratuit !
Jekyll est le choix naturel suggéré par la documentation GitHub. N'étant pas fan de Ruby ni des gems à installer, j’ai longtemps hésité à franchir le pas. Entre temps, j’ai beaucoup entendu parler (en bien) de Asciidoctor, notamment sur sa mise en place sur des projets comme Groovy, Hibernate, ou Golo. La migration du blog de Cédric Champeau m’a définitivement décidé à franchir le pas en me montrant la voie à suivre.
Les billets à venir porteront sur Java … et le hardware … une fois que j’aurais bien appréhender l’AsciiDoc.
Stay tuned !
En bas de page, vous pourrez constater que les publications de ce site sont sous licence Creative Commons by-nc-sa.
Billets plus anciens disponibles sur la page archive.