Page de présentation

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Sommaire :

 

-         Introduction

o       Pourquoi un TPE sur la robotique

o       Quel robot construire

o       Les fonctions désirées sur notre robot

 

-         Partie I : La mécanique

o       Assemblage

o       Fonctionnement

o       Composants

 

-         Partie II : L’électronique

o       Le cerveau du robot : Le PIC 

§         Qu’est-ce qu’un PIC

§         Fonctionnement d’un PIC

§         Carte de programmation du PIC

§         Carte du PIC sur le Robot

o       Les jambes du robot : les servomoteurs

§         Qu’est-ce qu’un servomoteur

§         Fonctionnement d’un servomoteur

§         Modification des servomoteurs

o       Les yeux du robot : Le capteur IR

§         Principe et fonctionnement du capteur IR

o       Les autre cartes électroniques du robot

§         La carte capteur IR

§         La carte servomoteur

§         L’alimentation

§         Les détecteurs de choc

o       Le Circuit électronique global du robot

 

-         Partie III : L’informatique

o       Pourquoi utiliser l’informatique

o       Le langage de programmation du PIC : Le langage C

§         Bases simples du C  (nécessaires pour comprendre le code source)

§        

o       Le programme du robot

§         La partie « interruptions , timers »

§         La partie « Déplacement » : programme principal

§         La partie « Détection infrarouge » 

 

-         Conclusion, résultat, projets futurs, etc

 

 

 

 

 

 

 

-        Introduction

 

 

 

 

o      Pourquoi un TPE sur la robotique ?

 

 

 

            En lisant les listes de sujets de TPE que l’on nous proposait pour avoir des idées, nous nous sommes plutôt dirigés vers des sujets faisant appel à la physique/chimie et aux maths. Ces sujets nous intriguaient plus que ceux de SVT, pas parce que nous n’aimons pas la svt au contraire mais plus par curiosité. Ensuite le thème de l’intelligence artificielle nous a séduit mais il fallait trouver quelque chose de plus précis. Nous avons pensé à l’intelligence artificielle dans les jeux vidéo, mais un TPE sur le sujet impliquait pour être intéressant de commencer à programmer des petits jeux vidéos mais à trois (pas forcément passionnés par la programmation) ce n’était pas le sujet idéal. Ensuite en discutant avec notre prof de maths, il nous a parlé de robots agricoles cueilleurs de pommes. C’est de la qu’est partie l’idée de faire un TPE sur la robotique.

 

Mais nous avions envie de faire quelque chose de concret, concevoir et assembler un robot serait l’idéal. Mais à première vue, nous n’étions pas sur d’en être capables par nous mêmes. Après plusieurs recherches sur Internet, sur des sites de passionnés, des forum de sciences, etc. Nous avons été rassurés et la difficulté même si elle était la n’était pas insurmontable. Encouragés par nos professeurs, nous avons décidé de monter un petit robot assez simple mais nécessitant quand même un certain nombre de connaissances.

 

 

 

 

o      Quel robot construire ?

 

 

Dans la vie courante, il existe des milliers de machines appelées « robots ». Il existe des robots qui vont sur mars, des robots sous-marins d’exploration, des robots dans les usines …

Dans notre cas, nous voulons faire quelque chose de plus simple, pour apprendre le B.Aba de la robotique. Et le mieux pour commencer est de construire un petit robot roulant. Il s’agit donc d’une base avec des roues animées par des moteurs, qui peut rouler. Mais le principe d’un robot est d’avoir une certaine « intelligence » qui est bien sur cachée derrière tout un mécanisme utilisant des composants électroniques. Sinon nous aurions fait une voiture télécommandée, ce qui serait beaucoup plus simple.

 

 

           

 

 

 

 

 

o       Les fonctions désirées sur notre robot

 

 

            Comme nous l’avons évoqué ci-dessus, la fonction primaire de notre rebot sera de rouler. Ensuite, en accord avec notre problématique, il est intéressant de lui faire éviter des obstacles. Pour cela, nous avons découvert qu’il existe plusieurs méthodes. La plus simple est de mettre des pare-chocs à l’avant du robot afin qu’il s’arrête dès qu’il rentre en contact avec un objet. Une solution plus sophistiquée est de lui faire identifier les obstacles à une certaine distance, pour les éviter sans avoir à reculer après un choc. En cherchant , nous avons trouvé plusieurs techniques principales pour détecter les obstacles : un émetteur récepteur à infrarouges ou ultrasons par exemple, ou une caméra miniature. Il n’est pas dur de faire un choix car la dernière méthode bien qu’étant la plus précise est assez chère et nécessite du matériel plus pointu pour être utilisée. De plus la précision d’une caméra est surdimensionnée pour une simple détection d’obstacles. Nous avons donc choisi la méthode IR (ou infrarouge) car les composants sont peu onéreux et c’est la méthode la plus répandue. Nous avons également choisi d’utiliser des pare-chocs car les obstacles de couleur noire par exemple ne réfléchissent pas les infrarouges.

