Licence CC BY

Semaine 9 : Les imprimantes 3D

Si les machines qui impriment des objets en trois dimensions ne sont pas récentes, l'attention portée à la version grand public de ces machines grandit depuis quelques années. Cette semaine, nous nous lançons dans la découverte des machines CNC avec un focus sur les imprimantes 3D. Nous verrons brièvement comment fonctionnent ces machines et quels outils existent pour passer d'un fichier informatique à un objet 3D.

Pour cela, nous sommes partis à Brest pour rencontrer Arthur et Stéphane qui commercialisent des imprimantes 3D et qui nous expliquent comment fonctionne une imprimante 3D un peu particulière : la RepRap.

L'impression 3D

PRINCIPES DE L'IMPRIMANTE 3D

Merci d'avoir regardé cette première vidéo sur les principes de base de l'impression 3D.

Cette vidéo fait suite au cours de la semaine dernière où nous avons survolé les bases de la modélisation 3D avec Blender. Une fois votre modèle créé sous Blender, il ne reste plus qu'à l'exporter en .stl. Ce fichier peut ainsi être transformé en langage machine ou .gcode pour l'imprimer avec votre imprimante 3D ou celle de votre FabLab. C'est justement ce qu'on vous montre dans la vidéo ci-dessous. Aussi, il est fortement recommandé de lire les références proposées ici :

Références

Merci à Arthur Wolf et Stéphane Philippe, adhérents du TyFab et fondateurs de Ipso Factio. Merci également aux équipes des Petits Débrouillards Bretagne pour nous avoir permis de tourner au TéléFab à Brest.

PASSER D'UN MODÈLE 3D À DU LANGAGE MACHINE

ANNEXE : L'IMPRESSION 3D

L'IMPRIMANTE 3D POUR TOUS - FUTUREMAG - ARTE

Les interruptions sur Arduino

Les interruptions

Vous avez remarqué qu'il n'est pas si évident que ça de détecter l'appui sur un bouton si au même moment on est en train de gérer la circulation des voitures et des trains ! Si l'on pouvait simplement interrompre momentanément notre programme quand le bouton est appuyé…

Vous avez peut-être remarqué aussi que, dans les discussions autour des boutons poussoirs, parfois les mots "interruption" ou "interrupt" (anglais) ou "asynchrone" sont dits (ou parfois à peine chuchoté) ! 

Alors, on va regarder pourquoi certains experts répondent tout de suite "Hola, petit, va grandir un peu avant d'essayer ça", et que d'autres sourient sous cape.

C'est quoi ?

D'abord, il faut faire quelques petits rappels:

  1. Le microcontrôleur, le coeur de l'Arduino, "tourne" à une vitesse phénoménale : souvent 4,000,000 instructions par seconde, et ne s'arrête JAMAIS ;
  2. Cela dit, il ne fait qu'une chose à la fois : à l'instant où il est en train d'éclairer une LED il ne peut pas lire en même temps l'état d'une entrée ;
  3. Dans ce monde de vitesse nous, pauvres humains, nous ressemblons à des escargots avec nos réactions de l'ordre de dizaines de millisecondes !

Alors, comment faire en sorte que, si quelque chose d'important se produit, on puisse arrêter la tâche en cours et intervenir avant qu'il soit trop tard ?

