Tag - arduino

Entries feed

Sunday, October 23 2016

Mesurer l'humidité avec une sonde DHT22 et la température avec une sonde DS18B20 sur Arduino, transférer l'information à un Raspberry Pi

L'objectif de ce billet est d'illustrer l'appariement et le travail synchronisé d'un Arduino et d'un Raspberry Pi. Concrètement, l'Arduino mesure l'humidité avec une sonde DHT22 et la température avec une sonde DS18B20 et l'objectif est de transférer cette information à un Raspberry Pi qui traite l'information et l'envoie sur Internet.

Certains se demanderont pourquoi ne pas tout faire directement avec le Raspberry Pi :

  1. on peut imaginer que tous les ports du Pi sont déjà utilisés
  2. ou que le montage se complique et qu'il n'est plus possible de tout gérer depuis le Pi mais qu'il est plus aisé de lui adjoindre une (ou des) planche(s) Arduino

Principe de communication entre Raspberry Pi et Arduino

Nous allons utiliser un lien série entre les 2 composants au travers d'une connexion USB qui relie les deux équipements. Concrètement, le Raspberry Pi enverra des ordres à l'Arduino sur le port série et écoutera attentivement la réponse qui viendra également sur le port série.

Code Arduino

Mesurer la température avec une sonde DS18B20

Pour faciliter les choses, on utilisera la bibliothèque DallasTemperature.h (disponible ici sur GitHub). Le code est développé ci-dessous et ne présente aucune difficulté particulière :

#include <OneWire.h> // Inclusion de la librairie OneWire
#include "DallasTemperature.h" //Librairie du capteur

// Initialize 1-wire
OneWire oneWire(10); //Bus 1-Wire sur la pin 10 de l'arduino
DallasTemperature sensors(&oneWire); //Utilistion du bus Onewire pour les capteurs
DeviceAddress sensorDeviceAddress; //Vérifie la compatibilité des capteurs

void doMeasures() {
  sensors.requestTemperatures(); //Demande la température aux capteurs
  Serial.print("temperature=");
  Serial.println(sensors.getTempCByIndex(0)); //Récupération de la température en degrés celsius du capteur n°0
}

// setup()
void setup() {
  sensors.begin(); //Activation des capteurs
  sensors.getAddress(sensorDeviceAddress, 0); //Demande l'adresse du capteur à l'index 0 du bus
  sensors.setResolution(sensorDeviceAddress, 11); //Résolutions possibles: 9,10,11,12
}

Pour mesurer la température, on appellera la fonction doMeasures().

Mesurer l'humidité avec une sonde DHT22

Là encore, le code n'est pas bien compliqué tant que l'on utilise la librairie DHT.h (par exemple celle d'Adafruit).

#include "DHT.h"

// Initialisation du capteur DHT
#define DHTPIN 12    // Pin sur lequel la sonde DHT 22 est attachée
#define DHTTYPE DHT22   // Type de sonde DHT22 : AM2302, AM2321
DHT dht(DHTPIN, DHTTYPE);

void doMeasures() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
  }

  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print("humidity=");
  Serial.println(h);
  Serial.print("temperature="); //Oui, un DHT22 ça mesure aussi la température :-) 
  Serial.println(t);
  Serial.print("heat_index=");
  Serial.println(hic);
}

// setup()
void setup() {
  dht.begin();
}
Écoute sur le port série et actions

Là encore, pas de surprise. La boucle loop() est utilisée pour réagir quand des données sont présentes sur l'interface série. On détecte la nature de l'appel et on peut imaginer différents comportements selon le message reçu. Par exemple, un caractère pourra déclencher le relevé de l'humidité sur DHT22 tandis qu'un autre caractère reçu déclenchera la prise de température sur la sonde DS18B20.

//setup()
void setup() {
  Serial.begin(9600); // Initialisation du port série
}

// for incoming serial data
int incomingByte = 0;
String res = "";

// loop()
void loop() {
  // On écoute sur le port série
  if (Serial.available() > 0) {
          // On lit le contenu du message série et selon le caractère reçu on déclenche une action différente
          incomingByte = Serial.read(); 
          if (incomingByte == 103) { //g
            doAction1();
          }
          if (incomingByte == 104) { //h
            doAction2();
          }
  }
}
Il suffit alors de tout combiner !