.

            Ensuite il es possible d’ajouter plusieurs fonctionnalités à un robot, comme d’être guidé par une télécommande, un ordinateur, d’apprendre un parcours prédéfini, de savoir se situer dans l’espace à l’aide balises… Les fonctionnalités sont quasi infinies mais nous ne pouvons bien sur pas toutes les intégrer par faute de temps et de moyens …

           

            Notre projet de réaliser un robot détecteur d’obstacles est déjà assez ambitieux car il doit être réalisé en moins de 3 mois sans compter le temps nécessaire pour assembler les centaines de petits composants.

.

.

.

.

En robotique,  peut presque tout faire, à condition d’avoir le matériel nécessaire,  les connaissances qui vont avec et surtout beaucoup de temps libre.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-        Partie I : La mécanique

 

 

 

 

o       Composants

 

 

Matériel utilisé : Plaque d’aluminium découpée sur mesure

Pour le chassi                         

                           Ventilateur d’ordinateur 80mm

                                    

   2x servomoteurs Futaba S3003

                                   

    Roues Lego

                                    

Batterie

      

Equerres en métal

                          

Vis                                                            

 

 

 

o       Assemblage

 

 

            Tout d’abord il a fallu choisir avec quel matériau usiner la plaque principale qui sera le châssis du robot. La solution la plus simple est de choisir une plaque en bois car c’est le matériau le plus facile à découper. Mais nous voulions quelque chose de plus solide et de plus esthétique. Nous avons donc choisi d’utiliser de l’aluminium car c’est un métal léger et résistant. On aurait aussi pu choisir une plaque en plexiglas mais elle le plexiglas est moins solide et se raye facilement. Alexandre a réussi à avoir une plaque découpée sur mesure selon nos plans, ce qui nous a facilité la tache. 

Ensuite elle a été coupée en deux afin de permettre la mise en place d’un étage. Nous avons choisi de monter un deuxième étage pour réduire la longueur du robot et permettre d’avoir plus de surface disponible pour les circuits et autres composants. Cet étage a été monté à l’aide un ventilateur d’ordinateur que nous avions sous la main. Ce ventilateur évite le soucis de fabriquer des piliers sur mesure. De plus il donne une certaine originalité au robot. Bien sûr il n’a aucune fonctionnalité autre que le maintien de l’étage, le refroidissement est inutile dans notre robot. Pour que cela tienne solidement en place, la plaque de la base du robot a été percée aux endroits adéquats et, par l’intermédiaire d’équerres en métal le ventilateur a été visé aux deux plaques (voir schéma et photos).

L’étage a ainsi été élevé permettant un gain de place maximum, tout en gardant une fiabilité quand à la résistance et au maintien de cet étage ainsi qu’une esthétique notable.

 

 

 

 

 

            On a ensuite fixé les servomoteurs (préalablement modifiés) sur les cotés de la base grâce au même principe de perçage, d’équerre et de vissage. Après cela il a fallu trouver une astuce pour fixer les roues Lego n’étant pas du tout conçues pour être fixées sur un servomoteur. Le servomoteur est livré avec plusieurs disques que l’on peut visser à l’axe de sortie. Par chance l’un d’eux correspondant parfaitement au rayon de la roue LEGO. Nous avons donc percé la roue LEGO et collé le disque à la roue avec de la colle epoxy.

 

 

           

 

Cette disposition permet ensuite d’adapter la batterie car la place centrale reste libre. La batterie ou Accu est la pièce la plus volumineuse et lourde en ce qui concerne le matériel indispensable au robot. Son poids n’est pas forcément un point négatif  car il permet de stabiliser la base du robot en le plaquant au sol. L’Accu est fixé à la plaque en Alu à l’aide de pâte à modeler.

 

 

 

o       Fonctionnement

 

