1. Introduction

Le principe de la machine est de séparer les différents Skittles, de les prendre en photo au moment opportun puis de les répartir dans le bon réceptacle.

20160217_100048.jpg

Pour séparer les Skittles, je me suis inspiré d'une machine déjà existante qu'on peut voir en action ici. Une roue tourne, perforée de trous pouvant accueillir un unique Skittle. Ma roue est opaque et percée de 2 trous. À l'opposé de la caméra se trouve une led et des photoréstistances ordinairement séparées par la roue. Lorsque le Skittle est en position adéquate pour être photographié, le trou en face permet à la lumière de la led d'aller activer les photorésistances et de déclencher la prise de photo. Une fois le cliché pris et analysé, un servomoteur tourne un tuyau dans lequel le Skittle tombera et ainsi, ceux-ci sont triés.

schema_ok.png

2. Matériel et méthodes

2.1. Tâches préliminaires

2.1.1 Connexion au Raspberry

La toute première chose à faire est de se connecter au Raspberry PI. Pour ce faire, nous allons le mettre sous tension et le connecter au routeur avec un câble RJ45 (Ethernet). Démarrer un ordinateur, le connecter au LAN, télécharger nmap ici et effectuer la commande suivante dans un terminal :

$ sudo nmap -sP 192.168.0.0/24

Nous obtenons en retour la liste des IP locales de tous les appareils connectés au LAN, dont notre Raspberry. Voici un exemple de ce que la commande devrait nous donner:

