Catégorie:RobotGEII : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
({{Rouge|Description et présentation du Projet}})
({{Rouge|Description et présentation du Projet}})
Ligne 4 : Ligne 4 :
  
  
=={{Bleu|''Présentation du championnat''}}==
+
=={{Bleu|'''Présentation du championnat'''}}==
  
 
=={{vert|Règle du jeu}}==
 
=={{vert|Règle du jeu}}==
  
  
=={{Bleu|Structure du robot}}==
+
=={{Bleu|'''Structure du robot'''}}==
  
 
=={{vert|Mécanique}}==
 
=={{vert|Mécanique}}==

Version du 18 mars 2016 à 09:00


Description et présentation du Projet

Présentation du championnat

Règle du jeu

Structure du robot

Mécanique

Design

Alimentation

Arrêt d'urgence

Prise jack

Dimensions

Ballon

Indicateur d'arriver

Carte ultrason (Alexandre.N)

programme de test des capteurs US :

int trig = 36;
int echo = A9;
long lecture_echo;
long cm;


void setup()
{
  pinMode(trig, OUTPUT);
  digitalWrite(trig, LOW);
  pinMode(echo, INPUT);
  Serial.begin(9600);
}

void loop()
{
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  lecture_echo = pulseIn(echo, HIGH);
  cm = lecture_echo / 58;
  Serial.print("Distance : ");
  Serial.print(cm);
  Serial.println(" cm");
  delay(100);
}



programme final des capteur US :

#include <util/delay.h>
#define distUSmini 30

/*  _Trigger_
    37 - PC0
    36 - PC1
    35 - PC2
    34 - PC3
    33 - PC4
    32 - PC5
    31 - PC6

    _Echo_
    8 - PK0
    9 - PK1
    10 - PK2
    11 - PK3
    12 - PK4
    13 - PK5
    14 - PK6
*/


boolean toggle1 = 0;
volatile unsigned long t[8];
unsigned long tfin, tdebut, d;
volatile boolean recpt;
volatile boolean newmesure = false;
volatile char numCapt;
volatile uint8_t USmode;