Le fonctionnement de la partie mécanique est simple. Les deux roues sont les roues motrices de l’appareil et la roue libre est en fait un petit patin qui frotte sur le sol. Cette disposition suffit pour effectuer tous les déplacements possibles avec une bonne vitesse.

 

 

 

 

 

 

 

 

 

 

 

 

-        Partie II : L’électronique

 

 

 

 

 

o       Le cerveau du robot : Le PIC

 

 

 

§         Qu’est-ce qu’un PIC ?

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Un PIC est un microcontrôleur fabriqué par la société américaine Microchip, c’est un circuit intégré que l’on utilise dans de nombreux montages électroniques pour contrôler d’autres composants, d’où le nom de micro-contrôleur. Les autres composants du circuit sont relié au PIC par l’intermédiaire de ses entrées et sorties sous forme de petite pattes (voir photo).

Pour diriger les entrées et les sorties, le PIC comprend dans sa partie principale de la mémoire ( le plus fréquemment une mémoire vive de type RAM et une mémoire de stockage type Flash ) et une unité de calcul ( petit processeur de quelques Mhz ), il peut aussi contenir un timer dont nous verrons l’utilité dans la partie programmation.

Il faut savoir que la firme Microchip ( www.microchip.com) commercialise des centaines de modèles de PIC et autres circuit intégrés. Les PIC, qui sont les plus célèbres existent en différents modèles plus ou moins grands, puissants et avec plus ou moins d’entrées/sorties et de mémoire. Nous avons choisi un modèle intermédiaire qui présente un bon rapport capacités/prix, c’est le modèle 18F252. Son prix est d’environ 16€ en France mais un ami nous en a prêté un.

Voici ses caractéristiques : (ressemblant à celles des premiers ordinateurs) 

 

Fréquence : 40Mhz

RAM : 1.5ko

Mémoire flash : 32ko

E/S : 23

 

(photo du notre)

 

 

 

§         Fonctionnement d’un PIC ?

 

 

Un PIC est alimenté par un courant de 5V. Ses sorties ont pour fonction de laisser passer où non le courant afin de fournir un courant sortant (5V) ou rien ou composants reliés à celles-ci. Les entrées sont des capteurs sensibles au courant entrant. Si une entrée reçoit un courant de 5V, elle est activée et dans les autres cas elle ne l’est pas.

A partir de ce fonctionnement simple, les possibilités sont très nombreuses car chaque entrée/sortie est contrôlée par le programme contenu dans la mémoire flash. Et comme vous allez le voir dans la partie informatique, les possibilités de programmation sont très nombreuses.

Pour avoir plus d’information sur le PIC que l’on choisi, il est nécessaire de consulter sa datasheet, c’est un document PDF de 330 pages. (lien vers celles des PIC 18Fxx2 lol ). On peut en tirer les caractéristiques du PIC et surtout le schéma des entrées/sorties :

 

           

 

 

 

            Nous allons voir dans la 3ème partie que l’on peut assigner à chaque sortie une valeur d’origine de 1 ou 0 ce qui correspond à une sortie de courant ou à rien. Le principe est le même pour les entrées, elles renvoient une valeur de 0 ou 1 selon la tension qu’elle reçoivent.

 

 

 

 

 

 

 

 

§        Carte de programmation du PIC

 

 


 

 

 

Pour transférer le programme dans la mémoire du PIC, il faut une liaison entre l’ordinateur et le PIC, cette liaison est un programmateur. Nous avons choisi d’assembler nous-même le notre pour une question de coût et aussi pour se réhabituer à bien souder (car depuis le collège certains n’ont pas touché un fer à souder).

Nous avons donc cherché sur internet, les plans d’un programmateur (typon du circuit imprimé : 1ere photo, implantation des composants : 2eme photo et liste des composants) et avons nous même assembler le tout. Le programmateur fonctionne heureusement à merveille.

Voici la liste des composants nécessaires :

 

Résistances de 10 K, 1.5 K, condensateurs de 100 UF 40 V chimique et  22 UF 16 V tantale
diodes 1N4148, Zener 5.1 V et  Zener 8.2 V
transistors BC 547B
Barrettes de contacts tulipe: 4 x 20 + 2 x 5 broches
Prise DB25 femelle pour circuit imprimé

 

*

 

 

 

 

 

 

 

 

§         Carte du PIC sur le Robot

 

La carte PIC a pour fonction de recevoir le PIC sur le robot et de connecter les différents éléments du robot aux entrées/sorties du PIC. Cette Carte est formée d’un circuit imprimé créé par ordinateur avec le logiciel eagle dont voici le circuit électrique fait avec :

 

 