Dans le monde numérique, on fait appel à des interruptions : un état signalé (provoqué par un événement à l'intérieur, ou par un signal extérieur) qui provoque une altération des séquences de traitements programmés.

Chaque type de processeur à ses propres façons de faire mais, en gros, voici ce qui se passe lors d'une interruption :

  • Le programme en cours est suspendu;
  • Le processeur mémorise l'endroit où il se trouvait (l'instruction qu'il était en train de préparer) ;
  • Il sauvegarde la valeur de certaines variables internes (sauvegarde d'état) ;
  • Il commence à exécuter un programme spécifique au type d'interruption…
    • (Pendant ce temps-là, notre programme à nous n'avance pas.)
    • Quand le traitement de l'interruption est terminé :
  • Le processeur récupère les variables sauvegardées ;
  • Il 'saute' à nouveau dans le programme d'origine, là où il en était.

Cela semble laborieux et lent mais à 4,000,000 instructions par seconde, cela ne prend même pas une milliseconde !

Une partie de cette séquence dépend du type de processeur mais l'essentiel, les instructions de traitement de l'événement, est sous notre contrôle : on peut lui dire quoi faire dans tel ou tel cas. Mais attention : si nous nous trompons dans notre code de traitement d'interruption, nos erreurs peuvent provoquer des symptômes assez difficiles à diagnostiquer. Vous voila prévenus…

Événement extérieur

Nous allons nous focaliser sur les événements extérieurs, que nous pouvons déclencher à notre guise. Sur l'Arduino UNO, deux broches sont équipées de détection d'interruption : les broches 2 (INT0) et 3 (INT1). Regardons ensemble comment on déclare que nous voulons traiter des interruptions sur l'une de ces deux broches :

1
attachInterrupt(interruption, fonction, mode);
  • interruption : le numéro d'interruption à traiter (sur UNO : "0" = broche 2 ; ou "1" = broche 3 )
  • fonction : le nom de la fonction à appeler (pas de passage de paramètres)
  • mode : spécifier dans quelles conditions l'interruption est à signaler : LOW, CHANGE, RISING, FALLING
Mode

Je ne l'ai pas dit, mais on est en train de parler d'événement externe, donc les broches 2 et/ou 3 devaient êtres déclarées en INPUT ou "INPUT-PULLUP", sinon on va provoquer des interruptions nous même si une broche affectée au traitement d'interruption change d'état (une source de soucis, déjà).  Alors, ces "modes", c'est quoi ?

  • LOW : provoquer une interruption quand la broche en question se trouve à l'état 0v ;
  • CHANGE : provoquer une interruption quand l'état de la broche en question change ;
  • RISING : provoquer une interruption quand la tension sur la broche en question monte (0v vers 5v) ;
  • FALLING : provoquer une interruption quand la tension sur la broche en question diminue (5v vers 0v).

Les plus vigilants d'entre vous sont en train de se demander "Et HIGH alors ?". Alors, ce n'est disponible QUE sur l'Arduino Due - mais le plus souvent on utilise des résistances (internes ou externes) de PULLUP, et donc l'état HIGH est, généralement, l'état de repos…

Fonction

Parfois la fonction est appelée ISR pour "Interrupt Service Routine" en anglais.  Nous voilà au coeur du problème : quoi faire avec cette interruption ?  Évidemment tout dépend de la raison de l'interruption : la baignoire qui déborde, le téléphone qui sonne, une trame TCP/IP qui arrive. Je peux vous donner quelques conseils, cependant.

  1. N'oubliez pas que tout le monde nous attend : dans cette fonction il faut faire le strict minimum, et le plus vite que possible ;
  2. Nous sommes pas chez nous !  Gare à nos gros sabots qui écrasent des variables ou modifient l'état du système - utiliser uniquement des variables déclarées localement, ou déclarées en volatile - et ne touchez à rien d'autre sauf si vous savez vraiment ce que vous faites!
  3. N'utilisez pas les instructions comme delay() ou les communications sur liaisons-séries (qui utilisent fréquemment des interruptions elles aussi). Si on veut voir l'état d'une variable à l'intérieur de notre fonction, sauvegardez sa valeur dans une autre variable (déclarée en globale et volatile) et l'afficher avec lcd.print() ou serial.print() depuis le programme principal.
Faire le strict minimum, et le plus vite que possible

Par exemple, si notre interruption porte sur la détection d'événement physique, comme l'appui sur un bouton, n'essayez pas de traiter les cas provoqués par cet appui mais simplement rendre cette information disponible pour notre programme. Allez, je pense qu'un montage avec l'Arduino sera plus efficace que tout ce blabla.

Détection de bouton

Nous allons faire un montage très simple : un bouton (condensateur conseillé mais pas obligatoire) :

Détection de bouton

Et un sketch aussi assez simple :

Déclarations :
1
2
3
4
#define boutonPin  2  // C'est l'entrée INT0
//  Pour qu'on puisse changer la valeur d'une variable depuis une fonction de
// gestion d'interruption, il faut que la variable soit déclarée "volatile"
volatile boolean changed = false;
Notre fonction ISR à nous :

(à ajouter après la } à la fin du loop() ou avant setup() )

1
2
3
4
void doContact() {
   changed = true;
   // Difficile de faire + court !
}
Activer l'interruption INT0, attacher notre ISR :

(dans setup() )

1
attachInterrupt(0, doContact, FALLING);
Et la boucle loop()
1
2
3
4
5
6
7
void loop(){
    if ( changed ) {
        changed = false;
        Serial.println("Ha ! Vous avez touché le bouton");
    }
    delay(1000);
}

Notez bien que nous ne nous soucions plus du bouton dans notre code principal.  Si la variable changed reste à l'état "faux", la boucle ne fait qu'attendre !  Ni vu, ni connu, notre fonction doContact a modifié la valeur de changed à l'instant où nous avons appuyé sur le bouton.  Le délai avant que le message s'affiche est tout simplement le delay(1000) qui continue à décompter.

Exemple complet :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
  Exemple pour démontrer l'utilisation des interruptions.

  Bouton poussoir, connecté entre GND et la broche 2 (INT0).

  Résistance PULLUP activé pour cette broche.  Condensateur de 100nF
  en parallèle avec le bouton recommandé.

  Glenn Smith.   MOOC Fabrication Numérique, mai 2014

*/ 

#define boutonPin  2  // C'est l'entrée INT0

//  Pour qu'on puisse changer la valeur d'une variable depuis une fonction de
// gestion d'interruption, il faut que la variable soit déclarée "volatile"
volatile boolean changed = false;

// Notre fonction de traitement d'interruption.  Le strict minimum, souvenez-vous.
void doContact() {
  changed = true;
  // Difficile de faire + court
}

void setup() { 
  // Broche en entrée avec résistance de pull-up
  pinMode(boutonPin, INPUT_PULLUP);

  // Attacher notre fonction ISR, détection de flanc descendant (5v vers 0v)
  attachInterrupt(0, doContact, FALLING);

  // Montrer que nous sommes la 
  Serial.begin (115200);
  Serial.println("Hello");
} 

void loop(){
  if ( changed ) {
    changed = false;
    Serial.println("Ha ! Vous avez touché le bouton");
  }
  delay(1000);
  // Vous pouvez ajouter du code ici pour faire clignoter un led, etc.
}

Suite

Dans le Wiki je vais publier un article utilisant cette technique pour 'dompter' un bouton rotatif - un must pour augmenter les possibilités d'interface humain / Arduino.  Pour ceux qui n'ont pas cet article dans leur kit, la même technique est aussi expliquée avec des boutons "classiques".

Bonne semaine à vous.

Merci à Glenn Smith pour ce cours !

Travaux pratiques

TP (1/2) À FAIRE POUR LA SEMAINE 10

Cette semaine, nous revenons à nos histoires de feu avec une barrière et un compteur de voiture. Grâce au cours de Glenn la semaine passée, le fonctionnement des écrans LCD ne devrait plus avoir de secrets pour vous. Voici donc les consignes :

Le montage à réaliser devra comporter :

  • Un servomoteur qui jouera le rôle de barrière ;
  • Un écran LCD qui viendra afficher le nombre de voitures passées depuis que l'Arduino est branché ;
  • Un bouton pour demander l'ouverture de la barrière (et qui viendra incrémenter le compteur de voitures) ;
  • Un feu bicolore qui passera au vert lorsque la barrière sera complètement ouverte.

Fonctionnement de l'exercice

Le scénario sera le suivant :

Le fonctionnement normal est un feu allumé au rouge, une barrière fermée (0°) et un afficheur LCD qui affiche sur la première ligne "Voiture numéro:" puis sur la seconde ligne le nombre de fois où le bouton a été appuyé depuis le démarrage de l'Arduino. Le fonctionnement normal est interrompu par l'appui sur un bouton poussoir.

Si l'appui du bouton est détecté, alors la barrière (actionnée par le servomoteur) se relève doucement. Lorsque la barrière est à la verticale (90°), le feu vert s'allume pendant 5 secondes pendant lesquelles la barrière reste ouverte (90°). Après les 5 secondes, le feu repasse au rouge, la barrière redescend doucement et on vient ajouter un au compteur affiché sur la seconde ligne de l'écran LCD. Enfin, le fonctionnement normal reprend.

Impératif : Votre code devra contenir une fonction appelée mouvementBarriere() prenant deux paramètres : la position de départ et la position d'arrivée. Cette fonction devra être capable de lever ou baisser la barrière en fonction de la valeur de ces paramètres.

Aussi, nous souhaitons recevoir le message "Voiture numéro:" suivi du nombre d'appuis sur le bouton dans le moniteur série lorsque l'appui a été détecté.

Quelques indices

Vous aurez besoin de mobiliser toutes les compétences vues ces dernières semaines pour réaliser ce TP :

  • L'utilisation de boucles for ou while ;
  • L'utilisation d'entrée et de sorties numériques ;
  • Utilisation de librairies et d'un servomoteur ;
  • Utilisation des instructions Serial ;
  • Déclaration d'une fonction ;
Quelques conseils
  • Avertissez-nous sur le fil de discussion ci-dessous si les consignes ne vous semblent pas claires ;
  • N'allez pas regarder la solution sur Internet sinon il n'y a pas de fun ;
  • Prenez toujours les hypothèses qui vous arrangent :) ;
  • Seules les notions abordées dans le cours et sur cette page sont nécessaires pour mener à bien ce TP ;
  • Il n'y a pas une mais plusieurs solutions à chaque problème. La meilleure est celle que vous comprenez !

Bon courage et bonne semaine,

L'équipe du MOOC

TP (2/2) complémentaire

Grâce à Slic3r, générez le .gcode de votre modèle 3D d'avion conçu la semaine dernière avec Blender. N'hésitez pas ensuite a partager sur le forum ou sur Twitter avec le hashtag #MoocFab ou sur la communauté Google+.