void setup() {
  Serial.begin(115200);

  pinMode(37, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(35, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(31, OUTPUT);

  cli();
  TCCR2A = 0;
  TCCR2B = 0;
  OCR2A = 156;
  TCCR2B |= (1 << WGM12);
  TCCR2B |= (1 << CS11);
  TCCR2B |= (1 << CS10);
  TCCR2B |= (1 << CS12);
  TIMSK2 |= (1 << OCIE1A);
  PCICR |= 1 << PCIE2;
  sei();
}


ISR(TIMER2_COMPA_vect)
{
  static boolean start = true;

  if (start == true)
  {
    if (USmode == 0) numCapt = 7;
    if (USmode == 1) numCapt = 0;

    if (numCapt != 7) //mode1
    {
      numCapt++;
      if (numCapt == 2) numCapt = 0; //à retirer quand 7 capteurs
    }
    TCCR2B &= ~((1 << CS12) | (1 << CS10));
    OCR2A = 150;
    if (numCapt == 7) // mode0
    {
      PORTC = 0b01111111;
      PCMSK2 = 0b01111111;
    }
    else
    {
      PORTC = 1 << numCapt;
      PCMSK2 = 1 << numCapt;
    }
  }
  else
  {
    PORTC = 0;
    recpt = false;
    TCCR2B |= ((1 << CS12) | (1 << CS10));
    OCR2A = 30;
  }
  start = !start;
}

ISR(PCINT2_vect)
{
  if (recpt == false)
  {
    tdebut = micros();
    recpt = true;
  }
  else
  {
    tfin = micros();
    if ((tfin - tdebut) > 50)
    {
      t[numCapt] = tfin - tdebut;
      recpt = false;
      newmesure = true;
    }
  }
}

void loop() {
  setUSmode(0);
  static unsigned long dateAffichage = 0, dateActuelle;
  dateActuelle = millis();
  if (newmesure == true)
  {
    //t = tfin - tdebut;
    if ((dateActuelle - dateAffichage) > 200)
    {
      //if
      dateAffichage = dateActuelle;
      //d = t / 58;
      Serial.print("Duree 0: ");
      Serial.print(t[0], DEC);
      Serial.println(" us.");
      Serial.print("Duree 1: ");
      Serial.print(t[1], DEC);
      Serial.println(" us.");
      Serial.print("Duree 2: ");
      Serial.print(t[2], DEC);
      Serial.println(" us.");
      Serial.print("Duree 3: ");
      Serial.print(t[3], DEC);
      Serial.println(" us.");
      Serial.print("Duree 4: ");
      Serial.print(t[4], DEC);
      Serial.println(" us.");
      Serial.print("Duree 5: ");
      Serial.print(t[5], DEC);
      Serial.println(" us.");
      Serial.print("Duree 6: ");
      Serial.print(t[6], DEC);
      Serial.println(" us.");
      Serial.print("Duree 7: ");
      Serial.print(t[7], DEC);
      Serial.println(" us.");
    }
    newmesure = false;
  }
}

void setUSmode(uint8_t mode)
{
  if (mode == 0) {
    USmode = 0;
    //numCapt=7;
  }
  if (mode == 1) {
    USmode = 1;
    //numCapt=0;
  }

}

Capteur US.jpg

Carte gestion des moteurs (Johan)

Carte Moteur

Carte ultrason (Vincent)

Presentation

La carte ultrason joue un rôle essentiel dans les déplacements de notre robot, elle est chargée de détecter les obstacles de manière précise et rapide afin d'informer le robot sur leur position pour qu'il puisse réagir et les éviter. Pour détecter les obstacles nous utilisons le module HC-SR04 permettant l'acquisition d'une information de distance.

HC-SR04.jpg

  • Présentation du module HC-SR04 : Le HC-SR04 est un module ultrason permettant l'évaluation d'une distance de 2cm à 4m. La mesure est réalisée "sans contact". Le module est composé d'un émetteur et d'un récepteur ultrason ainsi qu'une électronique de contrôle. Le fonctionnement de ce module s'apparente à celui d'un sonar de sous marin et sa mise en œuvre est relativement simple car il est prêt à l'emploi et possède 4 pattes: un GND, un VCC, un triger pour effectuer la mesure et un Écho pour le résultat de la mesure.

Conception de la carte ultrason

Cahier des charges



Tout d'abord, pour la conception de cette carte, nous utiliseront 7 modules ultrason afin de donner le plus d'informations possible sur les obstacles positionnés sur la trajectoire du robot. Le module HC-SR04 n’étant pas répertorié par Eagle nous devons donc commencer par créer le composant, ainsi que son empreinte qui comportera la taille réelle du composant sur Eagle.

Symbole du module HCSR04 Empreinte du module HCSR04

Cahier des charges:

  • Alimentation du micro-contrôleur séparée de l'alimentation des capteurs ultrason
  • Utilisation d'un micro-contrôleur (ATtiny88) pour gérer plus facilement les mesures des capteurs
  • Condensateur de découplage pour chaque capteur ultrason afin d'éviter le bruit
  • Bornier SPI pour communiquer avec les autres cartes du robot
  • Angle de 30° entre les capteurs pour gérer plus facilement le déplacements du robot



Ensuite nous devons choisir un microcontrôleur afin de piloter cette carte: on choisira un AT TINY 88 car il possede 2 port (C et D) dont on se servira pour gerer les 7 triger et les 7 echo des modules ultrason. Ce microcontrôleur permet aussi une communication SPI dont on se servira pour communiquer avec les autres cartes du robot.

Le bornier utilisé pour la liaison SPI doit répondre à des normes : Symbole du module HCSR04


Schéma, board, typon et schéma de connexion de la carte ultrason


Voici les différents schémas utiles de la carte ultrason:

texte alternatif

Todo.jpg On peut voir sur le schéma éléctrique que les 7 modules ultrason sont reliés sur les deux ports du micro-contrôleur.

board de la carte ultrason

Todo.jpg Voici le board de la carte ultrason.

tipon de la carte ultrason

Todo.jpg Ici les typons utiles à la réalisation de la carte.


texte alternatif

Todo.jpg Voici le Schéma des connexions de la carte ultrason.

Programmation de la carte ultrason

Premiers tests

Après la réalisation de la carte ultrason, nous avons effectués plusieurs tests pour vérifier son bon fonctionnement. Tout d'abord nous avons constaté une erreur: sur l'empreinte du composant HC-SR04, nous avons inversé le GND et le VCC, ce qui a par la suite causé des problèmes sur la carte. Nous avons donc corrigé ce problème, et avons effectué d'autres tests comme celui de la continuité.


Todo.jpg Nous avons ensuite testé le fonctionnement des 7 capteurs ultrason utilisé à l'aide du programme arduino si dessous qui nous transmettait par la liaison série la distance mesurée par le capteur:

/* Pinmapping */
const byte TRIGGER_PIN = 2; // Broche TRIGGER
const byte ECHO_PIN = 3;    // Broche ECHO
 
/* Constantes */
const long MEASURE_TIMEOUT = 25000L; // 40Hz = 25ms = ~8m à 340m/s
 
/* setup() */
void setup() {
   
  /* Pour l'affichage des résultats */
  Serial.begin(9600);
   
  /* Initialisation des broches */
  pinMode(TRIGGER_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  digitalWrite(TRIGGER_PIN, LOW); // DOIT être à LOW au repos
   
  /* Message d’accueil */
  Serial.println(F("~~ HC-SR04 ~~"));
}
 
/* loop() */
void loop() {
  
  /* 1) Lance une mesure de distance en envoyant une impulsion HIGH de 10µs sur la broche TRIGGER */
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER_PIN, LOW);
  
  /* 2) Mesure le temps entre l'envoi de l'impulsion ultrasonique et son écho (si il existe) */
  long measure = pulseIn(ECHO_PIN, HIGH, MEASURE_TIMEOUT);
   
  /* 3) Calcul la distance à partir du temps mesuré */
  long mm = measure / 2 * 0.34;
   
  /* Affiche les résultats en mm, cm et m */
  Serial.print(F("Distance: "));
  Serial.print(mm);
  Serial.print(F("mm ("));
  Serial.print(mm / 10.0, 2);
  Serial.print(F("cm, "));
  Serial.print(mm / 1000.0, 2);
  Serial.println(F("m)"));
   
  /* Délai d'attente pour éviter d'afficher trop de résultats à la seconde */
  delay(60);
}




programme de communication SPI : Ce programme permet d'établir la communication entre la carte ultrason (esclave) et la carte Arduino (maître). Pour vérifier le bon fonctionnement de la communication il suffit de programmer le micro-contrôleur de la carte ultrason pour qu'il transmette une valeur sur la liaison serie.

#include <SPI.h> //master 
void setup (void) 
{ 
  Serial.begin(115200);
  digitalWrite(SS, HIGH);
  // ensure SS stays high for now
  // Put SCK, MOSI, SS pins intooutput mode
  // also put SCK, MOSI into LOWstate, and SS into HIGH state.
  // Then put SPI hardware into Mastermode and turn SPI on
  SPI.begin ();
  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV128);
}
// end of setup 
void loop (void) 
{
  uint8_t c,a;
  // enable Slave Select
  digitalWrite(SS, LOW);
  // SS is pin 10
  // send test string
  a=SPI.transfer (10);
  digitalWrite(SS, HIGH);
  Serial.println(a,DEC);
  // disable Slave Select
  delay (100);
  // 1 seconds delay
}


Carte Codeur (Alexandre.L)

Comunication SPI arduino

Principe de la communication SPI sur Arduino

Une liaison SPI (Serial Peripheral Interface) est un bus de données série synchrone, qui opère en Full-duplex. Les circuits communiquent selon un schéma maître-esclaves, où le maître s'occupe totalement de la communication. Plusieurs esclaves peuvent coexister sur un même bus, dans ce cas, la sélection du destinataire se fait par le Slave Select.


SPI three slaves.svg.png

on dispose donc des pattes suivantes:

  • MOSI : Master Output Slave Input, le maître parle l'esclave écoute
  • MISO : Master Input Slave Output, le maître écoute, l’esclave parle
  • SLK : Serial Clock, Horloge de synchronisation généré par le maître
  • SS : Slave Select, utilisé si on dispose de plusieurs esclaves pour sélectionner avec lequel on communique



Echanges de données en SPI:



Maintenant que le principe de fonctionnement de la liaison SPI est éclaircit, intéressons nous aux échanges de données
SPI 8-bit circular transfer.svg.png

Todo.jpg on notera que les données circulent de manière circulaire; le bit 7 du master arrive sur b0 du slave, tandis que b7 du slave est envoyé sur b0 du master. il y a un décalage des bits contenus dans le registre SPDR (registre qui stock les données recues et envoyées sur la liaison SPI).

programme minimum Arduino de communication SPI:



Avec ces quelques bases, nous pouvons comprendre le programme Arduino suivant qui établit une communication quelques peu rudimentaire, mais qui illustre les fonctions Arduino utilisées pour créer une communication SPI:
Todo.jpg la carte Arduino Uno que nous utilisons possède déjà des pattes dédiées à la communication SPI:

  • MOSI : Pin 11
  • MISO : Pin 12
  • SCLK : Pin 13
  • SS : Pin 10
  • N'oublions pas de connecter les masses Arduino ensembles pour que la tension de référence soit la même




Programme maître:

// Written by Nick Gammon
// February 2011


#include <SPI.h>

void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  Serial.begin(115200);
  
}  // end of setup