Et ensuite on le transforme en typon de circuit imprimé (plan du circuit imprimé à graver) :

 

Et voilà ce que ça donne en vrai (les circuit imprimé sont fabriqués à partir du typon que nous fournissons à etronics qui nous les envoie par la poste) :

 

           

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Et la carte prête à être montée sur le robot avec tous les composants soudés :

 

 

 

            On voit bien les pistes qui sont connectées au pattes du PIC, il y a aussi le quartz de 40mhz nécessaire au timer du PIC, on retrouve aussi un interrupteur on/off, une prise DB9 pour y connecter un câble série pour modifier le programme (expliqué dans la partie 3). Il y a aussi une led de vérification, et des condenseurs pour fournir un courant « stable ». 

 

 

 

 

 

 

 

o       Les jambes du robot : les servomoteurs

 

 

 

§         Qu’est-ce qu’un servomoteur ?

 

Le servomoteur est l’élément qui fait tourner les roues du robot, ce n’est pas seulement un moteur car on peut lui demander de tourner dans un sens ou dans l’autre avec des asservissements différents.(définition d’un asservissement).

 

Un servomoteur se compose:

d'un moteur à courant continu

d'un système réducteur de vitesse à roues dentées

d'un potentiomètre

d'un circuit électronique

 

Les servomoteurs sont beaucoup utilisés en radio-modélisme, par exemple pour sortir le train d'atterrissage d'un avion.

 

 

§         Fonctionnement d’un servomoteur

 

 

Un servomoteur se pilote par l'intermédiaire d'un câble à trois fils. Ce câble permet à la fois de l'alimenter et de lui transmettre des consignes de position par le fil de signal. Le signal est une impulsion électrique envoyée par le PIC au servomoteur.

Le servomoteur réagit en fonction de la durée de l’impulsion qu’il reçoit. Selon cette impulsion l’axe tournera à gauche, à droite ou s’immobilisera.

La durée de l'impulsion peut être comprise (sur notre modèle de servomoteur) entre environ XX mS (le robot reculera) et XXmS(le robot avancera), XXmS correspond au centre(le robot sera immobile).

La fréquence de l’impulsion n’est pas importante, il faut juste que celle-cie soit répétée au maximum toutes les 20mS environ.

 

Exemple :

 

 

 

§         Modification des servomoteurs

 

 

Les servomoteurs étant conçus pour le radio-modélisme, leur axe de sortie n’effectue qu’une rotation d’environ 150°. Pour le faire tourner à 360° il faut ouvrir le servo moteur et couper délicatement les deux butées qui l’empêche de faire une rotation complète.

Voilà comment on fait en pratique :

 

 

Et à la fin, la rotation se fait parfaitement !

 

 

o       Les yeux du robot : Le capteur IR

 

 

 

§         Principe et fonctionnement du capteur IR

 

 

Le capteur IR est composé de 3 petites cartes : 2 cartes émettrices (droite et gauche) et 1 carte réceptrice. Les cartes émettrices sont constituées simplement d’une LED IR reliée à une sortie du PIC, et la carte réceptrice est un récepteur IR relié à une entrée du PIC.

 

Pour détecter les obstacles, on commande à chaque carte émettrice d’envoyer un signal spécifique. Lorsque le robot arrive devant un obstacle, un des signaux est renvoyé vers le récepteur, et indique donc la présence d’un obstacle. Comme les 2 signaux sont différents, on peut différencier un obstacle situé à droite d’un obstacle situé à gauche. Selon l’obstacle, le robot tournera du coté opposé et l’évitera de manière « intelligente ».

L’inconvénient d’un capteur infrarouge, c’est que les IR ne se réfléchissent pas sur les objets noirs ou très foncés. Ils sont donc invisibles pour le robot. On comprend donc l’utilité de rajouter des pare-chocs.

 

 

 

 

 

o       Les autre cartes électroniques du robot

 

 

§         La carte pares-chocs

 

La carte pare-choc sert à relier les 2 interrupteurs de l’avant du robot servant de pares-chocs droit et gauche. Le principe du pare-choc est expliqué sur le schéma ci-dessous :

 

Le PIC reçoit donc sur une de ses entrées un signal, quand le robot entre en contact avec un objet.

 

Voici donc la carte permettant de relier l’alimentation aux deux interrupteurs et ensuite aux entrées du PIC :

 

 

