# Projet de ROB3 : Damien CORSET et Romane COUEDEL

## **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Informations</span></span>**

- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">CORSET Damien - damien.corset@etu.sorbonne-universite.fr</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">COUEDEL Romane - romane.couedel@etu.sorbonne-universite.fr</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Date de début : 08/02/2024 - Date de fin : 30/05/2024</span></span>

## **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;"> Introduction </span></span>**

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Le projet Robot Écrivain a pour objectif de concevoir un système robotique capable de dessiner sur une surface plane horizontale. </span><span style="vertical-align: inherit;">En combinant les domaines de la mécanique, de l'électronique et de la programmation, notre équipe s'engage à relever ce défi. </span><span style="vertical-align: inherit;">Pour ce faire, nous devons respecter un cahier des charges précis et utiliser les machines disponibles au FABLAB, ainsi qu'une liste de matériel prédéfinie. </span><span style="vertical-align: inherit;">Ce projet représente une opportunité d'apprentissage, nous permettant de développer nos compétences en collaboration d'équipe et en utilisant des technologies avancées comme la découpe LASER et l'impression 3D.</span></span>

**<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Cahier des charges</span></span>**

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Le robot doit être fixé ou posé sur une plaque horizontale carrée de 250mm par 250mm et doit être capable de réaliser les deux exercices suivants :</span></span>

**<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Exercice 1</span></span>**

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Le robot doit être capable de tracer différentes figures imposées dans le plan de la plaque support, avec un crayon fixé sur son organe terminal. </span><span style="vertical-align: inherit;">Chaque figure doit être réalisée en 10 secondes, avec une marge d'erreur de +/- 0,2 secondes. </span><span style="vertical-align: inherit;">Les chiffres imposés sont les suivants :</span></span>

- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Une ligne de 5 cm de long,</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Une ligne pointillée de 5cm de long,</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Un cercle de 2,5 cm de rayon,</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Un cercle pointillé de 2,5 cm de rayon.</span></span>

**<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Exercice 2</span></span>**

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Le robot doit être capable de tracer un dessin dans un carré de dimensions 5 cm par 5 cm, avec un crayon fixé sur son organe terminal. </span><span style="vertical-align: inherit;">Le déplacement de celui-ci doit être contrôlé par un joystick. </span><span style="vertical-align: inherit;">Il est important de noter que la figure à tracer peut être discontinue, ce qui signifie qu'il faut prévoir la possibilité de relever le crayon du support horizontal pendant le tracé.</span></span>

<p class="callout info"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">De plus, une fonctionnalité facultative consiste à offrir la possibilité de régler la vitesse de déplacement du robot via l'interface utilisateur. </span><span style="vertical-align: inherit;">Cela permet d'ajuster la vitesse de tracé en fonction des besoins spécifiques de chaque dessin.</span></span></p>

**<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Fonctions contraintes</span></span>**

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Les contraintes imposées pour le projet Robot Écrivain sont :</span></span>

- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Respect des règles d'utilisation du FABLAB de Sorbonne Université</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Utilisation de composants (moteurs, contrôleurs, boutons, éléments de guidage, alimentation stabilisée, boutons, etc.) parmi un ensemble imposé.</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Fabrication des pièces grâce au Machine à découpe LASER et Imprimantes RAISE 3D PRO2.</span></span>
- <span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Programmation en C utilisant la chaîne de développement Arduino IDE.</span></span>

**Liste des composants et matériels disponibles**

- Un crayon
- Interface de commande :
- Une carte Arduino UNO avec câble USB-B;
- Un joystick:
- Une platine de prototypage;
- Alimentation régulée 5V ;
- Câbles, LEDs, boutons poussoirs, résistances.

- Motorisation :
- Deux servomoteurs HS422 180°;
- Un servomoteur Emax ES08A 180°.

- Mécanique :
- Matière PLA pour impression 3D;
- Feuilles medium : 3mm et 6mm d'épaisseur;
- Vis et écrous : M2, M2.5, M3, M4.
- Roulements et axes de diamètre 4mm.


**Gantt**

