BB-8 DIY (contrôlé par la Force ;)

Après quelques mois passés à bosser sur un gros projet, je m’offre une petite pause de fun pour un petit BB-8 fait maison, parce qu’il est vraiment trop mignon 😉 (vidéo disponible à la fin de l’article).

A la base, je voulais juste faire une une figurine et puis je me suis dit que ça serait sympa de l’animer un peu. Alors il ne se déplace pas, mais il tourne la tête, émet des sons et détecte les obstacles devant lui : un simple passage de la main devant lui déclenchera différentes animations.

Ci-dessous, l’ensemble des éléments utilisés (électronique, pièces imprimées, capteur ultrasons, servomoteur…). Le modèle 3D n’est pas de moi, il vient d’ici. J’ai fait des trous dans le corps pour pouvoir passer l’axe de la tête et imprimé des joints pour assembler le tout (+ le support).

Après ponçage, enduit, peinture et vernis, il ne reste plus qu’à assembler le tout.

L’image suivante représente le « cerveau » de BB-8 : un simple Arduino Nano, un buzzer et 3 borniers à visser (alimentation et capteur ultrasons).

Le code est disponible ici. C’est pas super propre mais bon, ça fait l’affaire. J’ai eu de petits soucis d’incompatibilité entre différentes librairies car elles utilisaient les mêmes interrupts : Servo, NewPing, Tone (ou même NewTone pour éviter le conflit avec NewPing). Au final, je n’utilise aucune librairie pour piloter le buzzer).

Vue du boitier une fois tous les composants en place :

Le servomoteur est fixé au centre du boitier :

Pour prolonger l’axe du servomoteur, j’ai utilisé un tube (qui remontera jusqu’à la tête) et imprimé 2 joints qui s’emboîtent dans le tube de PVC : le premier a un emplacement prévu pour intégrer le connecteur à la tête du servomoteur (en noir, que j’ai découpé d’un support vendu avec le servo) et le second qui permet de faire la jonction avec la tête).

Au passage, le socle au dessus du servo est constitué de 2 pièces : la première permet de surélever le support au dessus des vis du servo et le second est un cône qui donnera l’illusion d’une dune (le sable a été saupoudré sur une couche de colle à bois) parce qu’on rencontre BB-8 dans le désert ;).

Aperçu du système de rotation de la tête :

A l’arrière : un interrupteur et un connecteur USB (le robot peut fonctionner sur USB ou sur pile, au choix) :

Et voilà !

Pour finir, une démonstration de notre petit BB-8 en vidéo 🙂

 

Tous les fichiers sont disponibles ici (modèles Sketchup, fichiers STL et code pour le Arduino Nano). Les fichiers STL du robot en lui-même sont à récupérer sur Thingiverse comme indiqué plus haut.

PoC de l’étage électronique : Arduino Mega + 10 périphériques

J’ai prévu d’utiliser un Arduino Mega pour jouer le rôle de « moelle épinière » de mon prochain robot. C’est cette partie qui permettra l’acheminement des différents messages entre le cerveau (un mini-PC) et le corps (châssis, moteurs, capteurs) du robot.

Cette partie sera donc le carrefour de nombreux échanges entre différents types de périphériques, avec leurs contraintes (protocoles différents, performances, utilisation d’interrupts externes etc.).

Le but de ce PoC (Proof of Concept) est de démontrer que le Arduino Mega est bien capable d’assurer ce rôle. Plus précisément, il doit être capable de gérer en parallèle :

  • des périphériques sur bus SPI
  • des périphériques sur bus i2c
  • la communication série avec un PC
  • la communication avec un autre Arduino (Nano) sur le bus i2c
  • le pilotage de pins digitaux
  • la lecture de pins analogiques
  • des encodeurs très rapides avec des interrupts externes

Et tout ça pour une emprunte mémoire supportable.

Pour ce faire, j’ai fait un petit montage composé d’un Arduino Mega, d’une matrice de LEDs (SPI), d’un moteur CC et son encodeur (les 2 pins étant attachés à des interrupts externes), un tableau de 10 LEDs (je n’en utiliserai que 8, pilotés directement par des sorties digitales + une résistance de 150 Ohms), une photorésistance (sur pin analogique), un écran OLED (i2c), un capteur thermique IR de 8 cellules (i2c), un Arduino Nano (i2c) avec 2 capteurs ultrasons.

Le schéma suivant sera plus parlant :

PoC_mega