§         La carte servomoteur

 

 

La carte servomoteurs est aussi une petite carte avec comme support un bout de plaque pastillée. Elle sert à relier l’alimentation aux deux servos et les fils de signal aux sorties du PIC. De plus l’alimentation est séparées en 2 canaux indépendants et protégés par des octocoupleurs. Ces petits composants sont des circuits intégrés qui incluant une led et un capteur photorésistif. La carte comprend aussi un gros condensateur et des résistances de sécurité, ainsi que d’un interrupteur et une led marche/arrêt.

 

 

 

 

 

Voilà le schéma électrique :

 

 

 

Et la carte une fois montée :

 

 

 

 

 

 

 

 

 

§         L’alimentation

 

L’alimentation du robot se fait à l’aide d’une batterie de 7.2 Volts Ni-Cd. Le PIC étant alimenté en 5V, il faut utiliser un régulateur de tension afin d’obtenir du 5V pour toute la carte PIC. Les servos sont également alimenté en 5V donc toute l’alimentation se fait en 5V sur le robot.

Cette partie de la carte PIC sert à alimenter les autres cartes, ce sont plusieurs prises males reliées aux sorties du régulateur.

 

 

 

o       Le Circuit électronique global du robot

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-        Partie III : L’informatique

 

 

 

o       Pourquoi utiliser l’informatique ?

 

 

Il est simplement nécessaire d’utiliser l’informatique pour programmer le PIC. On utilise pour rédiger le programme, un logiciel fourni par Microchip : MPLAB IDE. Le programme sera rédigé en C, un langage de programmation très utilisé en informatique.

 

 

o       Le langage de programmation du PIC : Le langage C

 

 

§         Bases simples du C  (nécessaires pour comprendre le code source)

 

Il faut savoir qu’il n’est pas nécessaire d’apprendre le langage C de manière approfondie pour programmer un PIC. Pour comprendre quelques parties du code source que nous avons transférer dans le PIC, il faut comprendre quelques noms de fonctions comme : main() ; printf() ; void etc. et les mots clés comme « if, else, for, while, etc »

 

 

§        

 

 

o       Le programme final du robot :

 

 

 

//*************************************

// IRBOT

//

// Auteur : YANISSE Daniel

//*************************************

 

#include <18F252.h>                        // Inclusion du Header correspondant au µC utilisé

#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP  // Paramétrage des fusibles du microcontrôleur

#use delay(clock=20000000)

#use rs232(baud=115200, xmit=PIN_C6,rcv=PIN_C7)

 

//**********************

// Paramètres

//**********************

 

//**********************

// Defines

//**********************

#define DEBUT_TIMER0 65284    // (65534-65284)/(20000000/4) = 50 µs

#define SERVO_G      PIN_B3

#define SERVO_D      PIN_B2

#define SWITCH_G     PIN_C2

#define SWITCH_D     PIN_C3

#define LED_GAUCHE   PIN_C1

#define LED_DROITE   PIN_C0

#define CAPTEUR_IR   PIN_A0

 

//**********************

// Variables globales

//**********************

int nbtimers_droite_commande = 0;

int nbtimers_gauche_commande = 0;

int moteur_droit_actif = 0;

int moteur_gauche_actif = 0;

long nbtimers_effectue = 400;

int etalon = 180;

 

//**********************

// Fonctions

//**********************

void moteur_droit_avancer()  { nbtimers_droite_commande = 16; moteur_droit_actif  = 1; }

void moteur_droit_reculer()  { nbtimers_droite_commande =  6; moteur_droit_actif  = 1; }

void moteur_droit_arreter()  { nbtimers_droite_commande = 11; moteur_droit_actif  = 0; }

void moteur_gauche_avancer() { nbtimers_gauche_commande =  6; moteur_gauche_actif = 1; }

void moteur_gauche_reculer() { nbtimers_gauche_commande = 16; moteur_gauche_actif = 1; }

void moteur_gauche_arreter() { nbtimers_gauche_commande = 11; moteur_gauche_actif = 0; }

 

void moteurs_pause()

                {

                               moteur_droit_arreter();

                               moteur_gauche_arreter();

                               delay_ms(200);

                }

 