Il n'est pas difficile de combiner ces trois morceaux de code !

#include "DHT.h"
#include <OneWire.h>
#include "DallasTemperature.h" 

// Initialize DHT sensor.
#define DHTPIN 12
#define DHTTYPE DHT22  
DHT dht(DHTPIN, DHTTYPE);

// Initialize 1-wire
OneWire oneWire(10);
DallasTemperature sensors(&oneWire); //Utilistion du bus Onewire pour les capteurs
DeviceAddress sensorDeviceAddress; //Vérifie la compatibilité des capteurs

// for incoming serial data
int incomingByte = 0;
String res = "";

void doMeasures() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
  }

  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print("humidity=");
  Serial.println(h);
  Serial.print("temperature=");
  Serial.println(t);
  Serial.print("heat_index=");
  Serial.println(hic);

  sensors.requestTemperatures(); //Demande la température aux capteurs
  Serial.print("temperature=");
  Serial.println(sensors.getTempCByIndex(0)); //Récupération de la température en celsius du capteur n°0
}

// setup()
void setup() {
  Serial.begin(9600); // Initialisation du port série
  dht.begin();
  sensors.begin(); //Activation des capteurs
  sensors.getAddress(sensorDeviceAddress, 0); //Demande l'adresse du capteur à l'index 0 du bus
  sensors.setResolution(sensorDeviceAddress, 11); //Résolutions possibles: 9,10,11,12
}

// loop()
void loop() {
  // send data only when you receive data:
  if (Serial.available() > 0) {
          // read the incoming byte:
          incomingByte = Serial.read();
          if (incomingByte == 103) { //g
            doMeasures();
          }
  }
}

Code sur le Raspberry Pi

Nous allons utiliser un script Python qui se connectera via le port série à l'Arduino et :

  1. émettra le signal déclenchant l'action (dans notre cas le caractère "g")
  2. écoutera pendant 20 secondes l'éventuelle réponse
  3. transmettra la réponse à un serveur distant dans une requête GET
import serial
import os
import glob
import time
import requests

#Timeout de 20 secondes
tf = time.time()+20

#Initialisation du port série /dev/ttyUSB0 (cela peut varier selon la version de Raspbian et le type de planche Arduino, /dev/ttyUSB0 semble le défaut avec Raspbian Jessie et un Arduino Nano328)
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

#On attend 2 secondes : si l'on écrit trop vite après l'ouverture du bus série, la communication risque d'échouer
time.sleep(2)

#On écrit le caractère "g" (ASCII 103) sur le port série
print("Now, we are sending the command to Arduino!")
ser.write("g".encode())

#Et on boucle désormais en lecture sur le port série
while time.time()<tf:
  line = ser.readline()
  if line:
    result = str(line).rstrip('\r\n')
    print(result)
    try:
      #Dans notre cas, le résultat brut de l'Arduino est passé à un serveur distant qui stocke l'information
      r = requests.post('https://monserveurdecollectedesdonnees', data=result, timeout=5.0)
      print(str(r.status_code)+" "+result)
    except:
      print("Failed, with payload: "+result)

#On ferme le canal de communication
ser.close()

Ce script peut alors être placé dans le crontab du système pour être exécuté périodiquement.

Sunday, February 7 2016

Transformer une découpeuse laser avec Arduino et Grbl

De nombreuses découpeuses laser sont disponibles sur AliExpress (plateforme de vente chinoise) à des tarifs défiant toute concurrence. L'usage d'une découpeuse laser était d'ailleurs présentée dans le numéro de décembre de Linux Pratique (page 24, "Réalisez des gravures laser à l'aide d'Inkscape").

flowRoot4158.jpg