L’écran permettra d’afficher un certain nombre d’informations (température la plus élevée sur le capteur thermique, ticks moteurs, les distances relevées par les capteurs ultrasons), le tableau de 8 LEDs affichera la cellule la plus chaude détectée par le capteur thermique) et la matrice de LEDs dessinera une ampoule si une forte lumière est détectée ou un smiley si la température la plus élevée  relevée par le capteur est inférieure ou égale à 50°C et un cœur si elle les dépasse.

Pour mesurer l’intensité lumineuse, on utilisera une photorésistance  (1-10 KOhms) : sa résistance varie en fonction du niveau lumineux.  Un simple pont diviseur de tension (avec une résistance de 10 KOhms) nous permettra d’obtenir des variations de tension sur le port analogique que l’on pourra alors facilement mesurer. Un tuto ici.

L’Arduino Mega est le maître du bus i2c. Pour pouvoir communiquer avec un autre Arduino (Nano ici), ce dernier doit être utilisé en tant qu’esclave sur le bus i2c. Tout ce qu’il faut savoir est ici.

Les détails concernant le moteur (et son encodeur) utilisé est disponible ici. Et voici le détail des connexions :

Les librairies utilisées sont les suivantes :

Côté Arduino Mega, on est confortable, le programme occupe 7% du stockage et utilise 11% de la mémoire. Pour le Nano, la question ne se pose même pas : il ne fera que relever les mesures de capteurs ultrasons.

Lors des premiers essais, des problèmes de performances sont apparus et on pouvait observer une légère latence du système, de l’ordre des 200ms à vue de nez. En pratique, si j’allume la lumière sur la photorésistance, la matrice de LEDs affiche l’ampoule 200ms plus tard. Ce n’est pas énorme, mais ça se sent et ça pourrait poser des problèmes, pour la gestion des obstacles par exemple.

Je me suis vite aperçu que cela venait du rafraîchissement de l’écran OLED : à chaque tour de la boucle principale du programme, l’écran était entièrement redessiné. Je n’ai pas besoin de le mettre à jour si souvent, il suffirait de le faire une fois toutes les 200ms pour avoir un affichage assez fluide (sachant que pour mon utilisation, je pourrais même le rafraîchir toutes les secondes seulement).

Et c’est très facile à faire, grâce à la fonction millis(). Elle renvoie le nombre de millisecondes écoulées depuis que le Arduino est sous tension (le compteur revient à 0 après environ 50 jours de fonctionnement). A partir de là, il suffit de vérifier à chaque tour de la boucle principale qu’au moins 200ms se sont écoulées depuis le dernier rafraîchissement de l’écran. Si ce n’est pas le cas, on ne le redessine.

Cette petite astuce a réglé les problèmes de latence, l’Arduino Mega pilote le tout à merveille, la démo en vidéo :

Code source pour l’Arduino MEGA
Code source pour l’Arduino Nano

Premiers pas vers un système Ambilight DIY

Après une petite trêve, il est temps de se remettre au boulot : réalisation d’un système Ambilight maison. Philips intègre cette technologie à certains de ses écrans depuis plusieurs années. Le principe est de diffuser un halo lumineux autour de la télé, en fonction des couleurs affichées sur les bords, pour une meilleure immersion.

Je voudrais intégrer un système similaire, mais pour mon PC et aller plus loin : en profiter pour les films, mais aussi les jeux, la musique, pouvoir définir des ambiances, gérer des notifications etc.

Il y a une ou deux semaines, j’ai trouvé ça dans ma boite aux lettres :

OLYMPUS DIGITAL CAMERA

C’est l’élément clé : il s’agit d’un ruban de LEDs adressables. Comparés aux rubans de LEDs classique, l’avantage énorme de ces rubans, est qu’ils ne nécessitent que 3 ou 4 fils pour être contrôlés, grâce à des petits contrôleurs embarqués (chaque LEDs ayant une adresse). Il en existe différents types, j’ai opté (peut-être un peu rapidement) pour un modèle basé sur chipset SPI : WS2801. Ce n’est pas trop cher (15€ le mètre) et ça devrait faire l’affaire.

Le chipset de LEDs qui a le vent en poupe en ce moment semble être le WS2811 (ou 2812 / 2812B / Neopixel). Il s’agit d’un chipset 3 câbles, contrairement au SPI.

La chose importante à s’assurer lors du choix du chipset, est qu’il soit géré par la librairie FastLED pour Arduino. La liste des chispsets supportés est disponible sur le Wiki du projet.

Mon ruban sera donc piloté par un Arduino Nano. Parce que j’en avais un qui traînait, que ça ne coûte pas cher (2-3€) et que ça ne prend pas trop de place 🙂

OLYMPUS DIGITAL CAMERA