int1 ir_droit()

                {

                               int nb, nb2, i;

                               nb = 0;

                               for (i = 0; i < 250; i++)

                                               {

                                                               output_high(LED_DROITE);

                                                               delay_us(250);

                                                               if (input(CAPTEUR_IR))

                                                                              {

                                                                                              output_low(LED_DROITE);

                                                                                              nb++;

                                                                                              for(nb2 = 0; (input(CAPTEUR_IR) && nb2 < 10); nb2++) delay_us(100);

                                                                              }

                                                               output_low(LED_DROITE);

                                                               delay_us(250);

                                               }

                               printf("droite : %u\n\r", nb);

                               if (nb > etalon) return 1;

                               else return 0;

                }

 

int1 ir_gauche()

                {

                               int nb, nb2, i;

                               nb = 0;

                               for (i = 0; i < 250; i++)

                                               {

                                                               output_high(LED_GAUCHE);

                                                               delay_us(250);

                                                               if (input(CAPTEUR_IR))

                                                                              {

                                                                                              output_low(LED_GAUCHE);

                                                                                              nb++;

                                                                                              for(nb2 = 0; (input(CAPTEUR_IR) && nb2 < 10); nb2++) delay_us(100);

                                                                              }

                                                               output_low(LED_GAUCHE);

                                                               delay_us(250);

                                               }

                               printf("gauche : %u\n\r", nb);

                               if (nb > etalon) return 1;

                               else return 0;

                }

 

//**********************

// Timers & Interruptions

//**********************

#INT_TIMER0

void main_pwm() // toutes les 50µs

                {

                               if (nbtimers_effectue >= 400) // 400*50µs = 20ms

                                               {

                                                               nbtimers_effectue = 0;

                                                               if (moteur_droit_actif  == 1) output_high(SERVO_D);

                                                               if (moteur_gauche_actif == 1) output_high(SERVO_G);

                                               }

                               else

                                               {

                                                               if (moteur_droit_actif  == 1 && nbtimers_effectue >= nbtimers_droite_commande) output_low(SERVO_D);

                                                               if (moteur_gauche_actif == 1 && nbtimers_effectue >= nbtimers_gauche_commande) output_low(SERVO_G);

                                               }

                               nbtimers_effectue++;

                                set_timer0(DEBUT_TIMER0);

                }

 

//**********************

// Programme principal

//**********************

 

void main ()

                {

                               int nb, nb2, i;

 

                               set_timer0(DEBUT_TIMER0);

                               setup_timer_0(RTCC_INTERNAL);

                               enable_interrupts(INT_TIMER0);

                               enable_interrupts(GLOBAL);

 

                               printf("Demarrage\n\r");

                               delay_ms(200);

 

                               printf("Etalonnage\n\r");

                               delay_ms(5000);

 

                               nb = 0;

                               for (i = 0; i < 250; i++)

                                               {

                                                               output_high(LED_DROITE);

                                                               delay_us(250);

                                                               if (input(CAPTEUR_IR))

                                                                              {

                                                                                              output_low(LED_DROITE);

                                                                                              nb++;

                                                                                              for(nb2 = 0; (input(CAPTEUR_IR) && nb2 < 10); nb2++) delay_us(100);

                                                                              }

                                                               output_low(LED_DROITE);

                                                               delay_us(250);

                                               }

                               etalon = nb;

printf("etalon 1 : %u\n\r", etalon);

                               delay_ms(5000);

 

                               nb = 0;

                               for (i = 0; i < 250; i++)

                                               {

                                                               output_high(LED_DROITE);

                                                               delay_us(250);

                                                               if (input(CAPTEUR_IR))

                                                                              {

                                                                                              output_low(LED_DROITE);

                                                                                              nb++;

                                                                                              for(nb2 = 0; (input(CAPTEUR_IR) && nb2 < 10); nb2++) delay_us(100);

                                                                              }

                                                               output_low(LED_DROITE);

                                                               delay_us(250);

                                               }

printf("etalon 2 : %u\n\r", nb);

 

                               etalon = etalon/2 + nb/2;

printf("etalon : %u\n\r", etalon);

 

 

                               while(TRUE)

                                               {

                                                               if(!input(SWITCH_G)) // obstacle détecté à gauche

                                                                              {

                                                                                              moteurs_pause();

                                                                                              moteur_droit_reculer();

                                                                                              moteur_gauche_reculer();

                                                                                              delay_ms(1000);

                                                                                              moteurs_pause();

                                                                                              moteur_droit_reculer();

                                                                                              moteur_gauche_avancer();

                                                                                              delay_ms(500);

                                                                                              moteurs_pause();

                                                                                              moteur_droit_avancer();

                                                                                              moteur_gauche_avancer();

                                                                              }

                                                               else if (!input(SWITCH_D)) // idem à droite

                                                                              {

                                                                                              moteurs_pause();

                                                                                              moteur_droit_reculer();

                                                                                              moteur_gauche_reculer();

                                                                                              delay_ms(1000);

                                                                                              moteurs_pause();

                                                                                              moteur_droit_avancer();

                                                                                              moteur_gauche_reculer();

                                                                                              delay_ms(500);

                                                                                              moteurs_pause();

                                                                                              moteur_droit_avancer();

                                                                                              moteur_gauche_avancer();

                                                                              }

                                                               else if (ir_droit())

                                                                              {

                                                                                              moteur_droit_avancer();

                                                                                              moteur_gauche_arreter();

                                                                                              delay_ms(50);

                                                                              }

                                                               else if (ir_gauche())

                                                                              {

                                                                                              moteur_gauche_avancer();

                                                                                              moteur_droit_arreter();

                                                                                              delay_ms(50);

                                                                              }

                                                               else

                                                                              {

                                                                                              moteur_droit_avancer();

                                                                                              moteur_gauche_avancer();

                                                                              }

                                                               delay_ms(50);

                                                               /*moteur_droit_actif = 1;

                                                               for (nbtimers_droite_commande = 5; nbtimers_droite_commande <= 80; nbtimers_droite_commande++)

                                                                              {

                                                                                              printf("%u\n\r", nbtimers_droite_commande);

                                                                                              delay_ms(200);

                                                                              }*/

                                               }

                }

 