Attention ! Une découpeuse laser est un outil dangereux : les lasers utilisés sont très puissants et provoqueraient la cécité totale de toute personne qui regarderait le faisceau même brièvement. Équipez-vous de lunettes avec un abattement optique suffisant dans la longueur d'onde de travail et ne regardez jamais le faisceau même équipé. Méfiez-vous également des réflexions lumineuses scélérates ! Enfin, les matérieux découpés peuvent s'enflammer sous l'action du laser. L'usage d'une découpeuse laser nécessite une attention constante !

La découpeuse laser sur laquelle je mettais la main dernièrement avait un défaut majeur : elle n'était contrôlable qu'à l'aide de deux binaires chinois impossibles à exécuter sous Linux et à la qualité médiocre... Qu'à cela ne tienne : conservons le matériel mais remplaçons l'intelligence par un Arduino équipe de Grbl.

À propos de Grbl

Grbl (https://github.com/grbl/grbl) est un micrologiciel libre développé sur Arduino pour contrôler des graveuses CNC (Computer Numerical Control), i.e. des fraiseuses munis d'une tête mobile contrôlée en X, Y et Z par un ordinateur. Grbl interprète du G-code (cf. plus bas) et déplace en conséquence un outil sur 3 axes (X, Y et Z) et contrôle la puissance de cet outil. Il comprend de multiples optimisations sur l'usage et le déplacement des moteurs afin de gérer correctement les accélérations, les trajectoires...

Dans le cas de notre laser, nous n'aurons pas d'axe Z et nous nous contenterons d'utiliser Grbl pour contrôler X, Y et la puissance du laser (que l'on contrôlera comme la vitesse de rotation d'une fraise).

À propos de G-code

Le G-code est un langage de programmation inventé dans les années 1950 pour le contrôle des machines CNC. Il comprend un certain nombre d'instructions pour le contrôle d'équipements, par exemple :

G21 (définit l'unité de travail comme étant le millimètre)
M5 (éteint l'outil : la fraise, le laser)
F400 (choisit une vitesse de déplacement de 400 mm/min)
S500 (définit la puissance de l'outil : 500 RPM pour la fraise)

G00 X5 Y5 Z5 (déplacer l'outil vers [x,y,z] = [5,5,5] en laissant la machine choisir le chemin)
G01 X10 Y10 (déplacer l'outil vers [x,y] = [10,10] en effectuant une ligne droite, on ne change pas Z)
G02 X20 Y10 I5 J0 (effectuer un arc de cercle de centre [x,y] = [15,10] jusqu'au point [x,y] = [20,10])
M3 (démarre l'outil à la puissance sélectionnée auparavant i.e. S500)
...
M5 (éteint l'outil)

Il est à noter que Grbl ne supporte pas toutes les instructions du G-code (il y a des commandes exotiques qui n'ont pas un intérêt sensationnel et qui alourdiraient le code chargé sur Arduino) mais les principales sont bien gérées.

Mise en pratique

On supprime donc l'électronique chinoise embarquée initialement et on la remplace par un Arduino couplé à deux easydrivers pour contrôler les moteurs (stepper motors) contrôlant les axes X et Y ainsi que le laser. Le laser est contrôlé par 3 fils : une alimentation, une masse et un fil de contrôle par modulation TTL i.e. envoi d'un signal carré avec une fréquence de plus en plus élevée (jusqu'à 10 kHz) qui commande la puissance.

Le circuit ressemble alors à ceci : laser_sketch.png

On peut alors charger le micrologiciel Grbl sur l'Arduino comme décrit ici. Si on se connecte en série à l'Arduino (avec un baud rate à 115 200), on doit alors voir à l'allumage :

Grbl 0.9j ['$' for help]

Grbl (version 0.9j) est prêt à recevoir nos commandes !

On peut alors lancer les commandes de son choix dans le port série pour interagir avec Grbl et contrôler la découpeuse laser.

Pour plus d'aisance, on pourra installer un logiciel de contrôle tel que UniversalGcodeSender disponible ici.

Screenshot_2016-02-07_05-57-43.png

La machine est désormais prête à recevoir des instructions en G-code. Il ne reste plus qu'à utiliser la méthode de son choix pour générer les G-codes de ses créations.

Générer des G-codes avec Inkscape

Il existe des extensions pour générer les G-codes à partir de chemins vectoriels dans Inkscape. L'extension de base est même installée par défaut dans Inkscape :

Screenshot_2016-02-07_06-05-01.jpg

On pourra se référer à ces documentations pour l'utiliser, éventuellement en adaptant quelque peu au cas du laser pour lequel l'axe Z ne compte pas et les vitesses peuvent être plus élevées :

Quelques ordres de grandeur

Avec un laser de 5.5W à la longueur d'onde de 450 nm (laser bleu) :

  • on dessine joliment sur du carton brun à F400 / S600
  • on découpe 1 mm de bois avec F200 / S1000 en repassant 4 fois sur le trait
  • on grave le bois clair avec F200 / S1000 et un seul passage

Bonne gravure et bon découpage laser !

Saturday, February 6 2016

ino pour Arduino : compiler, envoyer et écouter en série sans l'IDE Arduino

L'Arduino IDE est super pour débuter. Mais rapidement, on peut se sentir un peu à l'étroit dans l'outil. Je l'ai donc avantageusement remplacé par mon éditeur de texte habituel (Atom) et "ino" (http://inotool.org/) pour communiquer avec les planches Arduino.

Installer ino

ino s'installe facilement sur une machine munie de Python2.7 par :

pip install ino

ou alors en récupérant les sources d'ino ici.

Il faut également installer l'IDE Arduino et picocom pour la communication sur le port série - sur Debian Jessie on pourra l'installer ainsi :

apt install arduino picocom

Utiliser ino

Avant toute chose, on crée un nouveau projet :

mkdir mon_projet
cd mon_projet
ino init

On place alors le code de son choix dans le fichier 'sketch.ino' placé dans le dossier 'src'.

Pour compiler :

ino build

Pour envoyer sur l'Arduino :

ino upload

Et pour écouter sur le port série :

ino serial

Pour aller plus loin

On pourra lancer :

ino --help

ou aller lire ici : http://inotool.org/quickstart

Constuire un photomètre avec Arduino

Nous allons expliquer ici comment fabriquer un photomètre avec la plateforme Arduino et le composant BH1750 (encore appelé GY-30, fiche technique ici) que l'on trouve pour quelques euros chez les bons revendeurs électroniques.

Un photomètre qui parle en série

Une première version du photomètre sera simple : nous utiliserons les facultés d'Arduino à communiquer via un port série pour afficher le niveau de luminosité mesuré. Le circuit est alors assez simple (cf. représentation ci-dessous) :

  • le pin VCC du capteur se connecte au pin 5V de l'Arduino
  • le pin GND du capteur se connecte au pin GND de l'Arduino
  • le pin SDA du capteur se connecte au pin A4 (Analogique 4) de l'Arduino
  • le pin SDL du capteur se connecte au pin A5 (Analogique 5) de l'Arduino

Uno_et_BH1750.png

On compile alors le code suivant et on le charge sur l'Arduino (par exemple avec l'IDE Arduino) :

#include <Wire.h>
 
int BH1750_address = 0x23; // i2c Addresse
byte buff[2];
 
void setup() {
  
  Wire.begin();
  BH1750_Init(BH1750_address);
  
  delay(200);
  Serial.begin(9600);
  Serial.println("Démarrage du système... patientez svp !");
}
 
void loop() {
  
  float valf=0;
 
  if(BH1750_Read(BH1750_address)==2){
    valf=((buff[0]<<8)|buff[1])/1.2;
  
    if(valf<0) {
      Serial.print("> 65535");
    }
    else {
      Serial.print((int)valf,DEC);
    }
    Serial.println(" lx"); 
  }
  delay(1000);
}
 
void BH1750_Init(int address) {
  Wire.beginTransmission(address);
  Wire.write(0x10); // 1 [lux] aufloesung
  Wire.endTransmission();
}
 
byte BH1750_Read(int address) {
  byte i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()) {
    buff[i] = Wire.read(); 
    i++;
  }
  Wire.endTransmission();  
  return i;
}

Et hop, sur le port série, on peut voir :

Démarrage du système... patientez svp !
92 lx
92 lx
92 lx
75 lx
47 lx
342 lx
43 lx

Un photomètre avec son propre écran LCD

Rajoutons un écran LCD pour afficher le résultat sans avoir à ouvrir un port série ! Nous allons donc brancher un LCD Keypad Shield (tel qu'ici) sur l'Arduino, et nous allons modifier le code comme suit :

#include <Wire.h>
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int BH1750_address = 0x23; // i2c Addresse
byte buff[2];

void setup() {

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Look the world");

  Wire.begin();
  BH1750_Init(BH1750_address);

  delay(200);
  Serial.begin(9600);
}

void loop(){
  float valf=0;
  if(BH1750_Read(BH1750_address)==2) {
    valf=((buff[0]<<8)|buff[1])/1.2;
    if(valf<0) {lcd.setCursor(0,0); lcd.print("> 65535 lx");}
    else {lcd.setCursor(0,0); lcd.print((int)valf,DEC); lcd.print(" lx                    ");}
  }
  else {
    lcd.setCursor(0,0); lcd.print("Error...             "+BH1750_Read(BH1750_address));
  }
  delay(1000);
}

void BH1750_Init(int address) {
  Wire.beginTransmission(address);
  Wire.write(0x10); // 1 [lux] aufloesung
  Wire.endTransmission();
}

byte BH1750_Read(int address){
  byte i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()){
    buff[i] = Wire.read();
    i++;
  }
  Wire.endTransmission();
  return i;
}

On compile et on charge sur l'Arduino, et hop le tour est joué !

photometre.jpg

Saturday, July 18 2015

Raspberry Pi, un relai, quelques branchements : interrupteur intelligent

La mission du jour était simple : redémarrer électriquement un serveur lorsqu'il cessait de répondre au ping. Défi relevé à l'aide d'un Pi, d'un relai et de quelques lignes de bash (et aussi un peu de python).

Parlons d'abord du relai

Un relai est un petit équipement électronique qui joue le rôle d'interrupteur contrôlable. Il existe de nombreuses cartes (pour Arduino notamment) qui comportent des relais en nombre variable : partons sur carte simple munie d'un seul canal.

relai.jpg

Le principe de fonctionnement d'un relai est assez simple : une langue métallique, asservie par un ressort, ferme par défaut un circuit. En présence d'un champ électrique dans une bobine, un champ magnétique induit déplace la langue métallique qui vient alors fermer un second circuit. Comme un simple dessin vaut mieux qu'un long discours :

principe-relai.jpg

Beaucoup plus d'information sur le principe d'un relai se trouve ici : http://www.astuces-pratiques.fr/electronique/le-relais-principe-de-fonctionnement.

Les relais que nous trouvons classiquement comportent pour chaque canal :

  • un bornier destiné au courant alternatif (attention lors de la manipulation ; ce n'est plus du 5V dans le circuit mais du 220V - il convient donc d'être particulièrement prudent notamment lors de l'usage en ne laissant pas le circuit électrique en libre accès !)
  • 3 connecteurs pour le contrôle :
* un lien à la terre (par ex. GND ou G)
* un lien à l'alimentation 5V (par ex. Vcc ou V) : à brancher sur les pins d'alimentation
* un pôle pour le contrôle (par ex. IN ou S)

Par défaut, en absence de toute alimentation, 2 des bornes du bornier alternatif sont reliées. Lorsque le relai sera alimenté et que le pin d'entrée (IN ou S) sera amené au potentiel 5V, une bascule de circuit ouvert/fermé s'effectuera. Selon le cas d'usage, on pourra préférer avoir une alimentation active par défaut ou bien une alimentation coupée par défaut... il suffira d'adapter le branchement dans le bornier alternatif.

Branchement du relai sur le Pi et contrôle du relai par le Pi

Tout simplement : Rpi_et_relai.png

et dès que l'on commandera au Pi de basculer le GPIO (7e pin sur la planche, selon la numérotation de la planche) alors le relai basculera.

Je ne présente pas ici le branchement au niveau du relai qui n'est pas bien compliqué si on le considère comme un simple interrupteur. Il conviendra seulement de placer l'interrupteur sur la phase (il est toujours plus prudent de couper la phase et non le neutre !).

Pour contrôler le relai, on pourra exécuter le code suivant en Python sur le Pi :

#! /usr/bin/python
import RPi.GPIO as GPIO ## Import GPIO library
GPIO.setmode(GPIO.BOARD) ## Use board pin numbering
GPIO.setup(7, GPIO.OUT) ## Setup GPIO Pin 7 to OUT
GPIO.output(7,True) ## Turn on GPIO pin 7

GPIO.output(7,True) pourra bien sûr être remplacé par GPIO.output(7,False) pour effectuer la bascule inverse.

Dans mon cas (c'est selon le branchement du relai), l'ouverture du circuit (i.e. son interruption) est commandée par ouvrir-circuit.py :

#! /usr/bin/python
import RPi.GPIO as GPIO ## Import GPIO library
GPIO.setmode(GPIO.BOARD) ## Use board pin numbering
GPIO.setup(7, GPIO.OUT) ## Setup GPIO Pin 7 to OUT
GPIO.output(7,True) ## Turn on GPIO pin 7

et la fermeture du circuit par fermer-circuit.py :

#! /usr/bin/python
import RPi.GPIO as GPIO ## Import GPIO library
GPIO.setmode(GPIO.BOARD) ## Use board pin numbering
GPIO.setup(7, GPIO.OUT) ## Setup GPIO Pin 7 to OUT
GPIO.output(7,False) ## Turn off GPIO pin 7

Et ce petit script bash (eteint-redemarre.sh) effectue une déconnexion/reconnexion de l'alimentation avec 5 secondes de pause intercalaire :

#!/bin/sh
/path/to/ouvrir-circuit.py 
sleep 5
/path/to/fermer-circuit.py 

Détecter la chute du serveur pour en provoquer le redémarrage

On peut alors demander au Pi de surveiller un hôte particulier et d'en provoquer le redémarrage électrique à l'aide de ce script :

#! /bin/sh
HOST=192.168.1.3
LOGFILE=/tmp/ce_que_le_pi_surveille.log
ping -c5 $HOST > /dev/null 2> /dev/null
if [ $? -eq 0 ] 
then 
	echo `date +%Y-%m-%d\ %H:%M` Host found >> $LOGFILE 
else
	echo `date +%Y-%m-%d\ %H:%M` Host not found >> $LOGFILE
	/path/to/eteint-redemarre.sh
fi

Et voilà, le tour est joué !

Sunday, April 5 2015

De belles rondeurs avec la Materia 101 d'Arduino

L'imprimante 3D Materia 101 d'Arduino est une très belle petite machine dont je ne peux que conseiller l'acquisition à tout amateur de nouvelles technologies. Assez peu chère, de qualité, et tout à fait libre, elle ravira ses utilisateurs. Fidèle à l'esprit Arduino, il s'agira plus d'une machine à usage éducatif (le montage étant déjà très instructif car permettant de comprendre en détail le fonctionnement des machines d'impression 3D) qu'un outil de production à grande échelle.

Après son montage, et au cours des premières impressions, nous avons toutefois constaté que les cercles n'étaient pas parfaitement ronds. Après avoir envisagé de nombreux paramètres (notamment réduire la vitesse d'impression pour éviter les vibrations trop importantes de la machine), nous avons réalisé qu'il fallait mettre en tension le plus possible les courroies de déplacement sur l'axe Y (les cercles étaient légèrement elliptiques sur cet axe).

Pour déplacer la tête d'écriture sur l'axe Y, 3 courroies sont impliquées. La première transfère le mouvement du moteur Y à l'axe général qui entraîne ensuite 2 autres courroies auxquelles est fixé le chariot de la tête de lecture.

Première étape : positionner le moteur Y pour mettre la courroie qui y est attachée très en tension : Ymotor.jpg

Deuxième étape : serrer les vis qui mettent en tension les courroies comme indiqué ci-dessous : screw_circleadjust.jpg

Dans notre cas, ce réglage effectué, les ronds étaient bien ronds - ce qui a permis à nos pièces de parfaitement s'emboîter les unes aux autres !

Bonne impression 3D !