Pour le WS2801, nous aurons besoin de 4 cables : +5V (IN/OUT), 0V (GND),  SPI Clock (CK) et SPI Data (SD).

OLYMPUS DIGITAL CAMERA

Remarque importante, qui m’a fait perdre un peu de temps : les rubans ne sont utilisables que dans un seul sens. Sur certains modèles, une flèche indique le sens. Ce n’était pas le cas sur le mien. J’aurais dû m’apercevoir plus tôt que d’un côté il était marqué « IN 5V » et de l’autre « OUT 5V » pour déterminer le sens.

La connexion sur le Arduino est très simple, il suffit d’utiliser les pins SPI CLOCK et SPI MOSI (pin digitaux 13 et 11 sur le Nano).

OLYMPUS DIGITAL CAMERA

Après un premier loupé, j’ai fini par souder un connecteur sur mon ruban de LEDs pour avoir quelque chose de propre, solide et facilement raccordable à la platine de tests.

OLYMPUS DIGITAL CAMERA

Pour mes premiers tests, j’ai travaillé avec un ruban de 6 LEDs. Ce n’est pas obligatoire, mais pratique pour la phase de calibrage. De plus, cela évite les problèmes liés à une alimentation insuffisante.

Après cette première partie concernant le matériel utilisé, passons au logiciel et au calibrage. Tout d’abord, il faudra se procurer la libraire FastLED (hyper optimisée et très complète).

Je copie/coller une remarque importante issue du site de FastLED :

IMPORTANT NOTE: If you are building for AVR based systems, please do not use any version of the arduino IDE 1.5.7 or later yet. It messes with some of the asm output which will cause you problems.

En clair, pour Arduino, s’assurer de ne pas avoir une version trop récente de l’IDE (j’utilise la 1.0.5-r2).

Une fois FastLED installé dans les librairies de l’IDE Arduino, nous pouvons ouvrir l’exemple « RGBCalibrate ».

Indiquer le nombre de LEDs utilisées :
#define NUM_LEDS 6

Modifier les pins utilisés :
#define DATA_PIN 11
#define CLOCK_PIN 13

Ajouter les LEDS qui correspondent au chipset utilisé (WS2801 dans mon cas) :
FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);

Le code est prêt à être chargé, et testé ! Normalement, les LEDs devraient s’allumer. Si on constate de que la première LED est rouge, les 2 suivantes vertes et les 3 dernières bleues, alors tout est bon, les couleurs sont envoyées dans le bon ordre : Rouge, Vert, Bleu. Si ce n’est pas le cas, il faudra modifier la ligne d’ajout des LEDs pour identifier l’ordre des couleurs à utiliser pour votre ruban. Dans mon cas, RGB ne correspondait pas, je suis passé en BGR, en modifiant la ligne (ne pas hésiter à tester toutes les combinaisons jusqu’à tomber sur la bonne) :
FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS);

OLYMPUS DIGITAL CAMERA

L’étape suivante a consisté à tester la communication entre le PC et la carte Arduino pour piloter le ruban. J’ai écrit 2 petits programmes:

  • un pour le Arduino Nano, qui écoute les ordres du PC et contrôle les LEDs en fonctions des messages reçus
  • un pour le PC (en .NET C#), qui permet d’envoyer des ordres au Arduino pour piloter les LEDs.

Le programme pour le Arduino Nano est dispo ici. Le principe est très simple : on écoute sur le port série. Si des données arrivent, on lit le premier octet, qui contiendra un caractère. Si ce caractère est un A, alors on lit les octets qui suivent (3 octets pour chaque led, correspondant au code couleur RGB). Si le premier octet est un B, C ou D, on passe en mode « amibiance » (le Arduino génère en boucle une animation pour les leds).

Côté PC, il s’agit d’un petit programme écrit en C# (application WPF). Les sources sont dispos ici. Attention, c’est pas un chef d’oeuvre, juste une bricole de test, pas de MVVM etc. Mais ça reste simple.
Rien de particulier à ajouter, si ce n’est que la communication avec le Arduino se fait grâce à la classe System.IO.Ports.SerialPort du Framework .NET et le composant graphique ColorPicker provient du Extended WPF Toolkit.

05_programmeTestLeds

Toutes les actions depuis cette fenêtre, à part les « Ambiances », envoient explicitement à l’Arduino l’état RGB de chaque LED. L’Arduino ne servant qu’à les faire suivre aux LEDs. Ainsi, les scénarios sont intégralement pilotés par le PC, contrairement aux ambiances qui sont calculées par l’Arduino.

Voici une vidéo qui illustre le fonctionnement de l’ensemble :