<p class="callout success">Répartition du travail en équipe [ici](https://docs.google.com/spreadsheets/d/1l3xwK5V_pOysevd3q7F5Jwf33_8ALGLU7fZH52m7O9I/edit#gid=1115838130).</p>

## **I - Conception préliminaire**

**Proposition 1:**

## ![](https://lh7-us.googleusercontent.com/jk_FdxSzhpfsYbrlamJ3qDR-lqQPAKbDfuLu3Z8TO6O5HADqt1uVUyZ7J_QPTYSC60-16rEN63a3yEz4avPYDLpqH5STXEl_FF0CGT4z1McedPMZEX2TQ2n2GF-yVqz_3ACptGma0lxiNZt28mhlegE)

Cette proposition utilise un système comprenant un premier rail de guidage linéaire immobile, fixé à deux masses, auquel est ajouté un chariot. Un second rail, perpendiculaire au premier, est également présent. Sur ce rail mobile, un chariot est fixé, intégrant l'effecteur, ici un stylo. Ainsi, lorsque le rail mobile se déplace, le stylo se déplace selon l'axe y, et lorsque le chariot bouge, le stylo se déplace selon l'axe x, conformément au repère tracé sur le dessin. Un premier servomoteur est utilisé pour déplacer le chariot le long de l'axe y, et un second, fixé sur le chariot, contrôle les déplacements de l'effecteur le long de l'axe x. Enfin, un dernier servomoteur, plus petit, est monté sur le chariot afin de pouvoir abaisser ou relever le stylo.

<p class="callout info">Inspiration : [AxiDraw V3](https://eu.robotshop.com/fr/products/axidraw-v3-personal-writing-drawing-robot-intl?gad_source=1&gclid=Cj0KCQiAw6yuBhDrARIsACf94RXAKLoYkCLJ3MuaRa6hlcLJr7fabXooPkDBvN3BWfvUlw3OVqt995QaAhrQEALw_wcB)</p>

**Proposition 2:**

## ![](https://lh7-us.googleusercontent.com/6dQh8R4xZy5zi8potylr07qsZyiMhc4li8cvnWhxSVdw3XkVThheMWl3QAeBtdHEA_n5TSuXSgBpWlkO4XyhMp00k_ej0lPC4msJYo8-mmb_GOKbsRvOa3M67fkzZQTlPyfJMom3RNwXikey4mw_EXk)

Dans la même idée que la proposition 1, cette proposition est constituée d’un chariot auquel est fixé le stylo, qui se déplace linéairement sur un rail de guidage mobile qui lui-même se déplace linéairement et repose sur deux autres rails immobiles. Ce système est déjà commercialisé non pas pour faire du dessin mais plutôt pour de la gravure au laser.  
Pour les mêmes raisons que précédemment cette proposition ne sera pas notre choix final.

<p class="callout info">Inspiration : [Machine à Graver Laser](https://www.vevor.fr/machine-de-gravure-laser-c_11141/vevor-machine-a-graver-laser-graveur-laser-cnc-6-w-zone-de-gravure-460x810-mm-p_010795045860)</p>

**Proposition 3:**

## ![](https://lh7-us.googleusercontent.com/f5q12pOXE9khUkgioINaaNyr51bM7RgR7qcIPEmkRtEv_Ci6KRHOfjg4HvzC5osGDvllgjAeiK8JKQ0wxKeZ9CYlQcIK1DC3-hFJhw2qhHFqazOnpk06uvXc_Q_uqqkvgFZRjqpMIacOyhQtYmNRFdw)

Le robot est composé d'un corps principal sur lequel est montés deux servomoteurs pour contrôler les bras. Les bras sont joints au niveau de leur main, où est fixé le crayon. Pour relever le crayon, nous avions pensé à soulever le corps du robot mais il est possible que le servomoteur ne supporte pas la charge de tout le système.

<p class="callout info">Inspiration : [Robot dessinateur](https://shopibest.com/product/robot/)</p>

**Proposition 4:**

## ![](https://lh7-us.googleusercontent.com/WUB5eCxQ0-_YBfuls5CfRj6rmwoYP5RysNizSkwoYsXD6tl_99DY2jFFnJ0TzobTHyTEIekoQdqVRSP4mNBiAdvrneJg9mzBMy10wm5CODGrMF0BRrAcLQxAAebc1DYyPxDWtx_8Svmkz_g28fTMWrw)

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Cette idée reprend la proposition 3, mais au lieu de soulever le corps entier du robot pour relever le cayon, on met en place un mécanisme indépendant pour soulever uniquement le crayon. </span><span style="vertical-align: inherit;">Le mécanisme se situe au niveau des principales articulations. </span><span style="vertical-align: inherit;">Il existe tout de même un risque minime que l'ensemble soit trop lourd à porter pour les deux servomoteurs si les mains trop lourdes et/ou si la longueur des bras sont trop importantes. </span><span style="vertical-align: inherit;">Cependant ces servomoteurs sont plus gros et plus puissants que celui qui se situe sur les mains. </span><span style="vertical-align: inherit;">L'inconvénient de ce système se situe au niveau de la tenue du crayon, puisqu'il faut à la fois qu'il soit serré et qu'il soit glissant pour permettre le mouvement des pièces. </span></span>

**<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Choix retenu:</span></span>**

[![choix.jpeg](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-02/scaled-1680-/choix.jpeg)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-02/choix.jpeg)

<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Cette solution reprend la proposition 4, sauf qu'on allonge l'avant bras sur lequel est fixé le servomoteur du crayon. </span><span style="vertical-align: inherit;">Le crayon se trouve à l'extrémité de cet avant-bras où il est serré. </span><span style="vertical-align: inherit;">Entre le crayon et le servomoteur qui le relève, les deux pièces se rejoignent ce qui permet le mouvement.</span></span>

## **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">II - Conception détaillée</span></span>**

#### **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.1. Conception mécanique</span></span>**

##### **2.1.1. Modélisation et vérification des ajustements**

Nous avons utilisé le logiciel de CAO SolidWorks pour modéliser l'ensemble du robot. Pour simplifier notre processus de conception et d'assemblage, nous avons divisé l'assemblage en plusieurs parties distinctes :

- Le premier sous-assemblage, nommé "base", est un boîtier abritant tous les composants électroniques, laissant les deux servomoteurs des bras visibles à l'extérieur. Sur le dessus de ce boîtier, se trouve le joystick, l'élément unique avec lequel l'utilisateur interagit. Pour faciliter le montage, des ouvertures sont prévues sur la plaque supérieure du boîtier pour permettre le passage des moteurs et la fixation du joystick. De plus, une ouverture latérale est réalisée pour permettre l'alimentation de la carte Arduino. La face inférieure du boîtier est constituée d'une plaque qui couvre entièrement la surface du robot, servant de support pour la feuille de dessin.
- Le deuxième sous-assemblage, appelé "effecteur", est mis en place par l'utilisateur à l'aide d'une vis, similaire au dispositif des compas, qui serre le stylo au système. Pour lever le stylo, un petit servo-moteur est fixé au bras le plus long, prévu avec des encoches pour permettre sa fixation. Des trous sont également prévus dans l'avant-bras pour fixer le mécanisme de levage du stylo, qui sera fabriqué en impression 3D.

<p class="callout info">Séparer notre assemblage en plusieurs sous-assemblages simplifie l'identification et la manipulation de chaque composant individuel, favorise une meilleure collaboration entre les membres de l'équipe et simplifie la maintenance et les potentielles modifications ultérieures.</p>

<p class="callout info">Il convient de souligner que notre processus de conception a nécessité la réalisation de tests sur les pièces nécessitant un montage serré, afin d'ajuster avec précision les dimensions des composants. Les variations dues aux ajustements et aux tolérances des machines ont été prises en compte pour garantir un assemblage correcte du robot.</p>

![](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/embedded-image-zun5epxq.png)

<p class="callout success">Nous avons maximiser l'utilisation de la découpe laser pour la fabrication de nos pièces pour plusieurs raisons. Tout d'abord, la découpe laser offre une solidité, une précision supérieures et un avantage en termes de rapidité de production, nous permettant de concrétiser notre projet de manière efficace. De plus, cette méthode nous a permis de réduire les coûts matériels.</p>

<p class="callout success">L'ensemble des pièces ainsi que l'assemblage sont disponibles [ici](https://drive.google.com/file/d/1NKOxVvD_H19jJoK8b_mGIjhFfFu6UY81/view?usp=drive_link). Les fichiers de fabrication sont également disponibles aux formats DXF, SVG ou STL.</p>





##### **2.1.2. Schéma cinématique**

Ci dessous le schéma cinématique du robot :

[![image18.jpg](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/scaled-1680-/image18.jpg)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/image18.jpg)

##### **2.1.3. Calcul du modèle géométrique direct et inverse**

Dans cette section, nous procédons au calcul du modèle géométrique direct et inverse pour notre système. Ces calculs sont nécessaires pour prédire le comportement du système.

**Références du Système :**

[![image.png](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/scaled-1680-/zALimage.png)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/zALimage.png)

**Modèle Géométrique Direct :**

Le Modèle Géométrique Direct (MGD) permet de déterminer la position et l'orientation de l'effecteur final d'un robot en connaissant les valeurs des angles de ses articulations. En d'autres termes, il permet de prédire où se situera l'effecteur du système en fonction des positions de ses articulations.

![](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/embedded-image-vsvtu4qa.png)

<details id="bkmrk-d%C3%A9tails-du-calcul-%5Bi"><summary>Détails des calculs du MGD</summary>

[![image.png](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/scaled-1680-/auAimage.png)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/auAimage.png)

</details> **Modèle Géométrique Inverse :**

D'autre part, le Modèle Géométrique Inverse (MGI) permet à l'inverse de calculer les valeurs des angles des articulations nécessaires pour atteindre une position spécifique de l'effecteur final. Autrement dit, il permet déterminer les mouvements que le système doit effectuer pour placer son effecteur à un endroit précis dans l'espace.

![](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/embedded-image-rmmrxzij.png)

<details id="bkmrk-d%C3%A9tails-des-calculs-"><summary>Détails des calculs du MGI</summary>

[![image.png](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/scaled-1680-/0cFimage.png)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/0cFimage.png)

</details><p class="callout info">Pour valider nos résultats et assurer leur précision, nous avons utilisé les logiciels SolidWorks et MATLAB. SolidWorks a été employé pour récréer le modèle du système à l'aide d'une esquisse, tandis que MATLAB a été utilisé pour effectuer des simulations numériques à l'aide des équations trouvées précédemment. Les résultats de nos calculs sous Matlab ont été comparés avec les valeurs renvoyées par le logiciel SolidWorks.</p>

<p class="callout success">Les fichiers SolidWorks et MATLAB correspondants sont disponibles [ici](https://drive.google.com/file/d/1NKOxVvD_H19jJoK8b_mGIjhFfFu6UY81/view?usp=drive_link).</p>


#### **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.2. Conception électronique</span></span></span></span>**

##### **2.2.1. Architecture électronique**

Dans notre conception électronique, nous distinguons deux aspects essentiels : l'électronique de commande, où la carte Arduino UNO joue un rôle central dans la gestion et la synchronisation des composants, et l'électronique de puissance. Le joystick, en tant qu'interface utilisateur principale, transmet les données d'entrée à la carte Arduino. Les deux servomoteurs HS422 et le servomoteur FT90MR servent d'actionneurs, les HS422 contrôlant les mouvements du système en x et y et le FT90MR en contrôlant la hauteur du stylo sur l'axe z. Une alimentation régulée de 5V assure une tension constante pour les moteurs. Cette alimentation régulée alimente à la fois la carte Arduino et les servomoteurs.

<p class="callout warning">Il est important de noter que la carte Arduino ne peut pas fournir des courants élevés à des actionneurs tels que les servomoteurs. Cette limitation peut compromettre le fonctionnement de la carte et entraîner des dysfonctionnements ou des dommages. C'est pourquoi en séparant la partie puissance de la partie électronique, nous évitons que la carte soit surchargée en courant ou détériorée.</p>

<p class="callout info">Nous avons fait le choix d'utiliser uniquement un joystick dans notre système, ce qui permet à la fois de naviguer dans les menus et de piloter manuellement le robot. Ce choix simplifie l'interface utilisateur et sera expliqué en détail dans la section sur la conception logicielle.</p>



##### **2.2.2. Schéma des connexions électriques**

Nous utilisons le logiciel KiCad pour réaliser le schéma des connexions. Il offre une interface conviviale et des fonctionnalités avancées pour la conception de circuits électroniques. Il nous permet de représenter de manière claire et précise les connexions entre les différents composants de notre système électronique.

[![image.png](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/scaled-1680-/FSnimage.png)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/FSnimage.png)

#### **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.3. Conception logicielle</span></span></span></span></span>**

##### **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.3.1. Architecture du code du menu principal</span></span></span></span></span>**

<span id="bkmrk--19" style="font-weight: normal;">![](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/embedded-image-exvzqq8h.png)</span>

<details id="bkmrk-code-du-menu-princip"><summary>Code du menu principal (C++)</summary>

```c++
#include <Arduino.h>
#include <Servo.h>
#include "fonctions.h"
#include "dessin.h"

int initialisationIO(void)
{
  pinMode(PIN_VRX, INPUT);
  pinMode(PIN_VRY, INPUT);
  pinMode(PIN_SW, INPUT);

  return 1;
}

int initialisationCom(void)
{
  Serial.begin(921000); // Pour debug
  return 1;
}

Servo servo1;
Servo servo2;
Servo servo3;

int initServo(void)
{
  servo1.attach(PIN_SERVO_1);
  servo2.attach(PIN_SERVO_2);
  servo3.attach(PIN_SERVO_3);

  return 1;
}

void setup()
{
  Serial.print("InitialisationCOM...\n");
  if (!initialisationCom())
  {
    Serial.print("Erreur...\n");
    abort();
  }
  Serial.print("InitialisationCOM reussie\n");

  Serial.print("InitialisationIO...\n");
  if (!initialisationIO())
  {
    Serial.print("Erreur...\n");
    abort();
  }
  Serial.print("InitialisationIO reussie\n");

  Serial.print("InitialisationSERVOS...\n");
  if (!initServo())
  {
    Serial.print("Erreur...\n");
    abort();
  }
  Serial.print("InitialisationSERVOS reussie\n");

  controlServoCalibration(45, 52);
  Serial.print("Debut programme...\n");
}

void loop()
{
  switch (choixJoystick(2, 0.5, 60, true))
  {
  case EXERCICE_1:
    Serial.print("Exercice 1\n");
    exercice1();
    break;

  case EXERCICE_2:
    Serial.print("Exercice 2\n");
    exercice2();
    break;

  default:
    Serial.print("Fin programme\n");
    abort();
  }
}


int choixJoystick(int nombreChoix, float triggerModule, int offset, bool BP)
{
  int choix = 0;

  do
  {
    //Valeur brut des capteurs
    int rawValX = analogRead(PIN_VRX) - OFFSET_VRX;
    int rawValY = 1023 - analogRead(PIN_VRY) - OFFSET_VRY;

    // Conversions des valeurs bruts en valeur centrées entre -512 / +512
    float ValX = float(map(rawValX, -OFFSET_VRX, (1023 - OFFSET_VRX), -1000, 1000)) / 1000.0;
    float ValY = float(map(rawValY, -OFFSET_VRY, (1023 - OFFSET_VRY), -1000, 1000)) / 1000.0;

    // Récupérations des données en coordonnées polaires
    float module = sqrt(ValX * ValX + ValY * ValY);
    int angle = atan2(ValY, ValX) * RAD_TO_DEG;

    // Ajustement pour rester dans notre plage angulaire 0-360° et module 0-1
    if (module > 1.0)
      module = 1.0;
    if (angle < 0.0)
      angle += 360.0;

    // Interprétation du résultat
    if (module > triggerModule)
    {
      for (int i = 0; i < nombreChoix; i++)
      {
        if (i == 0) // Cas particulier choix 0
        {
          if ((angle <= offset && angle >= 0) || (angle <= 360 && angle >= 360 - offset))
          {
            choix = 1;
            break;
          }
        }
        else // Détermination du choix entre 1 et nombreChoix
        {
          int angleRef = i * (360.0 / nombreChoix);

          if (angle >= (angleRef - offset) && angle <= (angleRef + offset))
          {
            choix = i + 1;
            break;
          }
        }
      }
    }
    _delay_ms(10);

  } while (choix == 0 || (digitalRead(PIN_SW) && BP)); // Tant qu'on a pas de choix ou bouton non appuyé

  return choix;
}

```

</details>##### **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.3.2. Architecture du code "Exercice 1"</span></span></span></span></span>**

<span id="bkmrk--23" style="font-weight: normal;">![](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/embedded-image-brdbgl9t.png)  
</span>

<details id="bkmrk-code-%22exerice-1%22-%28c%2B"><summary>Code "Exerice 1" (C++)</summary>

```c++
// Fonction principale de l'exercice 1
int exercice1(void)
{
    // Sélectionne une action en fonction du choix de l'utilisateur avec le joystick
    switch (choixJoystick(4, 0.5, 30, true))
    {
    case LIGNE_CONTINUE:
        // Trace une ligne continue
        tracerLigne(5, 25, X_MAX, 25, 200, TRAIT_CONTINU);
        break;

    case CERCLE_CONTINU:
        // Trace un cercle continu
        tracerCercle(30, 25, 23, 360, TRAIT_CONTINU);
        break;

    case LIGNE_DISCONTINUE:
        // Trace une ligne discontinue
        tracerLigne(5, 25, X_MAX, 25, 200, TRAIT_DISCONTINU);
        break;

    case CERCLE_DISCONTINU:
        // Trace un cercle discontinu
        tracerCercle(30, 25, 23, 360, TRAIT_DISCONTINU);
        break;
    }
    // Affiche la fin de l'exercice dans la console série
    Serial.print("Fin exercice 1\n");
    _delay_ms(1000); // Pause de 1 seconde
    return 1;
}

// Fonction pour tracer une ligne
int tracerLigne(float xFrom, float yFrom, float xTo, float yTo, int steps, bool trait)
{
    // Vérifie si les coordonnées sont dans les limites autorisées
    if (xFrom < X_MIN || xFrom > X_MAX || yFrom < Y_MIN || yFrom > Y_MAX)
        return -1;
    if (xTo < X_MIN || xTo > X_MAX || yTo < Y_MIN || yTo > Y_MAX)
        return -1;

    // Calcule les incréments pour chaque étape
    float xSteps = (xTo - xFrom) / float(steps);
    float ySteps = (yTo - yFrom) / float(steps);
    float q1, q2, compteur = 0;

    // Positionne le servo Z
    controlServoZ(85);
    _delay_ms(250);

    // Convertit les coordonnées en angles pour les servos XY
    inverseModeleGeom(xFrom, yFrom + OFFSET_Y, &q1, &q2);
    controlServoXY(q1, q2);
    _delay_ms(250);
    controlServoZ(95);

    // Boucle pour tracer la ligne
    for (float i = 0; i < steps; i++)
    {
        xFrom += xSteps;
        yFrom += ySteps;

        inverseModeleGeom(xFrom, yFrom + OFFSET_Y, &q1, &q2);
        controlServoXY(q1, q2);

        // Gère le trait discontinu si nécessaire
        if (trait)
        {
            if (compteur == 7)
            {
                controlServoZ(95);
            }
            else if (compteur == 10)
            {
                controlServoZ(85);
                compteur = 0;
            }
            compteur++;
        }
        _delay_ms(90); // (temps boucle + delay) * 50 = 10000ms avec temps boucle = 5ms (delay = 90 pour 10sec)
    }
    controlServoZ(75); // Ramène le servo Z à sa position initiale
    return 1;
}

// Fonction pour tracer un cercle
int tracerCercle(float xFrom, float yFrom, float radius, int steps, bool trait)
{
    float q1, q2, compteur = 0;
    float xTo = xFrom;
    float yTo = yFrom;

    controlServoZ(85);
    _delay_ms(250);

    // Positionne le servo XY pour commencer le cercle
    inverseModeleGeom(xFrom + radius, yFrom + OFFSET_Y, &q1, &q2);
    controlServoXY(q1, q2);
    _delay_ms(250);
    controlServoZ(105);

    // Boucle pour tracer le cercle
    for (int i = 0; i <= steps + 5; i++)
    {
        xTo = xFrom + radius * cos(i * (360.0 / steps) * DEG_TO_RAD);
        yTo = yFrom + radius * sin(i * (360.0 / steps) * DEG_TO_RAD);

        inverseModeleGeom(xTo, yTo + OFFSET_Y, &q1, &q2);
        controlServoXY(q1, q2);

        // Gère le trait discontinu si nécessaire
        if (trait)
        {
            if (compteur == 2)
            {
                controlServoZ(105);
            }
            else if (compteur == 4)
            {
                controlServoZ(85);
                compteur = 0;
            }
            compteur++;
        }
        _delay_ms(100); // (temps boucle + delay) * 90 = 10000ms avec temps boucle = 5ms (delay = 100 pour 10sec)
    }
    return 1;
}

// Fonction pour convertir les coordonnées (x, y) en angles pour les servos
int inverseModeleGeom(float x, float y, float *q1, float *q2)
{
    float O1E = sqrt(pow((x - D0), 2) + pow(y, 2));
    float Alpha1 = atan2(y, x - D0);
    float Alpha2 = acos((pow(L1, 2) - pow((L4 + L5), 2) + pow(O1E, 2)) / (2 * L1 * O1E));
    float Theta1 = Alpha1 + Alpha2;

    float Cx = (L4 / (L4 + L5)) * x + (L5 / (L4 + L5)) * (L1 * cos(Theta1) + D0);
    float Cy = (L4 / (L4 + L5)) * y + (L5 / (L4 + L5)) * (L1 * sin(Theta1));

    float O2C = sqrt(pow((Cx - D0 - D1), 2) + pow(Cy, 2));

    float Beta1 = atan2(Cy, (D0 + D1) - Cx);
    float Beta2 = acos((pow(L2, 2) - pow(L3, 2) + pow(O2C, 2)) / (2 * L2 * O2C));
    float Theta2 = PI - (Beta1 + Beta2);

    *q1 = Theta1 * RAD_TO_DEG;
    *q2 = Theta2 * RAD_TO_DEG;

    return 1;
}

```

</details>##### **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.3.3. Architecture du code "Exercice 2"</span></span></span></span></span>**

[![image.png](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/scaled-1680-/vGvimage.png)](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-03/vGvimage.png)

<details id="bkmrk-code-%22exercice-2%22-%28c"><summary>Code "Exercice 2" (C++)</summary>

```c++
int exercice2(void)
{
  float x = 0, y = 0, q1, q2;
  float vitesse = 0.05;

  while (!digitalRead(PIN_SW))
    ; // Anti rebond

  while (digitalRead(PIN_SW))
  {
    // Valeurs bruts des capteurs
    int rawValX = analogRead(PIN_VRX) - OFFSET_VRX;
    int rawValY = 1023 - analogRead(PIN_VRY) - OFFSET_VRY;

    // Conversions des valeurs bruts en valeur centrées entre -512 / +512
    float ValX = float(map(rawValX, -OFFSET_VRX, (1023 - OFFSET_VRX), -1000, 1000)) / 1000.0;
    float ValY = float(map(rawValY, -OFFSET_VRY, (1023 - OFFSET_VRY), -1000, 1000)) / 1000.0;

    // Récupérations des données en coordonnées polaires
    float module = sqrt(ValX * ValX + ValY * ValY);
    int angle = atan2(ValY, ValX) * RAD_TO_DEG;

    // Ajustement pour rester dans notre plage angulaire 0-360° et module 0-1
    if (module > 1.0)
      module = 1.0;
    if (angle < 0.0)
      angle += 360.0;

    // Interprétation du résultat
    if (module > 0.2)
    {
      x = x + vitesse * module * cos(angle * DEG_TO_RAD);
      y = y + vitesse * module * sin(angle * DEG_TO_RAD);

      // Saturation numérique pour éviter dépassement
      if (x < X_MIN)
        x = X_MIN;
      if (x > X_MAX)
        x = X_MAX;
      if (y < Y_MIN)
        y = Y_MIN;
      if (y > Y_MAX)
        y = Y_MAX;

      inverseModeleGeom(x, y + OFFSET_Y, &q1, &q2);
      controlServoXY(q1, q2);
    }
  }
  Serial.println("Fin exercice 2");
  _delay_ms(1000);
  return 1;
}
```

</details><p class="callout success">Le programme complet est disponible [ici](https://drive.google.com/drive/folders/1I3kV_7YYsN62A0KeueDZHmTrLymUBlCz?usp=sharing)</p>

## **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">III - Réalisation </span></span>**

![image.gif](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/Cwqimage.gif) ![image.gif](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/MeWimage.gif)

 ![image.gif](https://wiki.fablab.sorbonne-universite.fr/BookStack/uploads/images/gallery/2024-05/ejQimage.gif)

## **IV - Guide d'utilisation** 

**1. Navigation dans le menu principal :**

- **Choix des exercices :**
    - **Joystick à gauche ou à droite :** Sélectionner l'exercice 1 ou 2.
    - **Joystick en position neutre et validation :** Terminer le programme.
    - **Validation :** Appuyer sur le bouton poussoir du joystick pour confirmer la sélection et entrer dans l'exercice choisi.

**2. Exercice 1 - Tracé de figures :**

- **Sélection du mode de tracé :**
    - **Joystick à droite :** Tracé d'une ligne continue.
    - **Joystick vers le haut :** Tracé d'un cercle continu.
    - **Joystick à gauche :** Tracé d'une ligne discontinue.
    - **Joystick vers le bas :** Tracé d'un cercle discontinu.
- **Validation :** Appuyer sur le bouton poussoir du joystick pour lancer le tracé de la figure sélectionnée.

**3. Exercice 2 - Tracé libre :**

- **Déplacement et dessin :**
    - **Joystick :** Utiliser le joystick pour déplacer librement le robot dans le carré de 5 cm par 5 cm.
    - **Dessin :** Le robot dessine tant que le joystick est déplacé.
    - **Fin du tracé :** Appuyer sur le bouton poussoir du joystick pour arrêter le dessin et revenir au menu principal.

**4. Retour au menu principal :**

- Une fois un exercice terminé, le robot retourne automatiquement au menu principal.
- Le processus de sélection peut être répété pour lancer un autre exercice ou terminer le programme.

## **V - Limite du projet**

Bien que le projet Robot Écrivain ait été une réussite, il est important de noter certaines limitations liées aux matériaux et aux composants utilisés :

1. **Précision du matériel :**
    
    
    - **Servomoteurs :** Les servomoteurs que nous avons utilisés ont une résolution d'1°, ce qui limite la précision des mouvements. Cela pose des défis pour le tracé de figures nécessitant une haute précision.
    - **Absence de homing :** Le manque de capteurs de position initiale (homing) rend difficile le repositionnement exact du robot après une mise hors tension ou une interruption. Chaque redémarrage doit en théorie, nécessiter un recalibrage manuel.
2. **Capacités du microcontrôleur :**
    
    
    - **Carte Arduino UNO :** Notre système repose sur un microcontrôleur AVR à 16 MHz, avec un seul cœur. Cette architecture ne supporte pas le multitâche, ce qui signifie que les calculs et les tâches doivent être exécutés séquentiellement, ralentissant ainsi les performances globales.
    - **Limites de calcul :** Les capacités limitées de calcul du microcontrôleur entraînent des délais supplémentaires, surtout lors de la gestion des calculs géométriques pour le tracé des figures. Un microcontrôleur plus puissant, comme un ESP32, aurait permis des calculs plus rapides et une gestion multitâche.
3. **Conception mécanique et matériaux :**
    
    
    - **Découpe laser et impression 3D :** Bien que ces méthodes offrent de la précision et de la rapidité, les matériaux utilisés (PLA pour impression 3D et medium pour découpe laser) ont leurs propres limitations en termes de rigidité et de durabilité.
    - **Encombrement et stabilisation :** La structure du robot, en raison de la simplicité des matériaux et de la conception, peut manquer de la stabilité et de précision

Ces limitations ont impacté la précision, la rapidité et la facilité d'utilisation du robot. Cependant, elles ont également fourni des opportunités d'apprentissage précieuses et ont mis en lumière les domaines à améliorer pour des projets futurs plus ambitieux. Nous envisageons que des améliorations, telles que l'utilisation de composants plus avancés et la conception de systèmes de retour de position (servomoteurs intelligents), pourraient considérablement augmenter les capacités de notre robot.

## **<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Conclusion</span></span>**

Le projet Robot Écrivain a été une expérience enrichissante, combinant mécanique, électronique et programmation pour créer un robot capable de dessiner sur une surface plane. En respectant un cahier des charges précis et en utilisant les ressources du FABLAB, nous avons surmonté plusieurs défis techniques.

À travers les étapes de brainstorming, planification, modélisation CAO sur SolidWorks, et programmation en C++, chaque membre a contribué à la réussite du projet. Nos choix de conception, validés par nos professeurs ainsi que par des simulations et tests, ont assuré la précision et la fonctionnalité du robot.

L'architecture électronique a optimisé la gestion de la puissance et des commandes via Arduino, tandis que le développement du code a permis le tracé précis de figures imposées et la gestion de l'interface utilisateur. Les tests finaux ont confirmé le bon fonctionnement du robot, accomplissant toutes les tâches requises.

Ce projet nous a permis de développer des compétences techniques et de collaboration, constituant une base solide pour nos futures études et projets en ingénierie. Nous sommes fiers du travail accompli et des connaissances acquises tout au long de cette expérience.

## Journal de bord

08 février

- <span style="text-decoration: underline;">**Découverte du projet**</span> : Présentation PowerPoint détaillant le cahier des charges du robot dessinateur.
- <span style="text-decoration: underline;">**Formation des groupes**</span> : Les équipes ont été formées.
- <span style="text-decoration: underline;">**Brainstorming**</span> : Séance de brainstorming, générant une variété d’idées et de projets différents.
- <span style="text-decoration: underline;">**Choix d’un système :**</span> Sélection du robot le plus réalisable et efficace.
- <span style="text-decoration: underline;">**Répartition des tâches :**</span> Création d’un diagramme de Gantt.
- <span style="text-decoration: underline;">**Schéma électronique :**</span> Sélection des composants nécessaires

15 février

- <span style="text-decoration: underline;">**Choix des matériaux :**</span> quels matériaux sont les plus adaptés en tenant compte des choix disponibles.
- <span style="text-decoration: underline;">**Début de la modélisation solidworks.**</span>
- <span style="text-decoration: underline;">**Schéma électronique :**</span> élaboration du schéma électronique sur Kicad.
- **<span style="text-decoration: underline;">Modèle géométrique:</span>** Discussion autour de celui-ci en interne pour savoir comment le déterminer

28 février

- <span style="text-decoration: underline;">**Finalisation de la modélisation solidworks**</span>
- <span style="text-decoration: underline;">**Fabrication des pièces :**</span> Les premiers tests de fabrication ont été réalisés, notamment ceux liés à des ajustements (ex: les bras qui accueillent les roulements)
- <span style="text-decoration: underline;">**Modèle géométrique:**</span> avec l’aide de nos professeurs nous avons pu déterminer le modèle géométrique

07 mars

- <span style="text-decoration: underline;">**Fabrication des pièces:**</span> Création de toutes les pièces fabriquées à la découpeuse laser
- <span style="text-decoration: underline;">**Assemblage:**</span> Le robot est entièrement monté sauf l’organe terminal
- <span style="text-decoration: underline;">**Câblage + codage :** </span>On test de manière unitaire les composants

02 mai

- <span style="text-decoration: underline;">**Fabrication des pièces:**</span> Impression des dernières pièces qui permettent de lever le crayon
- <span style="text-decoration: underline;">**Assemblage:**</span> le robot est monté entièrement
- **<span style="text-decoration: underline;">Codage :</span>** exercice 1, exercice 2

30 mai

- <span style="text-decoration: underline;">**Codage:**</span> Derniers ajustements du code.