{"id":1214,"date":"2024-05-29T20:36:13","date_gmt":"2024-05-29T18:36:13","guid":{"rendered":"https:\/\/albooms.fr\/?p=1214"},"modified":"2025-03-27T06:35:23","modified_gmt":"2025-03-27T05:35:23","slug":"murmurer-a-loreille-de-sa-tortue","status":"publish","type":"post","link":"https:\/\/albooms.fr\/?p=1214","title":{"rendered":"Murmurer \u00e0 l&rsquo;oreille de sa tortue"},"content":{"rendered":"\n<p>Avant de commencer, le lecteur me pardonnera, je l&rsquo;esp\u00e8re, ce titre empreint de facilit\u00e9. La question r\u00e9elle de ce billet, c&rsquo;est comment commander la tortue de sol que l&rsquo;on vient d&rsquo;imprimer (<a href=\"https:\/\/albooms.fr\/?p=1147\">voir ici<\/a>), puis d&rsquo;assembler (<a href=\"https:\/\/albooms.fr\/?p=1171\">voir ici<\/a>). Ce billet sera, par ailleurs, exceptionnellement long puisqu&rsquo;il s&rsquo;agit davantage de documenter le code que d&rsquo;un travail de r\u00e9daction.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Avant de commencer<\/h5>\n\n\n\n<p>Si vous en \u00eates l\u00e0, c&rsquo;est que vous \u00eates plus ou moins convaincus de l&rsquo;int\u00e9r\u00eat de cette machine pour r\u00e9fl\u00e9chir \u00e0 un \u00ab\u00a0num\u00e9rique\u00a0\u00bb qui ne soit ni enferm\u00e9 dans une boite noire ni pour imaginer que les machines soient dou\u00e9es de la moindre forme d&rsquo;animisme ni conditionn\u00e9 par l&rsquo;indigence profonde du pr\u00e9tendu d\u00e9bat sur #l\u00e9z\u00e9crans.<\/p>\n\n\n\n<p>Nous avons donc un tas de PLA, de composants \u00e0 base de silicium, des c\u00e2bles en cuivre enrob\u00e9s dans du thermoplastique, quelques m\u00e9canismes et plusieurs vis en acier qui ne demandent qu&rsquo;\u00e0 \u00eatre mis en mouvement par la volont\u00e9 du programmeur. (Vous noterez que je suis jeune depuis suffisamment longtemps pour ne pas \u00e9crire codeur).<\/p>\n\n\n\n<p>Le billet qui suit reprend le programme de mise en fonctionnement de la tortue (<a href=\"https:\/\/albooms.fr\/ressources\/tortues\/Tortue_Robot_BT.zip\">t\u00e9l\u00e9chargeable ici)<\/a> pour le diss\u00e9quer. Cette mise \u00e0 nu ayant pour seul objectif de vous donner envie de reprendre ces instructions pour que vous fassiez faire \u00e0 la tortue ce que vous voulez.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Les choix retenus pour la communication<\/h5>\n\n\n\n<p>Le robot est command\u00e9 par une communication sur un port s\u00e9rie Bluetooth. L&rsquo;id\u00e9e est d&rsquo;envoyer au robot un caract\u00e8re ASCII sur le port s\u00e9rie du robot. Chaque caract\u00e8re est associ\u00e9 \u00e0 une commande et, le plus souvent, \u00e0 une variable. Cette commande permet l&rsquo;ex\u00e9cution d&rsquo;une op\u00e9ration \u00e9l\u00e9mentaire du robot. Si vous pensez que les phrases pr\u00e9c\u00e9dentes comprennent des jurons, ce n&rsquo;est pas grave, je vais vous faire un sch\u00e9ma. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"258\" src=\"https:\/\/albooms.fr\/wp-content\/uploads\/2024\/05\/boucle-1024x258.png\" alt=\"\" class=\"wp-image-1215\" srcset=\"https:\/\/albooms.fr\/wp-content\/uploads\/2024\/05\/boucle-1024x258.png 1024w, https:\/\/albooms.fr\/wp-content\/uploads\/2024\/05\/boucle-300x76.png 300w, https:\/\/albooms.fr\/wp-content\/uploads\/2024\/05\/boucle-768x194.png 768w, https:\/\/albooms.fr\/wp-content\/uploads\/2024\/05\/boucle-1536x387.png 1536w, https:\/\/albooms.fr\/wp-content\/uploads\/2024\/05\/boucle-2048x516.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Principe de commande de la tortue de sol<\/figcaption><\/figure>\n\n\n\n<p>Ainsi, si une fonction \u00ab\u00a0avancer de x centim\u00e8tres\u00a0\u00bb est programm\u00e9e dans la tortue de sol et que ce programme est associ\u00e9 (arbitrairement) \u00e0 la lettre K; le fait d&rsquo;envoyer la lettre K sur le port s\u00e9rie lance le sous-programme \u00ab\u00a0avancer de x centim\u00e8tres\u00a0\u00bb au robot qui l&rsquo;ex\u00e9cute.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Les biblioth\u00e8ques et les d\u00e9clarations de variables<\/h5>\n\n\n\n<p>Le code d\u00e9bute par l&rsquo;appel aux biblioth\u00e8ques du servomoteur, de la LED RGB et du module Bluetooth.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/Biblioth\u00e8ques\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n#include &lt;Servo.h&gt; \/\/ biblioth\u00e8que servomoteur\n#include &lt;Adafruit_NeoPixel.h&gt; \/\/ biblioth\u00e8que LED RGB\n#include &lt;SoftwareSerial.h&gt; \/\/ biblioth\u00e8que BlueTooth<\/code><\/pre>\n\n\n\n<p>Le servomoteur est ensuite configur\u00e9. Il est connect\u00e9 sur la broche digitale 7. Il effectue une rotation de 90\u00b0 entre la position basse (stylo en position d&rsquo;\u00e9criture) et la position haute (stylo en position de repos). Il est pr\u00e9f\u00e9rable de monter la came lorsque le servomoteur est en position basse. Le servomoteur sera appel\u00e9 Servo_stylo dans le programme.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ configuration servo\nint broche_servo = 7; \/\/ d\u00e9fini la broche du servomoteur\nint angle_stylo_B = 0; \/\/ angle du servo avec le stylo en bas\nint angle_stylo_H = 90; \/\/ angle du servo avec le stylo en bas\nServo Servo_stylo; \/\/ nom du servo<\/code><\/pre>\n\n\n\n<p>Le port s\u00e9rie Bluetooth sera d\u00e9clar\u00e9 de la fa\u00e7on suivante. D&rsquo;une part, nous allons cr\u00e9\u00e9 une variable d&rsquo;\u00e9coute du port, et d&rsquo;autre part, nous d\u00e9clarons le module Bluetooth en \u00e9coute sur la broche 0 et de transmission sur la broche 1. La variable d&rsquo;\u00e9coute permettra de n&rsquo;interpr\u00e9ter que le premier caract\u00e8re d&rsquo;une chaine transmise, par exemple lors de la transmission directe gr\u00e2ce \u00e0 un t\u00e9l\u00e9phone.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/  Variables d'ecoute du port s\u00e9rie\nString ent_serie; \/\/ r\u00e9cup\u00e8re la chaine de caract\u00e8re entr\u00e9e sur le port s\u00e9rie\nint ENTREE;\n\n\/\/ configuration du port s\u00e9rie BlueTooth\nint Rx=0;\nint Tx=1;\nSoftwareSerial BTmySerial(Rx, Tx); \/\/ RX, TX<\/code><\/pre>\n\n\n\n<p>Les variables cr\u00e9es ici sont peut-\u00eatre les plus \u00ab\u00a0sensibles\u00a0\u00bb du robot, puisque ce sont elles qui permettront son \u00e9talonnage. Le diam\u00e8tre des roues permet de r\u00e9gler l&rsquo;avance en d\u00e9placement. L&rsquo;entraxe permettra de r\u00e9gler les d\u00e9placements angulaires.<\/p>\n\n\n\n<p class=\"has-pale-cyan-blue-color has-text-color has-link-color wp-elements-0f37cd10c98b5b4371359e2715624de3\"><strong>ATTENTION:<\/strong> votre robot est un robot artisanal, il sera difficile de lui faire faire des figures aussi parfaites qu&rsquo;avec un logiciel. N\u00e9anmoins, un calibrage pr\u00e9cis peut donner des figures dont la pr\u00e9cision avoisine le millim\u00e8tre.<\/p>\n\n\n\n<p>Le nombre de pas par tour d\u00e9pend du mod\u00e8le de moteur pas \u00e0 pas (512 est le nombre de pas par tour du moteur pr\u00e9conis\u00e9).<\/p>\n\n\n\n<p>Le d\u00e9lai entre pas. La pr\u00e9conisation est de 10ms entre pas. On peut descendre en dessous, mais le risque de sauter des pas augmente avec la diminution de la temporisation.<\/p>\n\n\n\n<p>Je propose de cr\u00e9er une variable flottante qui calcule l&rsquo;avance de la roue du robot pour un pas de moteur. Elle sera utilis\u00e9e ult\u00e9rieurement  pour les calculs de d\u00e9placement.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Variables de d\u00e9placement\nfloat dia_roue=59.9; \/\/diam\u00e8tre des roues (augmentation = diminution distance parcourue)\nfloat entraxe=112.9; \/\/entraxe (augmentation = augmentation de la rotation angulaire)\nint Paspartour=512; \/\/voir la documentation du r\u00e9ducteur\nint duree_delai=10; \/\/attente entre pas in ms (10 mini)\nfloat AvanceParPas = (3.1415926 * dia_roue)\/Paspartour; \/\/calcule l'avance d'un pas<\/code><\/pre>\n\n\n\n<p>Nous allons maintenant cr\u00e9er des variables et des matrices pour le d\u00e9placement du moteur pas \u00e0 pas. Nous retrouvons tout d&rsquo;abord les d\u00e9clarations des broches mobilis\u00e9es par ces moteurs gauche (G) ou droite (D) <a href=\"https:\/\/albooms.fr\/?p=1171\">voir ici pour le c\u00e2blage physique<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Variables moteurs pas \u00e0 pas \nint broches_MoteurG&#91;4] = { 2, 3, 4, 5};\nint broches_MoteurD&#91;4] = { 10, 11, 12, 13};<\/code><\/pre>\n\n\n\n<p>Pour les matrices permettant la rotation des moteurs, nous envisageons que le moteur puisse tourner dans le sens horaire (dextro) ou antihoraire (levo) en regardant depuis le moteur vers la roue.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const  byte dextro&#91;4]&#91;4] =  {  \/\/rotation sens horaire depuis le moteur vers l'ext\u00e9rieur\n                          {HIGH, LOW, LOW, HIGH},\n                          {LOW, LOW, HIGH, HIGH},\n                          {LOW, HIGH, HIGH, LOW},\n                          {HIGH, HIGH, LOW, LOW},                              \n                          };\n\nconst  byte levo&#91;4]&#91;4] =  { \/\/rotation sens anti-horaire depuis le moteur vers l'ext\u00e9rieur \n                          {HIGH, HIGH, LOW, LOW},\n                          {LOW, HIGH, HIGH, LOW},\n                          {LOW, LOW, HIGH, HIGH},\n                          {HIGH, LOW, LOW, HIGH},     \n                          };<\/code><\/pre>\n\n\n\n<p>Vous trouverez de nombreuses pages sur le fonctionnement des moteurs pas \u00e0 pas qui vous permettront de comprendre la logique de ce codage. Ce qu&rsquo;il faut comprendre ici, c&rsquo;est qu&rsquo;un moteur pas \u00e0 pas est compos\u00e9 de 4 \u00e9lectroaimants qui sont alternativement aliment\u00e9s (HIGH) ou coup\u00e9s (LOW) pour d\u00e9placer le moteur d&rsquo;un pas.<\/p>\n\n\n\n<p>Le speaker est configur\u00e9 sur la broche 6. Nous profitons de cette d\u00e9claration pour cr\u00e9er un flag pour emp\u00eacher ou autoriser le d\u00e9clenchement des bips.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ configuration speaker\nint broche_speaker = 6; \/\/ Broche du speaker\nint speak = 0; \/\/ Flag pour emp\u00eacher le bip apr\u00e8s l'appel d'une boucle sonore<\/code><\/pre>\n\n\n\n<p>La LED RGB est configur\u00e9e selon les pr\u00e9conisations du site Grove SEEED.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ configuration led RGB\nint broche_RGB =8; \/\/ Broche de la led multicolore\nAdafruit_NeoPixel led_RGB = Adafruit_NeoPixel(1, broche_RGB, NEO_GRB + NEO_KHZ800);<\/code><\/pre>\n\n\n\n<p>Les d\u00e9clarations sont termin\u00e9es, nous allons maintenant passer \u00e0 l&rsquo;initialisation de la carte.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">L&rsquo;initialisation du robot &#8211; void setup()<\/h5>\n\n\n\n<p>Nous allons maintenant nous int\u00e9resser \u00e0 la fonction setup. Elle commence par l&rsquo;ouverture du port s\u00e9rie Bluetooth. Le mod\u00e8le Grove SEEED retenu fonctionne \u00e0 9600 Baud, mais cela peut changer si vous utilisez d&rsquo;autres modules Bluetooth.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void setup() \n{\n  \/\/ Initialise le port s\u00e9rie \n  BTmySerial.begin(9600); \/\/ ouvre le port s\u00e9rie et fixe le d\u00e9bit \u00e0 9600 bauds<\/code><\/pre>\n\n\n\n<p>Ensuite, c&rsquo;est le servomoteur qui est initialis\u00e9. La broche (D7) est d\u00e9clar\u00e9e, elle est configur\u00e9e en mode sortie. La rotation du servo met la came du style, et par cons\u00e9quent le stylo, en position haute. Enfin l&rsquo;alimentation de la broche est coup\u00e9e pour essayer d&rsquo;\u00e9conomiser les batteries. Un d\u00e9lai de 200 ms est demand\u00e9 pour attendre la fin de l&rsquo;op\u00e9ration.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/ initialisation le Servo_stylo\n  Servo_stylo.attach(broche_servo); \/\/ d\u00e9claration de la broche\n  pinMode(broche_servo, OUTPUT); \/\/ met la broche en mode sortie\n  stylo_H(); \/\/ monter le porte stylo en haut\n  digitalWrite (broche_servo, LOW); \/\/ coupe la broche du servo pour \u00e9conomiser les batteries\n  delay(200);<\/code><\/pre>\n\n\n\n<p>Les moteurs pas \u00e0 pas sont ensuite initialis\u00e9s, et l&rsquo;alimentation des moteurs est coup\u00e9e \u00e9galement pour \u00e9conomiser les batteries. Cette instruction est assez inutile dans le programme actuel, puisque nous allons d\u00e9marrer tr\u00e8s prochainement les moteurs pas \u00e0 pas, mais j&rsquo;ai estim\u00e9 qu&rsquo;il \u00e9tait important de la conserver pour des \u00e9volutions ult\u00e9rieures de programmation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ initialisation Moteurs pas \u00e0 pas \n    for(int pin=0; pin&lt;4; pin++)\n      {\n      pinMode(broches_MoteurG&#91;pin], OUTPUT); \/\/ met les broches du moteur gauche en mode sortie\n      digitalWrite(broches_MoteurG&#91;pin], LOW); \/\/ coupe la broche du moteur gauche pour \u00e9conomiser les batteries\n      pinMode(broches_MoteurD&#91;pin], OUTPUT); \/\/ met les broches du moteur droit en mode sortie\n      digitalWrite(broches_MoteurD&#91;pin], LOW); \/\/ coupe la broche du moteur droit pour \u00e9conomiser les batteries\n      }<\/code><\/pre>\n\n\n\n<p>La fonction setup appelle ensuite plusieurs fonctions pour d\u00e9marrer le robot. Nous en verrons le codage plus tard. Ces fonctions sont:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration du Bluetooth avec purge du buffer du port s\u00e9rie;<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/ configure le BT\n    BTConfig();<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Une petite \u00ab\u00a0danse de d\u00e9marrage\u00a0\u00bb pour v\u00e9rifier si le robot le robot est fonctionnel;<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>    \/\/ Fais bouger le robot\n    avance(5);\n    recule(5);\n    tournegauche(5);\n    tournedroite(5);<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Une m\u00e9lodie de fin pour signaler que le robot est pr\u00eat \u00e0 recevoir des consignes. J&rsquo;ai repris, comme dans la tortue Jeulin, \u00ab\u00a0Au clair de la lune\u00a0\u00bb, mais si vous vous sentez l&rsquo;\u00e2me musicienne, il est facile de changer la m\u00e9lodie comme nous le verrons plus loin.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>   \/\/ joue la m\u00e9lodie pour signaler que la tortue est pr\u00eate \n    melodie();<\/code><\/pre>\n\n\n\n<p>La fonction setup est termin\u00e9e, nous allons nous int\u00e9resser \u00e0 la boucle principale.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">La boucle principale &#8211; void loop() <\/h5>\n\n\n\n<p>La boucle principale d\u00e9bute par l&rsquo;\u00e9coute du port s\u00e9rie. J&rsquo;ai mis une \u00ab\u00a0s\u00e9curit\u00e9\u00a0\u00bb en place qui consiste \u00e0 n&rsquo;interpr\u00e9ter que le premier caract\u00e8re d&rsquo;une chaine, gr\u00e2ce \u00e0 la variable ENTREE, d\u00e9clar\u00e9e au d\u00e9but du programme. Il fait suite \u00e0 quelques essais  et bugs de communication via smartphone. Ce choix est discutable et peut \u00eatre modifi\u00e9 par l&rsquo;utilisateur, si besoin. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void loop() \n{\n  \/\/ ecoute du port s\u00e9rie\n  if (BTmySerial.available()) \/\/ecoute le port s\u00e9rie si re\u00e7oit une donn\u00e9e\n        { \n          ent_serie = BTmySerial.readString(); \/\/ lit la chaine envoy\u00e9e sur le port s\u00e9rie\n          ENTREE = ent_serie.charAt(0);  \/\/ extrait le premier caract\u00e8re (s\u00e9curit\u00e9 pour traiter les commandes une \u00e0 une);        \n          BTmySerial.println(ENTREE);  \/\/ lit le premier caract\u00e8re <\/code><\/pre>\n\n\n\n<p>La partie qui suit me semble \u00eatre le c\u0153ur du programme. En fonction du caract\u00e8re re\u00e7u sur le port Bluetooth, le programme principal appelle la fonction associ\u00e9e. Par exemple, si le caract\u00e8re H (code d\u00e9cimal 72) est lu sur le port s\u00e9rie, la fonction stylo_H est appel\u00e9e. Autre exemple, si le port s\u00e9rie re\u00e7oit le caract\u00e8re A (code d\u00e9cimal 65), la fonction avance est appel\u00e9e avec une variable 100, qui correspond \u00e0 la longueur en mm de l&rsquo;avance.<\/p>\n\n\n\n<p>C&rsquo;est ici que vous pouvez cr\u00e9er de \u00ab\u00a0nouvelles commandes\u00a0\u00bb personnalis\u00e9es en utilisant les caract\u00e8res ASCII non r\u00e9f\u00e9renc\u00e9s. Par exemple, les fonctions test_carre() et demi_tour() sont des fonctions sp\u00e9cifiques \u00e0 l&rsquo;\u00e9talonnage de la tortue. Elles permettent d&rsquo;am\u00e9liorer la pr\u00e9cision de <em>dia_roue<\/em> et <em>entraxe.<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>switch (ENTREE)\n        {\n                                         \/***************************\n                                         * Gestion des cartes roses *\n                                         *     modules Grove SEED   *\n                                         ***************************\/\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/ cartes roses servo moteur \/\/\n         \/\/        Grove Servo        \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case 'B': \/\/ caract\u00e8re B\n        stylo_B(); \/\/ appelle stylo bas\n        break;\n\n        case 'H':\n        stylo_H(); \/\/ H = stylo haut\n        break;\n\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/      Cartes roses phare led       \/\/\n         \/\/ Module \u00e0 LED RGB Grove 104020169  \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case '!':\n        allume_bleu(); \/\/ ! = allume la led en bleu\n        break;    \n\n        case '\"':\n        allume_vert(); \/\/ \" = allume la led en vert\n        break;          \n\n        case '#':\n        allume_rouge(); \/\/ # = allume la led en rouge\n        break;\n\n        case '$':\n        allume_violet(); \/\/ $ = allume la led en violet\n        break;\n\n        case '%':\n        allume_turquoise(); \/\/ % = allume la led en turquoise\n        break;\n\n        case '&amp;':\n        allume_jaune(); \/\/ &amp; = allume la led en jaune\n        break;\n        \n        case '+':\n        allume_blanc(); \/\/ + = allume la led en blanc\n        break;\n\n        case '-':\n        eteins_led(); \/\/ - = allume la led en blanc\n        break;        \n \n\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/   Cartes roses speaker    \/\/\n         \/\/ Module HP Grove 107020001 \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case 'J':\n        melodie(); \/\/ J = joue une m\u00e9lodie\n        fin();\n        break;\n\n        case 'K':\n        bip(); \/\/ K = bip\n        fin();\n        break;\n\n        case 'P':\n        rale(); \/\/ P = rale\n        fin();\n        break;\n\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/  Cartes Jaunes d\u00e9placements \/\/\n         \/\/ Pilotage moteurs pas \u00e0 pas  \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n        case 's':\n        avance(10); \/\/ s = avance de 10 mm\n        break;\n\n        case 'A':\n        avance(100); \/\/ A = avance de 100 mm\n        break;\n\n        case 'F':\n        avance(200); \/\/ F = avance de 200 mm\n        break;\n\n        case 't':\n        recule(10); \/\/t = recule de 10 mm\n        break;\n\n        case 'R':\n        recule(100); \/\/R = recule de 10 mm\n        break;\n\n        case 'U':\n        recule(200); \/\/U = recule de 200 mm\n        break;\n\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/   Cartes Jaunes rotation   \/\/\n         \/\/ Pilotage moteurs pas \u00e0 pas \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n        case 'v':\n        tournegauche(1); \/\/ v = tourne 1 degr\u00e9 gauche\n        break;\n\n        case 'G':\n        tournegauche(15); \/\/ G = tourne 15 degr\u00e9 gauche\n        break;  \n\n        case 'c':\n        tournegauche(30); \/\/ c = tourne 30 degr\u00e9 gauche\n        break;         \n\n        case 'f':\n        tournegauche(45); \/\/ f = tourne 45 degr\u00e9 gauche\n        break;  \n\n        case 'i':\n        tournegauche(60); \/\/ i = tourne 60 degr\u00e9 gauche\n        break;  \n\n        case 'l':\n        tournegauche(90); \/\/ l = tourne 90 degr\u00e9 gauche\n        break;  \n\n        case 'o':\n        tournegauche(120); \/\/ o = tourne 120 degr\u00e9 gauche\n        break;  \n\n        case 'u':\n        tournedroite(1); \/\/ u = tourne 1 degr\u00e9 droite\n        break;  \n\n        case 'D':\n        tournedroite(15); \/\/ D = tourne 15 degr\u00e9 droite\n        break; \n\n        case 'b':\n        tournedroite(30); \/\/ b = tourne 30 degr\u00e9 droite\n        break; \n\n        case 'e':\n        tournedroite(45); \/\/ e = tourne 45 degr\u00e9 droite\n        break; \n\n        case 'h':\n        tournedroite(60); \/\/ h = tourne 60 degr\u00e9 droite\n        break; \n\n        case 'k':\n        tournedroite(90); \/\/ k = tourne 90 degr\u00e9 droite\n        break; \n\n        case 'n':\n        tournedroite(120); \/\/ n = tourne 120 degr\u00e9 droite\n        break; \n\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/ Cartes Vertes 1\/4 de cercle \/\/\n         \/\/  Pilotage moteurs pas \u00e0 pas \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case '1':\n        avantdroite(100); \/\/ 1 = arc de cercle av dr rayon 100 mm\n        break; \n\n        case '5':\n        avantdroite(200); \/\/ 5 = arc de cercle av dr rayon 200 mm\n        break; \n\n\n        case '2':\n        avantgauche(100); \/\/ 2 = arc de cercle av g rayon 100 mm\n        break; \n\n        case '6':\n        avantgauche(200); \/\/ 6 = arc de cercle av g rayon 200 mm\n        break; \n\n        case '3':\n        arrieregauche(100); \/\/ 3 = arc de cercle ar g rayon 100 mm\n        break; \n\n        case '7':\n        arrieregauche(200); \/\/ 7 = arc de cercle ar g rayon 200 mm\n        break; \n\n        case '4':\n        arrieredroite(100); \/\/ 4 = arc de cercle ar dr rayon 100 mm\n        break; \n\n        case '8':\n        arrieredroite(200); \/\/ 8 = arc de cercle ar dr rayon 200 mm\n        break;\n\n           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/ Cartes Vertes 1\/4 de cercle \/\/\n         \/\/  Pilotage moteurs pas \u00e0 pas \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n        case 'a':\n        avance(0); \/\/ a = avance d'un pas\n        break;\n\n        case 'g':\n        tournegauche(0); \/\/ g = tourne d'un pas \u00e0 gauche\n        break;\n        \n        case 'd':\n        tournedroite(0); \/\/ d = tourne d'un pas \u00e0 droite\n        break;  \n\n        case 'r':\n        recule(0); \/\/ r = recule d'un pas\n        break;\n\n        case 'x':\n        test_carre();  \/\/ x lance la proc\u00e9dure d'\u00e9talonnage avec le carr\u00e9\n        break;\n\n        case 'y':\n        demi_tour(); \/\/ y lance la proc\u00e9dure d'\u00e9tallonnage avec le demi tour \n        break;\n\n        case 'z':\n        demo_maison(); \/\/ z lance la d\u00e9mo maison \n        break;\n      }\n  }\n}    <\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">les fonctions<\/h5>\n\n\n\n<h6 class=\"wp-block-heading\">La gestion du porte stylo<\/h6>\n\n\n\n<p>Elle est appel\u00e9e par les caract\u00e8res suivants <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/ cartes roses servo moteur \/\/\n         \/\/        Grove Servo        \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case 'B': \/\/ caract\u00e8re B\n        stylo_B(); \/\/ appelle stylo bas\n        break;\n\n        case 'H':\n        stylo_H(); \/\/ H = stylo haut\n        break;<\/code><\/pre>\n\n\n\n<p>Le porte stylo comporte 2 \u00e9tats <em>stylo en haut<\/em> ou <em>stylo en bas<\/em>. Le fonctionnement est identique pour les fonctions <em>stylo_<\/em>H et <em>stylo_B<\/em>. la broche est aliment\u00e9e, puis apr\u00e8s une temporisation, le servo moteur est amen\u00e9 \u00e0 l&rsquo;angle souhait\u00e9 (<em>angle_stylo_h<\/em> ou <em>angle_stylo_b<\/em>). Apr\u00e8s une nouvelle temporisation, l&rsquo;alimentation de la broche est coup\u00e9e.<\/p>\n\n\n\n<pre class=\"wp-block-code has-base-color has-white-background-color has-text-color has-background has-link-color has-small-font-size wp-elements-3f27af65cf6317f8e6c23daaa2431139\"><code>\/***************************************************************************\n *  gestion du porte sylo\n ***************************************************************************\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ rel\u00e8ve la came du porte-stylo \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid stylo_H () \n    {\n      digitalWrite (broche_servo, HIGH); \/\/ allume la broche du servo\n      delay(250);\n      Servo_stylo.write(angle_stylo_H); \/\/ met le servo sur la position haute\n      delay(250);\n      digitalWrite (broche_servo, LOW); \/\/ coupe la broche du servo (economie)\n      fin();\n    }\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ baisse la came du porte-stylo \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid stylo_B () \/\/ baisse la came du porte-stylo en haut\n    {\n      digitalWrite (broche_servo, HIGH); \/\/ allume la broche du servo\n      delay(250);\n      Servo_stylo.write(angle_stylo_B); \/\/ met le servo sur la position basse\n      delay(250);\n      digitalWrite (broche_servo, LOW); \/\/ coupe la broche du servo (economie)\n      fin();\n    }<\/code><\/pre>\n\n\n\n<h6 class=\"wp-block-heading\">Les fonctions avance et recule<\/h6>\n\n\n\n<p>Elles sont appel\u00e9es par les caract\u00e8res suivants:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/  Cartes Jaunes d\u00e9placements \/\/\n         \/\/ Pilotage moteurs pas \u00e0 pas  \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n        case 's':\n        avance(10); \/\/ s = avance de 10 mm\n        break;\n\n        case 'A':\n        avance(100); \/\/ A = avance de 100 mm\n        break;\n\n        case 'F':\n        avance(200); \/\/ F = avance de 200 mm\n        break;\n\n        case 't':\n        recule(10); \/\/t = recule de 10 mm\n        break;\n\n        case 'R':\n        recule(100); \/\/R = recule de 10 mm\n        break;\n\n        case 'U':\n        recule(200); \/\/U = recule de 200 mm\n        break;<\/code><\/pre>\n\n\n\n<p>Avec les cartes, je me contente, de 3 valeurs d&rsquo;avance 10, 100 et 200 mm ( et une fonction avance d&rsquo;un pas pour test). J&rsquo;ai pour projet d&rsquo;utiliser des variables ult\u00e9rieurement. Ces valeurs sont toutefois suffisantes pour mes essais actuels. Bien \u00e9videmment, vous pouvez faire d&rsquo;autres choix, par exemple avec des \u00ab\u00a0pas\u00a0\u00bb de 10, 20 et 30 cm.<\/p>\n\n\n\n<p>Les fonctions \u00ab\u00a0avance\u00a0\u00bb ou \u00ab\u00a0recule\u00a0\u00bb font tourner les moteurs pas \u00e0 pas gauche et droite du nombre de pas calcul\u00e9 par la routine <em>step <\/em>alternativement. Les sens de rotation des moteurs sont appel\u00e9s par les matrices <em>dextro[mask][pin]<\/em> ou <em>levo[mask][pin]<\/em>. Il faut qu&rsquo;un des moteurs tourne dans un sens horaire et l&rsquo;autre dans un sens antihoraire pour que la tortue avance ou recule.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************\n *  deplacement avant arri\u00e8re\n * utilise la sous routine \"step\" pour calculer le nombre de pas \n***************************************************************************\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ avance de la distance d\u00e9finie en cm \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid avance (float distance) \n  {\n  int steps = step(distance); \/\/ affecte le nombre de pas \u00e0 steps\n\n  for(int step=0; step&lt;steps; step++) \/\/ boucle sur le nombre de pas moteurs \u00e0 effectuer\n    {\n    for(int mask=0; mask&lt;4; mask++)\n      {\n      for(int pin=0; pin&lt;4; pin++)\n        {\n        digitalWrite(broches_MoteurG&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ avance le moteur gauche d'un pas\n        digitalWrite(broches_MoteurD&#91;pin], levo&#91;mask]&#91;pin]); \/\/ avance le moteur droit d'un pas\n        }\n      delay(duree_delai);\n      } \n    }\n    fin();\n  }\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ recule de la distance d\u00e9finie en cm \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid recule (float distance) \/\/ recule de la distance d\u00e9finie en cm\n  {\n    int steps = step(distance);\n\n    for(int step=0; step&lt;steps; step++) \/\/ boucle sur le nombre de pas moteurs \u00e0 effectuer\n      {\n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurG&#91;pin], levo&#91;mask]&#91;pin]); \/\/ recule le moteur gauche d'un pas\n          digitalWrite(broches_MoteurD&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ recule le moteur droit d'un pas\n          }\n        delay(duree_delai);\n        } \n      }\n      fin();\n  }\n  \n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/         sous routine \"step\"           \/\/\n\/\/\u00e9tablit le nombre de pas de d\u00e9placement\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nint step(float distance) \/\/ retourne le nombre de pas pour r\u00e9aliser la distance\n  {\n    int steps = distance \/ AvanceParPas; \/\/ calcule le nombre de pas\n    if (steps==0) \/\/ permet les avances d'un pas en affectant 0\n    {\n      steps=1;\n    }\n  return steps; \/\/ retourne le nombre de pas \n  }\n<\/code><\/pre>\n\n\n\n<h6 class=\"wp-block-heading\">Les rotations angulaires autour du stylo<\/h6>\n\n\n\n<p>Cette fonction est sans doute la moins pr\u00e9cise de toutes, car elle n\u00e9cessite une qualit\u00e9 de fabrication irr\u00e9prochable. Autrement dit, plus la construction et l&rsquo;assemblage sont soign\u00e9s, plus cette rotation sera pr\u00e9cise. Il est intuile d&rsquo;\u00e9talonner informatiquement le robot s&rsquo;il est mal fabriqu\u00e9. L&rsquo;impression 3D, si elle offre de la souplesse, n\u00e9cessite une maitrise de processus d&rsquo;impression importante pour obtenir des tol\u00e9rances dimensionnelles qui resteront relativement peu satisfaisantes pour un m\u00e9canicien. J&rsquo;ai fait le choix de privil\u00e9gier la facilit\u00e9 de r\u00e9alisation et la maitrise des couts en sacrifiant une partie de la pr\u00e9cision (<a href=\"https:\/\/albooms.fr\/?p=1147\">voir ici<\/a>). C&rsquo;est dans cette rotation angulaire que cette difficult\u00e9 est la plus difficile \u00e0 surmonter. Les fonctions <em>tournegauche <\/em>et <em>tournedroite <\/em>peuvent prendre les valeurs angulaires suivantes 1,15,30,45,60,120 degr\u00e9. On retrouve \u00e9galement la rotation de 1 pas. Ici aussi, ces valeurs peuvent \u00eatre chang\u00e9 ou compl\u00e9t\u00e9es, si besoin.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/   Cartes Jaunes rotation   \/\/\n         \/\/ Pilotage moteurs pas \u00e0 pas \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n        case 'v':\n        tournegauche(1); \/\/ v = tourne 1 degr\u00e9 gauche\n        break;\n\n        case 'G':\n        tournegauche(15); \/\/ G = tourne 15 degr\u00e9 gauche\n        break;  \n\n        case 'c':\n        tournegauche(30); \/\/ c = tourne 30 degr\u00e9 gauche\n        break;         \n\n        case 'f':\n        tournegauche(45); \/\/ f = tourne 45 degr\u00e9 gauche\n        break;  \n\n        case 'i':\n        tournegauche(60); \/\/ i = tourne 60 degr\u00e9 gauche\n        break;  \n\n        case 'l':\n        tournegauche(90); \/\/ l = tourne 90 degr\u00e9 gauche\n        break;  \n\n        case 'o':\n        tournegauche(120); \/\/ o = tourne 120 degr\u00e9 gauche\n        break;  \n\n        case 'u':\n        tournedroite(1); \/\/ u = tourne 1 degr\u00e9 droite\n        break;  \n\n        case 'D':\n        tournedroite(15); \/\/ D = tourne 15 degr\u00e9 droite\n        break; \n\n        case 'b':\n        tournedroite(30); \/\/ b = tourne 30 degr\u00e9 droite\n        break; \n\n        case 'e':\n        tournedroite(45); \/\/ e = tourne 45 degr\u00e9 droite\n        break; \n\n        case 'h':\n        tournedroite(60); \/\/ h = tourne 60 degr\u00e9 droite\n        break; \n\n        case 'k':\n        tournedroite(90); \/\/ k = tourne 90 degr\u00e9 droite\n        break; \n\n        case 'n':\n        tournedroite(120); \/\/ n = tourne 120 degr\u00e9 droite\n        break; \n\n<\/code><\/pre>\n\n\n\n<p>Du point de vue informatique, la programmation reste simple et reprend le principe des fonctions avance ou recule, sauf que, cette fois, les sens de rotation des moteurs sont identiques (levo\/levo ou dextro\/dextro). <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************\n * rotation sur l'axe du stylo\n * utilise la sous routine \"stepR\" pour calculer le nombre de pas \n***************************************************************************\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ tourne sur la gauche d'un angle d\u00e9fini \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n  void tournegauche (float angle)\n  {\n    \n    int steps = stepR(angle); \/\/ demande le calcul dun nombre de pas\n    for(int stepR=0; stepR&lt;steps; stepR++) \/\/ boucle sur le nombre de pas moteurs \u00e0 effectuer\n      {\n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurG&#91;pin], levo&#91;mask]&#91;pin]); \/\/ recule le moteur gauche d'un pas\n          digitalWrite(broches_MoteurD&#91;pin], levo&#91;mask]&#91;pin]); \/\/ avance le moteur droit d'un pas\n          }\n        delay(duree_delai);\n        } \n      }\n    fin();\n  }\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ tourne sur la droite d'un angle d\u00e9fini \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n   void tournedroite (float angle) \/\/ tourne sur la droite d'un angle d\u00e9fini\n    {\n   \n    int steps = stepR(angle); \/\/ demande le calcul dun nombre de pas\n \n    for(int stepR=0; stepR&lt;steps; stepR++) \/\/ boucle sur le nombre de pas moteurs \u00e0 effectuer\n      {\n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurG&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ avance le moteur gauche d'un pas\n          digitalWrite(broches_MoteurD&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ recule le moteur droit d'un pas\n          }\n        delay(duree_delai);\n        } \n      }\n      fin();\n    }\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/          sous routine \"stepR\"            \/\/\n\/\/\u00e9tablit le nombre de pas pour la rotation \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nint stepR(float angle){\n  int stepsR = ((entraxe * angle* 3.1415926)\/360)  * Paspartour \/ (dia_roue * 3.1415926); \/\/ Calcule le nombre de pas pour tourner d'un angle d\u00e9fini\n  if (stepsR==0) \/\/ permet les avances d'un pas en affectant 0\n  {\n    stepsR=1;\n  }\n  \n return stepsR; \/\/ retourne le nombre de pas\n}\n<\/code><\/pre>\n\n\n\n<h6 class=\"wp-block-heading\">Cr\u00e9er des arcs de cercle<\/h6>\n\n\n\n<p>La tortue peut cr\u00e9er des quarts de cercle. Ce choix est directement issu de la tortue Jeulin. Comme, je n&rsquo;ai pas encore travaill\u00e9 sur la notion de cercle avec des \u00e9l\u00e8ves, je ne sais pas si le quart de cercle est plus pertinent que le cercle. En d\u00e9monstration, c&rsquo;est assez \u00e9tonnant de tracer des quarts de cercle avec ou sans segments.<\/p>\n\n\n\n<p>ici aussi, les valeurs des rayons des cercles sont pr\u00e9determin\u00e9es (100 ou 200mm), et la tortue peut les r\u00e9aliser en avan\u00e7ant ou reculant, en tournant \u00e0 droite ou \u00e0 gauche.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/ Cartes Vertes 1\/4 de cercle \/\/\n         \/\/  Pilotage moteurs pas \u00e0 pas \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case '1':\n        avantdroite(100); \/\/ 1 = arc de cercle av dr rayon 100 mm\n        break; \n\n        case '5':\n        avantdroite(200); \/\/ 5 = arc de cercle av dr rayon 200 mm\n        break; \n\n\n        case '2':\n        avantgauche(100); \/\/ 2 = arc de cercle av g rayon 100 mm\n        break; \n\n        case '6':\n        avantgauche(200); \/\/ 6 = arc de cercle av g rayon 200 mm\n        break; \n\n        case '3':\n        arrieregauche(100); \/\/ 3 = arc de cercle ar g rayon 100 mm\n        break; \n\n        case '7':\n        arrieregauche(200); \/\/ 7 = arc de cercle ar g rayon 200 mm\n        break; \n\n        case '4':\n        arrieredroite(100); \/\/ 4 = arc de cercle ar dr rayon 100 mm\n        break; \n\n        case '8':\n        arrieredroite(200); \/\/ 8 = arc de cercle ar dr rayon 200 mm\n        break;\n<\/code><\/pre>\n\n\n\n<p>Les cercles sont relativement pr\u00e9cis (moins que les longueurs des segments, mais plus que les rotations angulaires). Dans l&rsquo;absolu, il ne s&rsquo;agit par r\u00e9ellement de cercles, mais d&rsquo;une approximation de cercle. En effet, le programme calcule le nombre de pas qui correspond au p\u00e9rim\u00e8tre du parcours du quart de cercle de la roue int\u00e9rieure au cercle (routine stepint) et fait la m\u00eame chose pour la roue ext\u00e9rieure.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/                      sous routine \"stepext\"                     \/\/\n\/\/\u00e9tablit le nombre de pas pour la rotation pour la roue exterieure\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nint stepsext(float dia_rot) \n  {\n    float perim_ext= (3.1415926 * ((dia_rot) + (entraxe)))\/4; \/\/ calcule le p\u00e9rim\u00e8tre parcouru par la roue ext\u00e9rieure\n    int steps_ext = perim_ext\/AvanceParPas  ; \/\/ nombre de pas n\u00e9cessaires \n    return steps_ext;  \n  }\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/                      sous routine \"stepint\"                     \/\/\n\/\/\u00e9tablit le nombre de pas pour la rotation pour la roue exterieure\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nint stepsint(float dia_rot)  \n  {\n      float perim_int= (3.1415926 * ((dia_rot) - (entraxe)))\/4; \/\/ calcule le p\u00e9rim\u00e8tre parcouru par la roue int\u00e9rieure\n      int steps_int = perim_int\/AvanceParPas  ; \/\/ nombre de pas n\u00e9cessaires attention la valeur est n\u00e9gative si entraxe &lt; diam\u00e8tre\n      return steps_int; \n  }\n<\/code><\/pre>\n\n\n\n<p>\u00c0 partir de ces deux p\u00e9rim\u00e8tres, le programme g\u00e8re les avanc\u00e9es relatives des roues. Par exemple, pour le quart de cercle avant droit. Le programme calcule \u00e9galement le ratio entre les p\u00e9rim\u00e8tres int\u00e9rieurs et ext\u00e9rieurs.<\/p>\n\n\n\n<p>Une simple boucle fait avancer la roue externe jusqu&rsquo;\u00e0 ratio-1, \u00e0 ratio, les deux roues tournent et relance une boucle, jusqu&rsquo;\u00e0 \u00e9puisement du p\u00e9rim\u00e8tre des deux roues. L&rsquo;arc de cercle est ainsi compos\u00e9 de petits arcs de cercle dont le rayon est l&rsquo;entraxe des roues et dont la position du centre est corrig\u00e9e \u00e0 la fin de chaque boucle de <em>ratio<\/em>.<\/p>\n\n\n\n<p>Si le rayon du cercle est inf\u00e9rieur \u00e0 l&rsquo;entraxe, il faut que la roue int\u00e9rieur recule <em>(<\/em>boucle<em> if(steps_int&lt;=0){}<\/em>), au lieu d&rsquo;avancer.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************\n * d\u00e9placement en 1\/4 de cercle de diam\u00e8tre d\u00e9fini\n * utilise les sous routine \"stepsext\" et \"stepint\" \n * pour calculer le nombre de pas pour chacune des roues\n***************************************************************************\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ 1\/4 de cercle  en avan\u00e7ant sur la droite \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid avantdroite (float dia_rot) \n  {\n\n    float steps_ext = stepsext(dia_rot); \/\/ demande le nombre de pas de la roue ext\u00e9rieure\n    float steps_int = stepsint(dia_rot); \/\/ demande le nombre de pas de la roue int\u00e9rieure\n    float ratio_init = steps_ext\/abs(steps_int); \/\/ calcule le ratio entre les pas ext et les pas int\n    int step=0; \/\/ affecte 0 \u00e0 step qui comptera les pas ext\u00e9rieurs\n    float ratio_dyn=0; \/\/ affecte 0 \u00e0 ratio dyn qui permettra de g\u00e9rer les avances diff\u00e9rentielle entre roues\n    float test_ratio = ratio_init-1; \/\/ calcule test_ratio qui d\u00e9clenchera l'avance de la roue int\u00e9reur quand le ratio sera correct\n\n    while( step&lt;steps_ext)\/\/ lance la boucle tant que la  roue ext\u00e9rieure n'aura pas finit le nombre de pas \n    {        \n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurG&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait avancer la roue gauche (ext)\n          }\n          delay(duree_delai);\n        }\n        \n        ratio_dyn=ratio_dyn+1; \/\/ incr\u00e9mente le ratio dynamique\n        step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n      \n        if (ratio_dyn>= test_ratio) \/\/ si le ratio est atteint moins un pas  \n          {  \n          for(int mask=0; mask&lt;4; mask++)\n            {\n            for(int pin=0; pin&lt;4; pin++)\n            {\n            digitalWrite(broches_MoteurG&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait avancer la roue gauche (ext)           \n            \n            if (steps_int&lt;=0) \/\/ si la roue int\u00e9rieure doit reculer (diam\u00e8tre du cercle &lt;entraxe du robot)\n              {\n              digitalWrite(broches_MoteurD&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait reculer la roue droite (int)    \n              }\n              else\n              {\n              digitalWrite(broches_MoteurD&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait avancer la roue droite (int) \n              }            \n            }\n            \n            delay(duree_delai);\n            \n            }     \n          step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n          ratio_dyn= ratio_dyn-test_ratio; \/\/ calcule le ratio dyn (conserve les d\u00e9cimales pour les incr\u00e9menter de nouveau)\n          } \n  \n      } \n\n      fin();\n    }\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ 1\/4 de cercle  en avan\u00e7ant sur la gauche \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid avantgauche (float dia_rot) \n  {\n    \n    float steps_ext = stepsext(dia_rot); \/\/ demande le nombre de pas de la roue ext\u00e9rieure\n    float steps_int = stepsint(dia_rot); \/\/ demande le nombre de pas de la roue int\u00e9rieure\n    float ratio_init = steps_ext\/abs(steps_int); \/\/ calcule le ratio entre les pas ext et les pas int\n    int step=0; \/\/ affecte 0 \u00e0 step qui comptera les pas ext\u00e9rieurs\n    float ratio_dyn=0; \/\/ affecte 0 \u00e0 ratio dyn qui permettra de g\u00e9rer les avances diff\u00e9rentielle entre roues\n    float test_ratio = ratio_init-1; \/\/ calcule test_ratio qui d\u00e9clenchera l'avance de la roue int\u00e9reur quand le ratio sera correct\n\n    while( step&lt;steps_ext) \/\/ lance la boucle tant que la  roue ext\u00e9rieure n'aura pas finit le nombre de pas \n    {        \n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurD&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait avancer la roue droite (ext)\n          }\n          delay(duree_delai);\n        }\n        \n        ratio_dyn=ratio_dyn+1; \/\/ incr\u00e9mente le ratio dynamique\n        step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n      \n        if (ratio_dyn>= test_ratio) \/\/ si le ratio est atteint moins un pas    \n          {  \n          for(int mask=0; mask&lt;4; mask++)\n            {\n            for(int pin=0; pin&lt;4; pin++)\n            {\n            digitalWrite(broches_MoteurD&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait avancer la roue droite (ext)          \n            \n            if (steps_int&lt;=0) \/\/ si la roue int\u00e9rieure doit reculer (diam\u00e8tre du cercle &lt;entraxe du robot)\n              {\n              digitalWrite(broches_MoteurG&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait reculer la roue gauche (int)  \n              }\n              else\n              {\n              digitalWrite(broches_MoteurG&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait avancer la roue droite (int) \n              }            \n            }\n            \n            delay(duree_delai);\n            \n            }     \n          step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n          ratio_dyn= ratio_dyn-test_ratio; \/\/ calcule le ratio dyn (conserve les d\u00e9cimales pour les incr\u00e9menter de nouveau)\n          } \n  \n      } \n\n      fin();\n    }\n\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ 1\/4 de cercle  en reculant sur la droite \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n  void arrieredroite (float dia_rot)   \/\/ trace un 1\/4 de cercle en reculant sur la droite  \n    {\n\n    float steps_ext = stepsext(dia_rot); \/\/ demande le nombre de pas de la roue ext\u00e9rieure\n    float steps_int = stepsint(dia_rot); \/\/ demande le nombre de pas de la roue int\u00e9rieure\n    float ratio_init = steps_ext\/abs(steps_int); \/\/ calcule le ratio entre les pas ext et les pas int\n    int step=0; \/\/ affecte 0 \u00e0 step qui comptera les pas ext\u00e9rieurs\n    float ratio_dyn=0; \/\/ affecte 0 \u00e0 ratio dyn qui permettra de g\u00e9rer les avances diff\u00e9rentielle entre roues\n    float test_ratio = ratio_init-1; \/\/ calcule test_ratio qui d\u00e9clenchera l'avance de la roue int\u00e9reur quand le ratio sera correct\n\n    while( step&lt;steps_ext) \/\/ lance la boucle tant que la  roue ext\u00e9rieure n'aura pas finit le nombre de pas \n    {        \n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurD&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait reculer la roue droite (ext)\n          }\n          delay(duree_delai);\n        }\n        \n        ratio_dyn=ratio_dyn+1; \/\/ incr\u00e9mente le ratio dynamique\n        step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n      \n        if (ratio_dyn>= test_ratio)  \/\/ si le ratio est atteint moins un pas  \n          {  \n          for(int mask=0; mask&lt;4; mask++)\n            {\n            for(int pin=0; pin&lt;4; pin++)\n            {\n            digitalWrite(broches_MoteurD&#91;pin], dextro&#91;mask]&#91;pin]);  \/\/ fait reculer la roue droite (ext)          \n            \n            if (steps_int&lt;=0) \/\/ si la roue int\u00e9rieure doit avancer (diam\u00e8tre du cercle &lt;entraxe du robot)\n              {\n              digitalWrite(broches_MoteurG&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait avancer la roue gauche (int) \n              }\n              else\n              {\n              digitalWrite(broches_MoteurG&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait reculer la roue gauche (int)  \n              }            \n            }\n            \n            delay(duree_delai);\n            \n            }     \n          step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n          ratio_dyn= ratio_dyn-test_ratio; \/\/ calcule le ratio dyn (conserve les d\u00e9cimales pour les incr\u00e9menter de nouveau)\n          } \n  \n      } \n\n      fin();\n    }\n\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ 1\/4 de cercle  en reculant sur la gauche \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n  void arrieregauche (float dia_rot)\n  {\n    {\n    float steps_ext = stepsext(dia_rot); \/\/ demande le nombre de pas de la roue ext\u00e9rieure\n    float steps_int = stepsint(dia_rot); \/\/ demande le nombre de pas de la roue int\u00e9rieure\n    float ratio_init = steps_ext\/abs(steps_int); \/\/ calcule le ratio entre les pas ext et les pas int\n    int step=0; \/\/ affecte 0 \u00e0 step qui comptera les pas ext\u00e9rieurs\n    float ratio_dyn=0; \/\/ affecte 0 \u00e0 ratio dyn qui permettra de g\u00e9rer les avances diff\u00e9rentielle entre roues\n    float test_ratio = ratio_init-1; \/\/ calcule test_ratio qui d\u00e9clenchera l'avance de la roue int\u00e9reur quand le ratio sera correct\n\n    while( step&lt;steps_ext) \/\/ lance la boucle tant que la  roue ext\u00e9rieure n'aura pas finit le nombre de pas \n    {        \n      for(int mask=0; mask&lt;4; mask++)\n        {\n        for(int pin=0; pin&lt;4; pin++)\n          {\n          digitalWrite(broches_MoteurG&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait reculer la roue gauche (ext)\n          }\n          delay(duree_delai);\n        }\n        \n        ratio_dyn=ratio_dyn+1; \/\/ incr\u00e9mente le ratio dynamique\n        step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n      \n        if (ratio_dyn>= test_ratio)  \/\/ si le ratio est atteint moins un pas  \n          {  \n          for(int mask=0; mask&lt;4; mask++)\n            {\n            for(int pin=0; pin&lt;4; pin++)\n            {\n            digitalWrite(broches_MoteurG&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait reculer la roue gauche (ext)            \n            \n            if (steps_int&lt;=0) \/\/ si la roue int\u00e9rieure doit reculer (diam\u00e8tre du cercle &lt;entraxe du robot)\n              {\n              digitalWrite(broches_MoteurD&#91;pin], levo&#91;mask]&#91;pin]); \/\/ fait avancer la roue droite (int) \n              }\n              else\n              {\n              digitalWrite(broches_MoteurD&#91;pin], dextro&#91;mask]&#91;pin]); \/\/ fait reculer la roue droite (int)  \n              }            \n            }\n            \n            delay(duree_delai);\n            \n            }     \n          step++; \/\/ incr\u00e9mente le nombre de pas ext r\u00e9alis\u00e9s\n          ratio_dyn= ratio_dyn-test_ratio; \/\/ calcule le ratio dyn (conserve les d\u00e9cimales pour les incr\u00e9menter de nouveau)\n          } \n  \n      } \n\n      fin();\n    }\n  }\n<\/code><\/pre>\n\n\n\n<p>Les quart de cercles \u00ab\u00a0reculer\u00a0\u00bb, \u00ab\u00a0tourner \u00e0 gauche\u00a0\u00bbsont programm\u00e9s de la m\u00eame fa\u00e7on, mais en inversant les roues externes et interne (tourne gauche) ou les sens de rotation (recule).<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">Les fonctions accessoires <\/h6>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les fonction sonores<\/li>\n<\/ul>\n\n\n\n<p>Comme la tortue est \u00e9quip\u00e9e d&rsquo;un module Haut-Parleur, j&rsquo;ai reproduis trois fonctions sonores pr\u00e9sents dans la tortue Jeulin. La premi\u00e8re est un bip de validation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Joue un bip \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid bip () \n{\n    tone(broche_speaker, 600, 250); \/\/ Bip\n    delay(300); \/\/ permet de s\u00e9parer les notes    \n    noTone(broche_speaker); \/\/ stoppe le son\n    speak = 1 ; \/\/ Met le flag boucle sonore \u00e0 1\n}\n<\/code><\/pre>\n\n\n\n<p>La seconde est un bip d&rsquo;erreur, reprenant le r\u00f4le de la fonction \u00ab\u00a0R\u00e2le\u00a0\u00bb. La fr\u00e9quence du Bip pas de 600Hz (bip) \u00e0 140Hz (bip grave).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n \/\/ Joue un bip grave \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid rale () \n{\n    tone(broche_speaker, 140, 800); \/\/ Bip grave\n    delay(1000); \/\/ permet de s\u00e9parer les notes    \n    noTone(broche_speaker); \/\/ stoppe le son\n    speak = 1 ; \/\/ Met le flag boucle sonore \u00e0 1\n}  <\/code><\/pre>\n\n\n\n<p>La derni\u00e8re est la m\u00e9lodie d\u00e9j\u00e0 \u00e9voqu\u00e9e plus haut. Le tableau <em>melody[<\/em>] indique les fr\u00e9quences des notes et le tableau <em>dur\u00e9e[<\/em>], leur dur\u00e9e. Il est ais\u00e9 de modifier la m\u00e9lodie ou d&rsquo;en ajouter une autre.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n \/\/ Joue une m\u00e9lodie \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid melodie () \n{\n  int melody&#91;] =   \n    { \n    349,349,349,392,440,392,349,440,392,392,349, \/\/ Au clair de la lune\n    };\n  int duree&#91;] = \n    {\n    200,200,200,200,500,500,200,200,200,200,200, \/\/ dur\u00e9e des notes\n    };\n  for (int thisNote = 0; thisNote &lt; 11; thisNote++) \n    {\n    tone(broche_speaker, melody&#91;thisNote], duree&#91;thisNote]); \/\/ Joue la note\n    delay(duree&#91;thisNote]+100); \/\/ permet de s\u00e9parer les notes    \n    noTone(broche_speaker); \/\/ stoppe le son\n    }\n    speak = 1 ; \/\/ Met le flag boucle sonore \u00e0 1\n}<\/code><\/pre>\n\n\n\n<p>Elles sont appel\u00e9es depuis le programme principal avec les commandes suivantes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/   Cartes roses speaker    \/\/\n         \/\/ Module HP Grove 107020001 \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case 'J':\n        melodie(); \/\/ J = joue une m\u00e9lodie\n        fin();\n        break;\n\n        case 'K':\n        bip(); \/\/ K = bip\n        fin();\n        break;\n\n        case 'P':\n        rale(); \/\/ P = rale\n        fin();\n        break;<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les fonctions lumineuses<\/li>\n<\/ul>\n\n\n\n<p>Le phare avant est \u00e9quip\u00e9 d&rsquo;une led RGB. Il est alors facile de modifier l&rsquo;aspect du phare en jouant sur les teintes RGB. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>           \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n          \/\/      Cartes roses phare led       \/\/\n         \/\/ Module \u00e0 LED RGB Grove 104020169  \/\/\n        \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n        case '!':\n        allume_bleu(); \/\/ ! = allume la led en bleu\n        break;    \n\n        case '\"':\n        allume_vert(); \/\/ \" = allume la led en vert\n        break;          \n\n        case '#':\n        allume_rouge(); \/\/ # = allume la led en rouge\n        break;\n\n        case '$':\n        allume_violet(); \/\/ $ = allume la led en violet\n        break;\n\n        case '%':\n        allume_turquoise(); \/\/ % = allume la led en turquoise\n        break;\n\n        case '&amp;':\n        allume_jaune(); \/\/ &amp; = allume la led en jaune\n        break;\n        \n        case '+':\n        allume_blanc(); \/\/ + = allume la led en blanc\n        break;\n\n        case '-':\n        eteins_led(); \/\/ - = allume la led en blanc\n        break;        \n <\/code><\/pre>\n\n\n\n<p>Le phare blanc s&rsquo;obtient avec :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void allume_blanc () \n  {\n  led_RGB.setBrightness(255); \/\/ luminosit\u00e9 max\n  led_RGB.begin(); \/\/d\u00e9marre l'allumage\n  led_RGB.setPixelColor(0, led_RGB.Color(255,255,255)); \/\/allume toutes les leds = blanc\n  led_RGB.show(); \/\/allume la led\n  fin();\n  }<\/code><\/pre>\n\n\n\n<p>Tandis que le bleu s&rsquo;obtient avec les param\u00e8tres suivants :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  led_RGB.setPixelColor(0, led_RGB.Color(0,0,255)); \/\/allume B = bleu<\/code><\/pre>\n\n\n\n<p>pour les couleurs retenues, les valeurs sont: <\/p>\n\n\n\n<figure class=\"wp-block-table aligncenter has-small-font-size\"><table><thead><tr><th class=\"has-text-align-center\" data-align=\"center\">Couleur<\/th><th class=\"has-text-align-center\" data-align=\"center\">Red<\/th><th class=\"has-text-align-center\" data-align=\"center\">Green<\/th><th class=\"has-text-align-center\" data-align=\"center\">Blue<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\">Blanc<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Bleu<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Vert<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Rouge<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Violet<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Turquoise<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><td class=\"has-text-align-center\" data-align=\"center\">255<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Jaune<\/td><td class=\"has-text-align-center\" data-align=\"center\">125<\/td><td class=\"has-text-align-center\" data-align=\"center\">125<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">&nbsp;\u00c9teins<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><td class=\"has-text-align-center\" data-align=\"center\">0<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\"><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-custom-couleur-1-color\">R\u00e9glages de la led RGB retenus dans le programme<\/mark><\/figcaption><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les fonctions de maintenance<\/li>\n<\/ul>\n\n\n\n<p>Ces fonctions sont programm\u00e9es pour faciliter le r\u00e9glage de la pr\u00e9cision de la tortue. Ainsi que je l&rsquo;ai d\u00e9j\u00e0 \u00e9voqu\u00e9, la pr\u00e9cision d&rsquo;un robot artisanal est relative, mais il est possible d&rsquo;op\u00e9rer quelques r\u00e9glage et \u00e9talonnage afin d&rsquo;avoir une tortue relativement pr\u00e9cise. Un billet sera d&rsquo;ailleurs prochainement consacr\u00e9 \u00e0 ce point sp\u00e9cifique prochainement. Il existe deux fonctions actuellement pour \u00e9talonner la tortue.<\/p>\n\n\n\n<p>La premi\u00e8re fonction est la fonction demi-tour, la tortue avance de 40 cm, fait demi-tour puis avance de nouveau de 40 cm. La mesure de la longueur permet de v\u00e9rifier l&rsquo;exactitude de la variable <em>float dia_roue<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>   \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n  \/\/ figure test 1\/2 tour \/\/\n \/\/ gestion des angles   \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n  void demi_tour()\n  {\n    stylo_B();\n    avance(400);\n    stylo_H();\n    tournegauche(180);\n    stylo_B();\n    avance(400);\n    stylo_H();\n    bip();\n    bip();\n  }<\/code><\/pre>\n\n\n\n<p>La seconde permet de v\u00e9rifier la valeur de l&rsquo;entraxe entre roues, <em>float entraxe<\/em>. Il s&rsquo;agit de dessiner une s\u00e9rie de 3 carr\u00e9s imbriqu\u00e9s. La rotation relative entre les trois carr\u00e9s doit \u00eatre minimis\u00e9e par le r\u00e9glage de la valeur de l&rsquo;entraxe.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>   \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n  \/\/ figure test carr\u00e9  \/\/\n \/\/ gestion des angles \/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n  void test_carre()\n  {\n    stylo_B();\n    for(int ncarres=0; ncarres&lt;3; ncarres++)\n    {\n    avance(100);\n    tournegauche(90);\n    avance(100);\n    tournegauche(90);\n    avance(100);\n    tournegauche(90);\n    avance(100);\n    tournegauche(90);\n\n    }\n    stylo_H();\n     \n    bip();\n    bip();\n  }<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">La fin de la transmission<\/h5>\n\n\n\n<p>La fin de la transmission d&rsquo;une op\u00e9ration est signal\u00e9e par l&rsquo;envoi d&rsquo;un caract\u00e8re arobase sur le port s\u00e9rie. Cette fonction sert \u00e0 informer la t\u00e9l\u00e9commande, par exemple, le lecteur de carte que le robot est disponible. Bien que le couple lecteur de carte &amp; robot puisse g\u00e9rer une succession de cartes seules sans soucis, Il est n\u00e9cessaire d&rsquo;obtenir la lecture de la commande suivante lorsqu&rsquo;on programme<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/***************************************************************************\n * gestion de la fin de transmission\n***************************************************************************\/\n\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n \/\/Fin transmission\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n  void fin () \n  {\n    BTmySerial.println ('@'); \/\/ envoie un arobace \u00e0 la fin de la transmission\n    if (speak == 0) \/\/ v\u00e9rifie si on ne sort pas d'une boucle sonore\n      {\n      bip ();\n      }\n    speak = 0;\n  }<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">C&rsquo;est la fin<\/h5>\n\n\n\n<p>Les principales fonctions impl\u00e9ment\u00e9es dans la tortue sont d\u00e9velopp\u00e9es ici. Vous avez la possibilit\u00e9 de les faire \u00e9voluer ou de les am\u00e9liorer. N&rsquo;oubliez pas la tortue est open source, donc pensez \u00e0 partager votre travail!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Avant de commencer, le lecteur me pardonnera, je l&rsquo;esp\u00e8re, ce titre empreint de facilit\u00e9. La question r\u00e9elle de ce billet, c&rsquo;est comment commander la tortue de sol que l&rsquo;on vient d&rsquo;imprimer (voir ici), puis d&rsquo;assembler (voir ici). Ce billet sera, par ailleurs, exceptionnellement long puisqu&rsquo;il s&rsquo;agit davantage de documenter le code que d&rsquo;un travail de [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":22,"footnotes":""},"categories":[1],"tags":[],"post_folder":[],"class_list":["post-1214","post","type-post","status-publish","format-standard","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/albooms.fr\/index.php?rest_route=\/wp\/v2\/posts\/1214","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/albooms.fr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/albooms.fr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/albooms.fr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/albooms.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1214"}],"version-history":[{"count":9,"href":"https:\/\/albooms.fr\/index.php?rest_route=\/wp\/v2\/posts\/1214\/revisions"}],"predecessor-version":[{"id":1345,"href":"https:\/\/albooms.fr\/index.php?rest_route=\/wp\/v2\/posts\/1214\/revisions\/1345"}],"wp:attachment":[{"href":"https:\/\/albooms.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/albooms.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1214"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/albooms.fr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1214"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/albooms.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fpost_folder&post=1214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}