A la première approche, un programme peut paraître rébarbatif car il est long et l’on ne comprend pas la syntaxe. Nous ne pouvons pas tout détailler, mais nous allons juste indiquer à quoi correspondent les parties importantes du programme.

 

 

§         La déclaration des entrées/sorties, variables globales et des fonctions.

 

//**********************

// Defines

//**********************

#define DEBUT_TIMER0 65284    // (65534-65284)/(20000000/4) = 50 µs

#define SERVO_G      PIN_B3

#define SERVO_D      PIN_B2

#define SWITCH_G     PIN_C2

#define SWITCH_D     PIN_C3

#define LED_GAUCHE   PIN_C1

#define LED_DROITE   PIN_C0

#define CAPTEUR_IR   PIN_A0

 

Cette partie sert à donner un nom plus explicite aux entrées et sorties utilisées : exemple : on branche le servo gauche sur le pin B3, on écri donc :  #define SERVO_G      PIN_B3

 

 

//**********************

// Variables globales

//**********************

int nbtimers_droite_commande = 0;

int nbtimers_gauche_commande = 0;

int moteur_droit_actif = 0;

int moteur_gauche_actif = 0;

long nbtimers_effectue = 400;

int etalon = 180;

 

Ici on défini des variables qui vont être utilisée dans tout le programme grâce aux fonctions ci-dessous. Par exemple int nbtimers_droite_commande = 0;  signifie que l’on défini une variable entière, valant 0 par défaut, elle correspond au nombre d’impulsions envoyées au servo droit.

 

 

 

//**********************

// Fonctions

//**********************

void moteur_droit_avancer()  { nbtimers_droite_commande = 16; moteur_droit_actif  = 1; }

void moteur_droit_reculer()  { nbtimers_droite_commande =  6; moteur_droit_actif  = 1; }

void moteur_droit_arreter()  { nbtimers_droite_commande = 11; moteur_droit_actif  = 0; }

void moteur_gauche_avancer() { nbtimers_gauche_commande =  6; moteur_gauche_actif = 1; }

void moteur_gauche_reculer() { nbtimers_gauche_commande = 16; moteur_gauche_actif = 1; }

void moteur_gauche_arreter() { nbtimers_gauche_commande = 11; moteur_gauche_actif = 0; }

 

void moteurs_pause()

                {

                               moteur_droit_arreter();

                               moteur_gauche_arreter();

                               delay_ms(200);

                }

 

Cette parties sert à déclarer les fonctions les plus importantes, servant à contrôler les servos.

void moteur_droit_avancer()  { nbtimers_droite_commande = 16; moteur_droit_actif  = 1; }  Cette ligne signifie que l’on déclare une fonction ( void() qui ne revoit pas de valeur), qui s’appelle moteur_droit_avancer, et qui correspond à l’envoi d’une impulsion toutes les 16ms.

 

 