void loop (void)
{

  char c,r;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Hello, world!\n" ; c = *p; p++)
    Serial.write(SPI.transfer (c));
  Serial.write('\n');
  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay 
}  // end of loop




Programme esclave:

// Written by Nick Gammon
// February 2011


#include <SPI.h>

char buf [100];
volatile byte pos;
volatile boolean process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging
  
  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  
  // get ready for an interrupt 
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  static uint8_t i=0;
byte c = SPDR;  // grab byte from SPI Data Register
  
  // add to buffer if room
  if (pos < sizeof buf)
    {
    buf [pos++] = c;
 //   SPDR=i;
 //   i++;
    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;
      
    }  // end of room available
    
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;  
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set
    
}  // end of loop


Conception et réalisation de la carte codeur

Pour concevoir et réaliser la carte, nous devons respecter les contraintes suivantes:

  • pas de pistes au dos de la carte : la carte sera fixée et plaquée sur le châssis (à cause de l'espace occupé par les moteurs), le contact entre le dos de la carte et le châssis va créer des court-circuits si des pistes sont au dos. De plus pour des raisons de coût et de simplicité de réalisation cela est préférable.
  • la position des codeurs sera fixe : ils seront placés précisément sous les roues dentées fixées sur les axes des moteurs.
  • les pistes devrons être courtes : les grandeurs circulant sur la carte sont très faibles et seront donc facilement perturbées par les champs électriques et magnétiques.
  • choix et emplacement du connecteur : ces derniers n'ont pas de contraintes, le connecteur sera placé simplement de la manière la plus avantageuse pour le routage, et à la fois de manière accessible pour le connecter facilement.



Conception: Schéma électrique et Routage


choix des composants:

  • nous avons choisis un connecteur droit pour ça simplicité de branchement
  • les codeurs seront des Tcut 1300 du constructeur Vishay

Tcut1300.png


voici le schéma électrique:

Schema electrique-carteCodeur.png

Codeur et mesure

Todo.jpg ce schéma est plutôt simple, il est constitué d'une partie qui alimente les codeurs et d'une partie qui récupère les mesures des codeurs. Ces mesures sont renvoyé via le connecteur vers une autre carte qui analysera ces données.
Correspondance des pattes du connecteur (vue du board):

  • Patte n°1 : mesure codeur EME1 (Gauche)
  • Patte n°2 : +Vcc alimentation
  • Patte n°3 : mesure codeur EME2 (droite)
  • Patte n°4 : mesure codeur EME2 (Gauche)
  • Patte n°5 : GND masse
  • Patte n°6 : mesure codeur EME1 (droite)



BoardCarteCodeur.png

Todo.jpg on notera que les pistes sont relativement proches et que le connecteur va être difficile à souder mais cela reste envisageable. Des trous de perçage sont prévus sur la carte pour la fixer et la plaquer sur le chassi



Programme test de la carte codeur


programme de test : ce programme à pour but de valider ou non le bon fonctionnement des codeurs, il permet d'afficher le nombre d'encoches passées sur chaque roue. On peut ainsi tester si les mesures effectuées par la carte sont valides, le sens des roues etc...


Média:Codeurs.ino.zip


Gestion du déplacement du robot



équations du positionnement


Le positionnement du robot sera calculé en traitant les informations de mesures reçues sur des petits déplacements, le fait d'effectuer ces mesures sur des petits déplacements limitera l'erreur de positionnement et augmentera la précision de calcul.


Il y a deux manières d'approximer la trajectoire parcourue par le robot :


  • En utilisant des segments de droites : On considère alors que le robot va en ligne droite sur toute la période de calcul. Ceci revient à supposer que les deux roues ont une vitesse constante et identique sur cet portion de trajectoire. A la fin de cet portion, on corrige l'orientation du robot en fonction de la différence de distance parcourue par les deux roues.


  • En utilisant des arcs de cercles : On considère alors que le robot se déplace et change d'orientation en suivant un arc de cercle pendant le temps . Ceci revient à considérer que chacune des roues a une vitesse constante sur la période mais que les vitesses des 2 roues ne sont pas identiques.





positionnement par segement


On peux alors calculer les positionnement en calculant la distance parcouru et le temps de trajet des 2 roues :


positionnement par segement


Et avec ces équations, obtenir à la position du robot (coordonnées x,y)


positionnement par segement




programme de test : ce programme à pour but de valider le calcul des équations ci-dessus. Grâce au nombre d'encoches comptées sur chaque roue,il permet d'afficher la position en x du robot, sa position en y (voir axes ci-dessus), sa position angulaire et le nombre d'encoches comptés. On peut ainsi tester si les calculs effectuées renvoient une distance et un angle valide.


Média:MesurePosition.ino.zip


Programmes de déplacement



Suite a ces programmes nous avons commencé à essayer de nous rapprocher un peu plus d'un premier objectif: rendre le robot capable de se déplacer précisément. Nous avons donc travaillé sur un programme qui fait réaliser au robot un déplacement en ligne droite et s’arrête au bout d' 1 mètre. La difficulté ici a été de maintenir une trajectoire rectiligne ce qui implique une correction de trajectoire en permanence à cause de certains facteurs (les roues ne tournent pas à la même vitesse, glissement...)

programme de déplacement sur 1m : Le robot se déplace en ligne droite sur 1 mètre, sa vitesse augmente progressivement au démarrage pour éviter les glissements, elle atteint une vitesse maximum constante, puis ralentit progressivement pour s’arrêter.


Média:MesurePosition.ino.zip


système de fin de course (ballon) (Maxime)

Sous-catégories

Cette catégorie comprend seulement la sous-catégorie ci-dessous.

Pages dans la catégorie « RobotGEII »

Cette catégorie comprend 4 pages, dont les 4 ci-dessous.