2024-04-12 17:45:33 +02:00
|
|
|
|
+++
|
|
|
|
|
title = "Robot timide – le robot qui fuit la lumière"
|
|
|
|
|
description = "Création d'un robot timide pour un projet scolaire."
|
|
|
|
|
date = 2022-05-19
|
|
|
|
|
|
|
|
|
|
[taxonomies]
|
|
|
|
|
tags = ["maker", "fablab", "robotique"]
|
|
|
|
|
+++
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
Création d'un robot timide pour un projet scolaire.
|
|
|
|
|
|
|
|
|
|
> Article cloné depuis [Eirlab](https://www.eirlab.net/2022/05/19/robot-timide-le-robot-qui-fuit-la-lumiere/)
|
|
|
|
|
|
|
|
|
|
Dans le cadre de l’option Makers proposée en deuxième année à l’ENSEIRB-MATMECA,
|
|
|
|
|
en filière Informatique, un robot timide a vu le jour au sein d’Eirlab.
|
|
|
|
|
Cet article est un guide pour expliquer comment reproduire notre travail, dans
|
|
|
|
|
le plus pur esprit Maker.
|
|
|
|
|
|
2024-04-12 17:45:33 +02:00
|
|
|
|
<!-- more -->
|
|
|
|
|
|
|
|
|
|
![Une vue de 3/4 face du robot finalisé](images/robot_timide_header.jpg)
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
## Concept de base
|
|
|
|
|
|
|
|
|
|
Nous voulions mettre en oeuvre un robot qui détecterait en temps réel la
|
|
|
|
|
luminosité autour de lui et ce dans le but de se déplacer vers l’endroit le
|
|
|
|
|
plus sombre de la pièce dans lequel il se trouve, et de s’y cacher. Un autre
|
|
|
|
|
mode est aussi disponible, permettant non pas d’aller vers l’endroit le plus
|
|
|
|
|
sombre, mais à l’inverse de fuir l’endroit le plus lumineux, pour avoir deux
|
|
|
|
|
manières de voir le problème.
|
|
|
|
|
|
2024-04-12 17:45:33 +02:00
|
|
|
|
![Une vue de face du robot timide dans sa forme finale.](images/robot_timide_enseirb.jpg)
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
## Du matériel
|
|
|
|
|
|
|
|
|
|
Avant de pouvoir travailler sur une partie logicielle du projet, il faut
|
|
|
|
|
évidemment avoir une base physique pour accueillir et exécuter ce code.
|
|
|
|
|
|
|
|
|
|
À noter que ce projet n’a nécessité aucune dépense et a été réalisé entièrement
|
|
|
|
|
avec du matériel déjà disponible au sein du Fablab.
|
|
|
|
|
|
|
|
|
|
### Liste du matériel
|
|
|
|
|
|
|
|
|
|
Pour pouvoir reproduire ce projet, il vous faudra avoir en votre possession les
|
|
|
|
|
éléments suivants :
|
|
|
|
|
|
|
|
|
|
- 1x Arduino Uno (ou clone équivalent) – c’est la tête pensante de ce projet
|
|
|
|
|
- 1x Arduino Motor Shield – pour contrôler les deux moteurs du robot
|
|
|
|
|
- 2x moteurs à courant continu, ici des FT DC 130D – pour se mouvoir dans l’espace
|
|
|
|
|
- 3x capteurs de distance à ultrasons HC-SR04 – pour éviter de rencontrer des murs trop souvent
|
|
|
|
|
- 4x photo résistances – une par côté, pour pouvoir détecter la luminosité autour de lui
|
|
|
|
|
- 4x résistances de 2kΩ – pour le circuit des photo résistances, permettant d’avoir une amplitude optimale
|
|
|
|
|
- 1x pile 9 Volts – pour alimenter tout le système
|
|
|
|
|
- 1x boîtier pour pile 9 Volts [OPTIONNEL] – pour éviter de perdre l’unique source d’alimentation du robot
|
|
|
|
|
|
|
|
|
|
### Base du châssis
|
|
|
|
|
|
|
|
|
|
Le châssis est une plaque en bois, ici du contreplaqué de 5 millimètres
|
|
|
|
|
d’épaisseur, qui a été usinée à l’aide de la découpeuse laser du Fablab. Elle
|
|
|
|
|
mesure 17×15,5 centimètres, et dispose de deux bords biseautés pour avoir une
|
|
|
|
|
vue frontale des obstacles que le robot pourrait rencontrer. Ici, ces biseaux
|
|
|
|
|
ont des angles de 20 degrés, sur 4,5 centimètres. La plaque de base est ensuite
|
|
|
|
|
percée pour accueillir les différents modules du robot. Les éléments les plus
|
|
|
|
|
légers ou risquant moins de se détacher sont fixés par un simple système de
|
|
|
|
|
mâchoire, prenant en étau la plaque de bois dans une forme de U.
|
|
|
|
|
|
2024-04-12 17:45:33 +02:00
|
|
|
|
![La forme de U pour prendre la plaque de base en mâchoire et tenir un capteur par pression.](images/u_shape.jpg)
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
### Alimentation
|
|
|
|
|
|
|
|
|
|
Pour l’alimentation du robot, on vient envoyer 9 Volts d’une source quelconque,
|
|
|
|
|
d’une pile ou d’une alimentation stabilisée par exemple, dans l’entrée `VIN`
|
|
|
|
|
de l’Arduino, qui sera après régulée en interne pour donner les différents
|
|
|
|
|
rails d’alimentation. Cette entrée d’alimentation est connectée en interne au
|
|
|
|
|
port DC “barrel jack” de l’Arduino, donc avant les régulateurs de courant,
|
|
|
|
|
et prend donc des tensions entre 5 et 9 Volts.
|
|
|
|
|
|
|
|
|
|
Dans ce projet, nous utilisons une pile 9 Volts rechargeable dans un boîtier
|
|
|
|
|
vissé au châssis.
|
|
|
|
|
|
2024-04-12 17:45:33 +02:00
|
|
|
|
![Une vue de la pile 9 Volts que nous utilisons, rechargeable en micro USB.](images/pile9v.jpg)
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
### Moteurs
|
|
|
|
|
|
|
|
|
|
Les moteurs ici sont vissés au châssis, car juste pris en mâchoire ils ne
|
|
|
|
|
tiennent pas et se détachent à la moindre accélération.
|
|
|
|
|
|
|
|
|
|
Ils sont directement alimentés et pilotés via la carte Arduino Motor Shield,
|
|
|
|
|
qui permet de sélectionner leur vitesse sur une échelle de `0` à `255`,
|
|
|
|
|
d’actionner les freins et de leur donner un sens de rotation, et ce très
|
|
|
|
|
simplement dans le code.
|
|
|
|
|
|
|
|
|
|
Des roues ont été imprimées en 3D pour aller sur les embouts des moteurs, et un
|
|
|
|
|
joint torique sert de pneu pour améliorer l’adhérence du robot et éviter les
|
|
|
|
|
démarrage en “burn”.
|
|
|
|
|
|
|
|
|
|
### PCB
|
|
|
|
|
|
|
|
|
|
Au début de ce projet, nous avons utilisé une carte de prototypage électronique,
|
|
|
|
|
aussi appelé breadboard. Dans un second temps et pour éviter toute déconnexion
|
|
|
|
|
de câbles liée à une potentielle accélération violente, nous avons fait un PCB,
|
|
|
|
|
soudé manuellement sur une carte de prototypage prévu à cet effet.
|
|
|
|
|
|
2024-04-12 17:45:33 +02:00
|
|
|
|
![Une vue du dessus de notre PCB fait main.](images/pcb_irl.jpg)
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
Au niveau électronique, le PCB est routé de la manière suivante :
|
|
|
|
|
|
2024-04-12 17:45:33 +02:00
|
|
|
|
![Le routage du PCB sur une carte de protypage de type Breadboard.](images/pcb_fritzing.png)
|
2022-06-03 11:18:25 +02:00
|
|
|
|
|
|
|
|
|
Les différents composants viennent se connecter sur le PCB au moyen de
|
|
|
|
|
différentes broches femelles, pour que ce dernier puisse être détaché et modifié
|
|
|
|
|
sans devoir dessouder le moindre composant.
|
|
|
|
|
|
|
|
|
|
## Et du logiciel
|
|
|
|
|
|
|
|
|
|
D’un point de vue logiciel, notre projet est assez simple. En pseudo-algorithme,
|
|
|
|
|
on peut tout simplement le résumer à “on regarde parmi les 4 photo résistances
|
|
|
|
|
et on tourne ou avance vers celle ayant la valeur la plus sombre” dans le cas
|
|
|
|
|
où `followDark` est à `true`. Si au contraire cette valeur est à `false`, alors
|
|
|
|
|
il ira dans la direction opposée à la photorésistance ayant la plus haute valeur.
|
|
|
|
|
|
|
|
|
|
Une mesure des distances en face des trois capteurs à ultrasons permet d’arrêter
|
|
|
|
|
le robot (presque) avant collision frontale, et le robot ne se déplacera pas
|
|
|
|
|
tant que l’objet en face est toujours présent, et donc en théorie tant qu’il a
|
|
|
|
|
trouvé l’endroit le plus sombre.
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
#define echo1Pin 5
|
|
|
|
|
#define trig1Pin 4
|
|
|
|
|
#define echo2Pin 7
|
|
|
|
|
#define trig2Pin 6
|
|
|
|
|
#define echo3Pin 10
|
|
|
|
|
#define trig3Pin 2
|
|
|
|
|
#define rotMot1Pin 12
|
|
|
|
|
#define brakeMot1Pin 9
|
|
|
|
|
#define vitMot1Pin 3
|
|
|
|
|
#define rotMot2Pin 13
|
|
|
|
|
#define brakeMot2Pin 8
|
|
|
|
|
#define vitMot2Pin 11
|
|
|
|
|
#define photoRes1Pin A2
|
|
|
|
|
#define photoRes2Pin A3
|
|
|
|
|
#define photoRes3Pin A4
|
|
|
|
|
#define photoRes4Pin A5
|
|
|
|
|
|
|
|
|
|
#define followDark false
|
|
|
|
|
|
|
|
|
|
long duration;
|
|
|
|
|
int distance;
|
|
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
|
Serial.begin(9600);
|
|
|
|
|
pinMode(rotMot1Pin, OUTPUT);
|
|
|
|
|
pinMode(brakeMot1Pin, OUTPUT);
|
|
|
|
|
pinMode(vitMot1Pin, OUTPUT);
|
|
|
|
|
|
|
|
|
|
pinMode(rotMot2Pin, OUTPUT);
|
|
|
|
|
pinMode(brakeMot2Pin, OUTPUT);
|
|
|
|
|
pinMode(vitMot2Pin, OUTPUT);
|
|
|
|
|
|
|
|
|
|
pinMode(photoRes1Pin, INPUT);
|
|
|
|
|
pinMode(photoRes2Pin, INPUT);
|
|
|
|
|
pinMode(photoRes3Pin, INPUT);
|
|
|
|
|
pinMode(photoRes4Pin, INPUT);
|
|
|
|
|
|
|
|
|
|
pinMode(trig1Pin, OUTPUT);
|
|
|
|
|
pinMode(echo1Pin, INPUT);
|
|
|
|
|
pinMode(trig2Pin, OUTPUT);
|
|
|
|
|
pinMode(echo2Pin, INPUT);
|
|
|
|
|
pinMode(trig3Pin, OUTPUT);
|
|
|
|
|
pinMode(echo3Pin, INPUT);
|
|
|
|
|
|
|
|
|
|
delay(3000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void loop(){
|
|
|
|
|
byte echoPins[3] = {echo1Pin,echo2Pin,echo3Pin};
|
|
|
|
|
byte trigPins[3] = {trig1Pin,trig2Pin,trig3Pin};
|
|
|
|
|
long int durations[3] = {};
|
|
|
|
|
long int distances[3] = {};
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 3; i++){
|
|
|
|
|
digitalWrite(trigPins[i], LOW);
|
|
|
|
|
delayMicroseconds(2);
|
|
|
|
|
|
|
|
|
|
digitalWrite(trigPins[i], HIGH);
|
|
|
|
|
delayMicroseconds(10);
|
|
|
|
|
digitalWrite(trigPins[i], LOW);
|
|
|
|
|
durations[i] = pulseIn(echoPins[i], HIGH);
|
|
|
|
|
distances[i] = durations[i] * 0.034 / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int photoRes[4] = {};
|
|
|
|
|
Serial.print("Capteur infra : 1[");
|
|
|
|
|
photoRes[0] = analogRead(photoRes1Pin);
|
|
|
|
|
Serial.print(photoRes[0]);
|
|
|
|
|
Serial.print("] 2[");
|
|
|
|
|
photoRes[1] = analogRead(photoRes2Pin);
|
|
|
|
|
Serial.print(photoRes[1]);
|
|
|
|
|
Serial.print("] 3[");
|
|
|
|
|
photoRes[2] = analogRead(photoRes3Pin);
|
|
|
|
|
Serial.print(photoRes[2]);
|
|
|
|
|
Serial.print("] 4[");
|
|
|
|
|
photoRes[3] = analogRead(photoRes4Pin);
|
|
|
|
|
Serial.print(photoRes[3]);
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 3; i++){
|
|
|
|
|
Serial.print("] - distance(cm) : ");
|
|
|
|
|
Serial.print(distances[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Serial.println();
|
|
|
|
|
|
|
|
|
|
bool b = false;
|
|
|
|
|
for(int i = 0; i < 3; i++){
|
|
|
|
|
if (distances[i] < 30) {
|
|
|
|
|
b= true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int photoResRef = photoRes[0];
|
|
|
|
|
bool photoStop = true;
|
|
|
|
|
int photoResMinPos = 0;
|
|
|
|
|
|
|
|
|
|
if (followDark){
|
|
|
|
|
int photoResMin = 1024;
|
|
|
|
|
for (int i = 0; i < 4; i++){
|
|
|
|
|
if (photoResMin > photoRes[i]){
|
|
|
|
|
photoResMin = photoRes[i];
|
|
|
|
|
photoResMinPos = i;
|
|
|
|
|
}
|
|
|
|
|
if (abs(photoResRef - photoRes[i]) > 20){
|
|
|
|
|
photoStop = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else{
|
|
|
|
|
int photoResMax = 0;
|
|
|
|
|
for (int i = 0; i < 4; i++){
|
|
|
|
|
if (photoResMax < photoRes[i]){
|
|
|
|
|
photoResMax = photoRes[i];
|
|
|
|
|
photoResMinPos = (i + 2)%4;
|
|
|
|
|
}
|
|
|
|
|
if (abs(photoResRef - photoRes[i]) > 20){
|
|
|
|
|
photoStop = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Serial.println(photoResMinPos);
|
|
|
|
|
|
|
|
|
|
if (b || photoStop){
|
|
|
|
|
digitalWrite(brakeMot1Pin, HIGH);
|
|
|
|
|
digitalWrite(brakeMot2Pin, HIGH);
|
|
|
|
|
} else {
|
|
|
|
|
digitalWrite(brakeMot1Pin, LOW);
|
|
|
|
|
digitalWrite(brakeMot2Pin, LOW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (photoResMinPos == 0){
|
|
|
|
|
digitalWrite(rotMot1Pin, LOW);
|
|
|
|
|
digitalWrite(rotMot2Pin, LOW);
|
|
|
|
|
}
|
|
|
|
|
if (photoResMinPos == 1){
|
|
|
|
|
digitalWrite(rotMot1Pin, LOW);
|
|
|
|
|
digitalWrite(rotMot2Pin, LOW);
|
|
|
|
|
}
|
|
|
|
|
if (photoResMinPos == 2){
|
|
|
|
|
digitalWrite(rotMot1Pin, HIGH);
|
|
|
|
|
digitalWrite(rotMot2Pin, HIGH);
|
|
|
|
|
}
|
|
|
|
|
if (photoResMinPos == 3){
|
|
|
|
|
digitalWrite(rotMot1Pin, HIGH);
|
|
|
|
|
digitalWrite(rotMot2Pin, LOW);
|
|
|
|
|
}
|
|
|
|
|
analogWrite(vitMot1Pin, 150);
|
|
|
|
|
analogWrite(vitMot2Pin, 150);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Remerciements
|
|
|
|
|
|
|
|
|
|
Merci au Fablab de l’ENSEIRB-MATMECA, Eirlab, pour nous avoir permis de
|
|
|
|
|
travailler sur ce projet et d’avoir contribué matériellement au projet.
|
|
|
|
|
|
|
|
|
|
Merci aussi aux différents Fabmanagers qui nous ont aidés tout au long du projet
|
|
|
|
|
en répondant à nos questions plus ou moins posées sous l’emprise de la fatigue.
|
|
|
|
|
|
|
|
|
|
À la mémoire de Kaitlin Rooke.
|