Starting Nmap 6.40 ( http://nmap.org ) at 2015-12-21 09:16 CET
Nmap scan report for 192.168.0.103
Host is up (-0.097s latency).
MAC Address: B8:27:EB:86:C3:7D (Raspberry Pi Foundation)

Une fois l'adresse IP locale du Raspberry obtenue, nous allons nous y connecter en ssh (Sous windows, avec PuTTY) au nom de l'utilisateur pi, avec le mot de passe, par défaut "raspberry".

$ ssh pi@192.168.0.103

Lorsque la connexion est établie, nous nous retrouvons dans un terminal où il faut parler en bash. Je ne m'étalerai pas sur ce qu'est un terminal, si vous êtes ici vous savez probablement déjà ce dont il s'agit, mais voici tout de même un aide-mémoire des principales commandes utilisables.

Étant donné que nous utilisons un Raspberry Pi, le code qu'il s'impose d'utiliser est bien entendu le python. Beaucoup de tutoriels existent si vous êtes novices en la matière, tout comme je l'ai été avant la réalisation de ce projet. Tout d'abord, créons notre fichier avec cette commande :

$ touch monCode.py

Pour rappel, .py est l'extension utilisée pour les scripts python. Ensuite, il faut rendre le fichier exécutable, pour ce faire nous allons effectuer la commande suivante :

$ chmod 755 monCode.py

Finalement, ouvrir le fichier avec un éditeur de texte (nano ou vi par exemple):

$ nano monCode.py

Nous pouvons maintenant nous mettre à coder! Le code que j'ai écrit est disponible ici.

2.1.2. Schéma électrique et composants

Voici les composants que j'ai utilisés et le montage :

Untitled_Sketch_bb.png

À savoir que les résistances sont toutes de 330 Ohm.

2.2. Présentation du Skittle devant la caméra

2.2.1 Partie matérielle

Tout d'abord, les Skittles sont déversés dans un tube vertical, dont l'extrémité est posée sur une roue horizontale qui est toujours en rotation. Cette roue qui a l'épaisseur d'un Skittle (approximativement 1 cm) est percée de 2 trous de même diamètre qu'un Skittle. Le tube est positionné de manière à ce que lorsque la roue tourne, un Skittle à la fois prenne place dans un trou. Ceci permet de les prendre un à un. La roue est posée sur une plateforme sur laquelle les Skittles reposent. Après que la roue ait tourné d'environ un quart de tour, le Skittle arrive sous une caméra qui le prend en photo. La structure principale de ma machine est en briques Lego, qui sont extrêmement abondantes, bon marché et très maniables. J'ai créé la roue avec Sketchup et je l'ai concrétisée avec une imprimante 3D. À l'aide de ce même outil, j'ai également créé un support pour ma caméra, avec un emplacement pour accueillir une led blanche dont la fonction est d'éclairer le Skittle.

2.2.2. Partie électronique

Rien de bien compliqué ici, on a un moteur pour faire tourner la roue et un Raspberry Pi Camera Module. Le moteur doit être branché sur une alimentation externe, j'utilise 4 piles AA au lithium. J'ai tout d'abord tenté de faire fonctionner celui-ci à l'aide d'un transistor pour commander l'alimentation externe avec le Raspberry et d'une diode pour sécuriser le tout, mais comme au final la roue doit tout le temps être en mouvement, je suis allé à l'essentiel et j'ai directement raccordé le moteur à l'alimentation. Pour utiliser la caméra, il faut simplement la connecter au Raspberry. Ne faites pas comme moi, mais éteignez plutôt le Raspberry avant d'y connecter la caméra, à moins de vouloir la rendre hors d'usage! J'ai du changer de caméra à cause de cela et cela m'a causé quelques problèmes dont je parlerai plus bas.

2.2.3. Partie logicielle

Le moteur ne nécessite pas de code : on le met sous tension et hop, c'est parti! Pour utiliser la caméra, nous allons en premier installer python-picamera, qui comme l'indique son nom nous permettra d'utiliser très simplement la camera. On entre dans notre cher terminal les deux lignes suivantes : la première pour mettre à jour tout le système (ça ne fait jamais de mal) et la deuxième pour installer python-picamera.

$ sudo apt-get update
$ sudo apt-get install python-picamera

Une fois muni de ce formidable outil, nous pouvons commencer à écrire le code. Pour faciliter la conversion, il faut prendre une image au format .png, et à basse résolution (32x32 par exemple). Mon code se trouve à cette adresse. Prendre une photo se fait ainsi :

import picamera
camera = picamera.PiCamera()
camera.capture('image.png')

Il y a beaucoup de paramètres possibles, par exemple la résolution ou le format d'image. Aussi, plus d'infos sont disponibles ici. Ce n'est pas tout de savoir prendre une photo, encore faut-il savoir le faire au moment adéquat! C'est pourquoi nous allons passer à la partie suivante.

2.3. Prise du cliché au moment adéquat

2.3.1. Partie matérielle

La roue n'est pas percée de 2 trous par hasard : Lorsque le Skittle est en position idéale pour être photographié, la roue qui d'habitude coupe la lumière de la led laisse passer le faisceau lumineux par le trou opposé et celui-ci va titiller les photorésistances pour que celles-ci donnent le feu vert à la camera. À noter: les photorésistances sont isolées de toute autre lumière que la led.

2.3.2. Partie électronique

La led, qui peut être de n'importe quelle couleur tant qu'elle est détectée par les photorésistances, se branche sur le 5 V ou le 3.3 V avec une résistance de 330 Ohm. Le 3.3 est moins dangereux en cas de faux montage, mais le 5 assure une lumière plus intense, c'est donc avec celui-ci que j'ai choisi d'alimenter ma led. Une photorésistance est une résistance qui diminue plus elle est exposée à la lumière. Elle sera mise entre le 5 V et une Pin du GPIO. Il est important de savoir que contrairement à l'Arduino, le Raspberry Pi est incapable de lire une information analogique sur une de ses pins : à la place, la pin compare l'information reçue avec un certain seuil et restitue 1 ou 0, selon si la valeur est respectivement en-dessus ou en-dessous du seuil. Or à ma connaissance, il n'est pas possible de modifier ce seuil logiciellement. Et malheureusement, il était trop haut pour qu'une seule photorésistance puisse affecter la valeur rendue. J'ai donc monté pas moins de 6 photorésistances en parallèle. J'ai ainsi obtenu une sensibilité adéquate.

2.3.3. Partie logicielle

Nous allons utiliser le GPIO : les pins du raspberry. Il faut commencer le code par :

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

et toujours le finir par :

GPIO.cleanup()

Il va de plus falloir recourir à la programmation événementielle pour pouvoir prendre la photo au bon moment. Le code doit sans arrêt être en attente d'une hausse de luminosité. Je l'ai codé ainsi dans mon script :

GPIO.add_event_detect(LIGHT_PIN, GPIO.RISING,  callback=trigger, bouncetime=300)

On ajoute un événement occurrant lorsque la pin de la photorésistance observe une hausse de tension, et qui appelle une sous-routine nommée "trigger". On peut ajouter à la fin de la sous-routine quelques lignes empêchant la sous-routine de se déclencher juste après sa fin:

GPIO.remove_event_detect(LIGHT_PIN)
sleep(0.5)
GPIO.add_event_detect(LIGHT_PIN, GPIO.RISING, callback=trigger, bouncetime=300)

Maintenant que nous avons pris une photo au bon moment, il nous reste plus qu'à l'analyser et à l'utiliser! Rendons-nous à la section suivante.

2.4. Traitement de la photo et déplacement du tuyau

2.4.1. Partie matérielle

Le traitement de l'image est uniquement logiciel. Pour déplacer le tuyau dans lequel passera les Skittles, un servomoteur semble la meilleure solution. J'ai donc fixé un tuyau à un servomoteur et cela fait parfaitement l'affaire. De l'autre bout du tuyau, 5 compartiments de n'importe quelle sorte faisant offices de réceptacle conviennent.

2.4.2. Partie électronique

Pas grand-chose à dire ici, si ce n'est que le servo est un composant à 3 pattes: le 5V, le GND et l'information, qui est écrite en PWM, ou Pulse Width Modulation. Le PWM est une manière de simuler une sortie analogique en émettant un signal entier pendant une fraction de temps : Par exemple, on peut émettre un signal de 5 V 80% du temps pour simuler un signal de 4 (5 x 0.8) V. L'intégrale des deux fonctions de tension au cours du temps doivent être identique.

2.4.3. Partie logicielle

Pour définir le PWM, il faut prendre en compte 2 paramètres : la fréquence, et le rapport cyclique, ou duty. En python, nous pouvons par exemple écrire :

GPIO.setup(MOTOR_PIN, GPIO.OUT)
pwmotor = GPIO.PWM(MOTOR_PIN, 500)
pwmotor.start(66)

Pour identifier la couleur, j'ai choisi de convertir le fichier image en format .sng. Il s'agit d'un format texte qui affiche les composantes rgb de chaque pixel de l'image : c'est idéal pour la reconnaissance de couleurs. Il faut tout d'abord installer SNG à partir du terminal.

$ sudo apt-get install sng

Cependant, nous utilisons le python et non le bash pour notre script, il va donc falloir faire appel au bash depuis python avec les deux commandes suivantes :

import subprocess

au début du code, puis

subprocess.call ('sng', '/tmp/image.png')

Voici donc notre image convertie! L'analyse de la couleur se fait à partir de proportions entre les composantes rgb. Tout est dans mon code, je ne reviendrai pas dessus ici.

Voilà pour la conception de la machine! Regardons maintenant ce que ça a donné...

3. Résultats et Discussion

En tout premier lieu, voici une vidéo de la machine en plein fonctionnement. Hélas, vous l'aurez remarqué, il y a quelques problèmes... Avant tout, 3 jours avant la réédition de ce projet, ma caméra a rendu l'âme et j'ai du m'en procurer une autre. Mais mon vendeur, qui m'en a fourni une autre la veille de la réédition, n'avait plus que le modèle Pi NoIR,qui est dépourvue de filtre à infrarouges. Les images obtenues ne furent donc plus du tout pareilles, et mes algorithmes ne fonctionnaient plus alors que quelques jours auparavant, ils marchaient presque parfaitement... Un exemple magnifique qui montre qu'il y a un gouffre entre théorie et pratique. D'autre part, je comptais assurer la rotation de la roue à l'aide d'un moteur, mais j'ai également été pris de court au niveau du temps et je n'ai hélas pas pu mener à bien cette ambition. C'est cependant anecdotique car la rotation de la roue peut tout autant bien se faire à la main!

4. Conclusion

En conclusion, ce projet avait un grand potentiel qui n'a pas pu se révéler du fait des aléas de l'hardware. Je suis toutefois satisfait de mon code, qui théoriquement fonctionne. J'ai pu apprendre nombre de notions en concevant cette machine, et j'espère avoir à mon tour pu vous les transmettre via ce billet de blog. Si vous avez des questions, n'hésitez pas à me contacter à julien.sahli@gyp.educanet2.ch ou à juliensa98@gmail.com Le code que j'ai écrit est disponible ici.