§         La partie « interruptions , timers »

 

//**********************

// Timers & Interruptions

//**********************

#INT_TIMER0

void main_pwm() // toutes les 50µs

                {

                               if (nbtimers_effectue >= 400) // 400*50µs = 20ms

                                               {

                                                               nbtimers_effectue = 0;

                                                               if (moteur_droit_actif  == 1) output_high(SERVO_D);

                                                               if (moteur_gauche_actif == 1) output_high(SERVO_G);

                                               }

                               else

                                               {

                                                               if (moteur_droit_actif  == 1 && nbtimers_effectue >= nbtimers_droite_commande) output_low(SERVO_D);

                                                               if (moteur_gauche_actif == 1 && nbtimers_effectue >= nbtimers_gauche_commande) output_low(SERVO_G);

                                               }

                               nbtimers_effectue++;

                               set_timer0(DEBUT_TIMER0);

                }

 

Cette partie du programme tire partie du timer, étant un composant intégré au PIC comme on l’a dit plus haut. Le timer sert à donner une unité de temps à l’aide du quartz (comme une montre). Ici on définit des interruptions, qui sont des pauses et des remises à zéro. On les utilise pour envoyé l’impulsion à une fréquence donnée, ici : 20ms.

 

 

 

§         La partie « Déplacement » : programme principal

 

 

 

 

if(!input(SWITCH_G)) // obstacle détecté à gauche

{

                               moteurs_pause();

                               moteur_droit_reculer();

                               moteur_gauche_reculer();

                               delay_ms(1000);

                               moteurs_pause();

                               moteur_droit_reculer();

                               moteur_gauche_avancer();

                               delay_ms(500);

                               moteurs_pause();

                               moteur_droit_avancer();

                               moteur_gauche_avancer();

                }

else if (!input(SWITCH_D)) // idem à droite

                {

                               moteurs_pause();

                               moteur_droit_reculer();

                               moteur_gauche_reculer();

                               delay_ms(1000);

                               moteurs_pause();

                               moteur_droit_avancer();

                               moteur_gauche_reculer();

                               delay_ms(500);

                               moteurs_pause();

                               moteur_droit_avancer();

                               moteur_gauche_avancer();

                }

else if (ir_droit())  // si obstacle détecté par IR à droite

                {

                               moteur_droit_avancer();

                               moteur_gauche_arreter();

                               delay_ms(50);

                }

else if (ir_gauche())  // idem à gauche

                {

                               moteur_gauche_avancer();

                               moteur_droit_arreter();

                               delay_ms(50);

                }

else

                {

                               moteur_droit_avancer();

                               moteur_gauche_avancer();

                }

 

 

Cette partie est assez facile à comprendre, il suffit de comprendre les mot clés if (si) et else (sinon) et else if (ou si).

 

Par exemple :  Le bloc suivant la ligne  if(!input(SWITCH_G)) // obstacle détecté à gauche sert à donner les ordres à suivre si un obstacle est détecté par le pare choc gauche (switch_g).

La fonction delay_ms() sert à préciser sur quelle durée on éxecute la fonction précédente : delay_ms(1000) veut dire 1sec.

 

 

 

§         La partie « Détection infrarouge » 

 

Voici la déclaration de la fonction correspondant à la détection d’un obstacle par IR à droite.

 

int1 ir_droit()

                {

                               int nb, nb2, i;

                               nb = 0;

                               for (i = 0; i < 250; i++)

                                               {

                                                               output_high(LED_DROITE);

                                                               delay_us(250);

                                                               if (input(CAPTEUR_IR))

                                                                              {

                                                                                              output_low(LED_DROITE);

                                                                                              nb++;

                                                                                              for(nb2 = 0; (input(CAPTEUR_IR) && nb2 < 10); nb2++) delay_us(100);

                                                                              }

                                                               output_low(LED_DROITE);

                                                               delay_us(250);

                                               }

                               printf("droite : %u\n\r", nb);

                               if (nb > etalon) return 1;

                               else return 0;

                }

 

Détaillons cette partie importante :

 

Dans cette partie on définit la fonction ir_droit() qui correspond à la détection d’un obstacle à droite. Ensuite on demande à la led droite d’envoyer un signal. Ensuite le détecteur va renvoyer ce qu’il reçoit. Si le signal est assez fort, c’est qu’un obstacle est détecté. Et donc le PIC recevra la valeur 1.

 

 

Conclusion, résultat, projets futurs, etc