Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
wiki:projets:card_dealer [2018/10/22 14:58] ROMAIN Adelaide |
wiki:projets:card_dealer [2020/10/05 14:39] (Version actuelle) |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ====== | + | ====== |
+ | ==== Journal de bord ==== | ||
+ | <fs large>22 octobre 2018: </fs> \\ | ||
- | Porteur(s) | + | - Création de la page wiki du projet |
- | {{ :wiki: | + | <fs large>25 octobre 2018:</fs> \\ |
- | L' | + | * État de l'art |
- | Les " | + | |
- | Si ce projet | + | Porteur(s) du projet: Romain Sever (contact : [[romain.sever@gmail.com|romain.sever@gmail.com]]) |
- | Ce projet | + | ===== Présentation du projet ===== |
- | <fs medium> | + | L' |
- | <fs medium> | + | |
- | ===== Matériel nécessaire ===== | + | |
- | L' | ||
- | Le chassis du robot serait en partie constitué de LEGO Technic et l' | ||
- | - 1 [[arduino uno|Arduino Uno]] ou similaire | + | <fs medium> |
- | {{http://upload.wikimedia.org/ | + | <fs medium> |
- | - 1 ou plusieurs [[https:// | + | ===== État de l'art ===== |
+ | Il existe déjà différentes machines pour mélanger les cartes notamment dans les casinos : https:// | ||
+ | ou encore des gadget qu'on peut trouver sur Amazon : https://www.youtube.com/ | ||
+ | Mais aucun d'eux ne peut distribuer. | ||
- | - Des [[https:// | + | Les machines comme celle du uno peut quant-à-elle distribuer mais ne peut pas compter ni mélanger. |
- | - Un driver | + | Et ainsi de suite, beaucoup de projet DIY ont été réalisé mais aucun n'est capable de faire les 3 actions grâce à un mème robot |
- | - Un petit [[https:// | + | https:// |
+ | https://www.youtube.com/ | ||
+ | https:// | ||
+ | https:// | ||
- | - Une pile de 9V et des connecteurs pour alimenter les moteurs DC. | ||
- | - des câbles jumper, résistances, | ||
- | - des LEGO Technic ou du carton rigide pour construire le chassis du robot. | + | ===== Cahier des charges |
- | + | Afin de pouvoir organiser | |
- | + | ||
- | - Une imprimante 3D pour imprimer des pièces qui permettront d' | + | |
- | Le fichier que nous allons imprimer est disponible sur [[https:// | + | |
- | ===== Construction | + | |
- | + | ||
- | ==== Partie 1 : Test du capteur à ultrasons ==== | + | |
- | + | ||
- | On va commencer par tester le capteur à ultrasons. On écrit un petit programme pour allumer une LED lorsque le capteur voit un obstacle à moins de 2 mètres. \\ | + | |
- | Pour comprendre comment mesurer une distance à l'aide du capteur HC-SR04, vous pouvez suivre | + | |
- | + | ||
- | <fs x-large> | + | |
- | </ | + | |
- | + | ||
- | {{ : | + | |
- | + | ||
- | < | + | |
- | + | ||
- | <fs x-large> | + | |
- | </ | + | |
- | + | ||
- | <code =Arduino> | + | |
- | /* | + | |
- | * Code d' | + | |
- | */ | + | |
- | + | ||
- | /* Constantes pour les broches */ | + | |
- | const byte TRIGGER_PIN = 2; // Broche TRIGGER | + | |
- | const byte ECHO_PIN = 3; // Broche ECHO | + | |
- | const byte LED_PIN = 12; // Broche LED | + | |
- | + | ||
- | + | ||
- | /* Constantes pour le timeout: le temps à partir duquel le capteur considère qu'il n'y a aucun obstacle à portée (temps de parcours d' | + | |
- | const unsigned long MEASURE_TIMEOUT = 50000UL; // 25ms = ~8m a 340m/s | + | |
- | + | ||
- | /* Vitesse du son dans l'air en mm/ | + | |
- | const float SOUND_SPEED = 340.0 / 1000; | + | |
- | + | ||
- | /** Fonction setup() */ | + | |
- | void setup() { | + | |
- | + | ||
- | /* Initialise le port serie */ | + | |
- | Serial.begin(115200); | + | |
- | + | ||
- | /* Initialise | + | |
- | pinMode(TRIGGER_PIN, | + | |
- | digitalWrite(TRIGGER_PIN, | + | |
- | + | ||
- | pinMode(LED_PIN, | + | |
- | digitalWrite(LED_PIN, | + | |
- | + | ||
- | pinMode(ECHO_PIN, | + | |
- | } | + | |
- | + | ||
- | /** Fonction loop() */ | + | |
- | void loop() { | + | |
- | + | ||
- | /* 1. Lance une mesure de distance en envoyant une impulsion HIGH de 10 microsec sur la broche TRIGGER */ | + | |
- | digitalWrite(TRIGGER_PIN, | + | |
- | delayMicroseconds(10); | + | |
- | digitalWrite(TRIGGER_PIN, | + | |
- | + | ||
- | /* 2. Mesure | + | |
- | long measure = pulseIn(ECHO_PIN, | + | |
- | + | ||
- | /* 3. Calcule la distance à partir du temps mesuré */ | + | |
- | float distance_mm = measure / 2.0 * SOUND_SPEED; | + | |
- | + | ||
- | if(distance_mm/ | + | |
- | digitalWrite(LED_PIN, | + | |
- | } | + | |
- | + | ||
- | // Affiche les résultats en m | + | |
- | Serial.print(F(" | + | |
- | Serial.print(distance_mm / 1000.0, 2); | + | |
- | Serial.println(F(" | + | |
- | + | ||
- | + | ||
- | /* Délai d' | + | |
- | delay(200); | + | |
- | + | ||
- | digitalWrite(LED_PIN, | + | |
- | + | ||
- | }</ | + | |
+ | ===Fonctions=== | ||
+ | * Compter les points | ||
+ | * Trier les cartes | ||
+ | * Mélanger les cartes | ||
+ | * Distribuer les cartes au bon nombre de joueurs | ||
+ | * Retourner les cartes (poker) | ||
+ | * Distribuer un chien | ||
+ | * Ne pas mélanger les cartes | ||
+ | * Afficher les points | ||
+ | * Calculer les points | ||
+ | * Permettre de sélectionner le nombre de joueur | ||
+ | * Permettre de sélectionner le jeu | ||
+ | ===== Dossier de conception ====== | ||
+ | Le robot ce divisera en trois étages qui auront chacun leurs fonctionnalités. Tout d' | ||
+ | Ensuite, il enverra chaque carte dans le Mélangeur. Lui, sera capable de mélanger ou non les cartes en fonction du programme demandé. Enfin le distributeur pourra distribuer au nombre de joueur désiré et retourner ou non les cartes. | ||
+ | ====Compteur/ | ||
+ | Pour compter trier les cartes on utilisera une camera et la librairie OpenCV. Cette partie du robot sera une boite avec une fente sur le coté. On y placera les cartes. Au fond, une roue entrainera les cartes une à une à travers la fente dans l' | ||
+ | ==== Mélangeur==== | ||
+ | Le mélangeur est constitué d'un "porte feuille" | ||
+ | ====Distributeur==== | ||
+ | Le distributeur est un réceptacle avec une roue pour tirer les carte une à une comme le compteur. Les cartes sortent sur un toboggan les amenant devant le joueur. Le tout est monté sur une base tournante afin de distribuer les cartes devant chaque joueur. | ||
Ligne 131: | Ligne 70: | ||
- | |||
- | ==== Partie 2 : Apprendre à piloter des moteurs DC avec Arduino et une carte TB6612FNG ==== | ||
- | |||
- | A l'aide d'une carte électronique Dual TB6612FNG (1A) (motor driver), on peut piloter deux moteurs DC avec la carte Arduino et leur envoyer des instructions de vitesse et de sens de rotation | ||
- | |||
- | La puce en question, dispo par exemple sur [[https:// | ||
- | {{ : | ||
- | |||
- | <fs x-large> | ||
- | </fs> | ||
- | |||
- | |||
- | {{ : | ||
- | |||
- | Les ports du motor driver Dual TB6612FNG : | ||
- | |||
- | {{ : | ||
- | |||
- | - Les ports GND doivent être connectés au GND de l' | ||
- | - Le port VCC est connecté au port 5V de l' | ||
- | - Pour piloter les moteurs, on utilise une pile de 9V, le + de la pile est connecté à VM et le - au GND de l' | ||
- | - Les deux connecteurs des moteurs DC doivent branchés sur A01 et A02 pour le moteur A et B01 et B02 pour le moteur B. | ||
- | - Les ports de gauche sont les ports qui permettent de contrôler la vitesse et le sens de rotation des moteurs. Ils sont connectés à des ports digitaux en sortie de l' | ||
- | |||
- | <fs x-large> | ||
- | </fs> | ||
- | |||
- | <code =Arduino> | ||
- | //Moteur A connecté entre les pins A01 et A02 du Motor Driver TB6612FNG | ||
- | //Moteur B connecté entre les pins B01 et B02 du Motor Driver TB6612FNG | ||
- | |||
- | int STBY = 10; // standby Pin (si HIGH alors on peut faire tourner les moteurs, si LOW, les moteurs s' | ||
- | |||
- | //Motor A | ||
- | int PWMA = 5; //Pin qui contrôle la vitesse du moteur A (nombre entre 0 et 255 donc on doit le mettre sur un port PWM) | ||
- | // AIN1 et AIN2 sont les pins de sens de rotation du moteur A | ||
- | // Le moteur A tourne dans le sens horaire si le pin AIN1 est LOW et le pin AIN2 est HIGH | ||
- | // Inversement, | ||
- | // (si les deux sont LOW ou les deux sont HIGH, il ne tourne pas) | ||
- | int AIN1 = 9; //Sens de rotation | ||
- | int AIN2 = 8; //Sens | ||
- | |||
- | //Motor B | ||
- | int PWMB = 3; //Pin qui contrôle la vitesse du moteur B | ||
- | // Pins de sens de rotation du moteur B | ||
- | int BIN1 = 11; //Sens | ||
- | int BIN2 = 12; //Sens | ||
- | |||
- | void setup() { | ||
- | // On définit tous les ports comme sorties pour piloter les moteurs | ||
- | pinMode(STBY, | ||
- | |||
- | // Commandes Moteur A | ||
- | pinMode(PWMA, | ||
- | pinMode(AIN1, | ||
- | pinMode(AIN2, | ||
- | |||
- | // Commandes Moteur B | ||
- | pinMode(PWMB, | ||
- | pinMode(BIN1, | ||
- | pinMode(BIN2, | ||
- | } | ||
- | |||
- | void loop() { | ||
- | move(1, 200, 1); //motor 1, full speed, left | ||
- | move(2, 200, 1); //motor 2, full speed, left | ||
- | |||
- | delay(5000); | ||
- | stop(); // on stoppe les moteurs | ||
- | delay(250); //hold for 250ms until move again | ||
- | |||
- | move(1, 128, 0); //motor 1, half speed, right | ||
- | move(2, 128, 0); //motor 2, half speed, right | ||
- | |||
- | delay(1000); | ||
- | stop(); | ||
- | delay(250); | ||
- | } | ||
- | |||
- | void move(int motor, int speed, int direction) { | ||
- | // Function move(): Move specific motor at speed and direction | ||
- | // | ||
- | // Inputs: | ||
- | // motor: 0 for B and 1 for A | ||
- | // speed: number between 0 and 255: 0 is off, and 255 is full speed | ||
- | // direction: 0 clockwise, 1 counter-clockwise | ||
- | |||
- | // DEMARRAGE | ||
- | digitalWrite(STBY, | ||
- | |||
- | // SENS DE ROTATION | ||
- | // Sens Horaire | ||
- | // Le moteur A tourne dans le sens horaire si le pin AIN1 est LOW et le pin AIN2 est HIGH (si les deux sont LOW ou les deux sont HIGH, il ne tourne pas) | ||
- | boolean inPin1 = LOW; | ||
- | boolean inPin2 = HIGH; | ||
- | // Sens Anti-Horaire | ||
- | if (direction == 1) { // Si on change la direction dans le sens antihoraire | ||
- | inPin1 = HIGH; | ||
- | inPin2 = LOW; | ||
- | } | ||
- | |||
- | // ENVOI DES INSTRUCTIONS DE SENS DE ROTATION ET DE VITESSE AUX MOTEURS | ||
- | if (motor == 1) { // MOTEUR A | ||
- | digitalWrite(AIN1, | ||
- | digitalWrite(AIN2, | ||
- | analogWrite(PWMA, | ||
- | } else { // if motor == 0 (MOTEUR B) | ||
- | digitalWrite(BIN1, | ||
- | digitalWrite(BIN2, | ||
- | analogWrite(PWMB, | ||
- | } | ||
- | } | ||
- | |||
- | void stop() { | ||
- | //Function stop(): Appeler cette fonction dans le programme pour stopper les moteurs | ||
- | digitalWrite(STBY, | ||
- | } | ||
- | </ | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ---- | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ==== Partie 3 : Instructions pour les moteurs ==== | ||
- | |||
- | Maintenant que l'on sait comment lire les données de distance du capteur à ultrasons et comment piloter les moteurs, nous pouvons maintenant combiner les scripts précédents pour donner les instructions aux moteurs du robot. | ||
- | Il faut aussi modifier le montage pour incorporer le capteur à ultrasons et les moteurs. | ||
- | |||
- | <fs x-large> | ||
- | </fs> | ||
- | |||
- | {{ : | ||
- | |||
- | |||
- | - Lorsqu' | ||
- | |||
- | |||
- | < | ||
- | move(1, 100, 1); //motor 1, full speed, left | ||
- | move(0, 100, 1); //motor 2, full speed, left | ||
- | </ | ||
- | |||
- | - Lorsque le robot voir un obstacle, on le fait s' | ||
- | |||
- | < | ||
- | move(1, 50, 0); //motor 1, recule | ||
- | move(0, 50, 0); //motor 2, recule | ||
- | delay(3000); | ||
- | </ | ||
- | |||
- | |||
- | Enfin, on fait tourner le robot en faisant tourner ses deux roues dans un sens opposé pendant 1.5s, avant de s' | ||
- | |||
- | < | ||
- | |||
- | |||
- | randNumber = random(100.0); | ||
- | if (randNumber < 50.0) { | ||
- | move(1, 100, 1); //motor 1, tourne à gauche | ||
- | move(0, 100, 0); //motor 2, tourne | ||
- | } else { | ||
- | move(1, 100, 0); //motor 1, tourne à droite | ||
- | move(0, 100, 1); //motor 2, tourne | ||
- | } | ||
- | delay(1500); | ||
- | stop(); // Stopper les moteurs | ||
- | | ||
- | </ | ||
- | |||
- | |||
- | Voilà le code complet ci-dessous : | ||
- | |||
- | |||
- | <fs x-large> | ||
- | </fs> | ||
- | |||
- | <code =Arduino> | ||
- | |||
- | /* Code pour piloter des moteurs quand le capteur à ultrasons détecte un obstacle */ | ||
- | /* Robot éviteur d' | ||
- | |||
- | //Moteur A connecté entre les pins A01 et A02 du Motor Driver TB6612FNG | ||
- | //Moteur B connecté entre les pins B01 et B02 du Motor Driver TB6612FNG | ||
- | |||
- | int STBY = 10; // standby Pin (si HIGH alors on peut faire tourner les moteurs, si LOW, les moteurs s' | ||
- | |||
- | //Motor A | ||
- | int PWMA = 5; //Pin qui contrôle la vitesse du moteur A (nombre entre 0 et 255 donc on doit le mettre sur un port PWM) | ||
- | // AIN1 et AIN2 sont les pins de sens de rotation du moteur A | ||
- | // Le moteur A tourne dans le sens horaire si le pin AIN1 est LOW et le pin AIN2 est HIGH | ||
- | // Inversement, | ||
- | // (si les deux sont LOW ou les deux sont HIGH, il ne tourne pas) | ||
- | int AIN1 = 9; //Sens de rotation | ||
- | int AIN2 = 8; //Sens | ||
- | |||
- | //Motor B | ||
- | int PWMB = 6; //Pin qui contrôle la vitesse du moteur B | ||
- | // Pins de sens de rotation du moteur B | ||
- | int BIN1 = 11; //Sens | ||
- | int BIN2 = 12; //Sens | ||
- | |||
- | /* Constantes pour les broches */ | ||
- | const byte TRIGGER_PIN = 2; // Broche TRIGGER | ||
- | const byte ECHO_PIN = 3; // Broche ECHO | ||
- | const byte LED_PIN = 7; // Broche LED | ||
- | |||
- | /* Constantes pour le timeout */ | ||
- | const unsigned long MEASURE_TIMEOUT = 50000UL; // 25ms = ~8m a 340m/s | ||
- | |||
- | /* Vitesse du son dans l'air en mm/ | ||
- | const float SOUND_SPEED = 340.0 / 1000; | ||
- | |||
- | |||
- | long randNumber; | ||
- | |||
- | |||
- | /** Fonction setup() */ | ||
- | void setup() { | ||
- | /* Initialise le port serie */ | ||
- | Serial.begin(115200); | ||
- | |||
- | /* Capteur Ultrasons */ | ||
- | // Initialise les broches pour le capteur à ultrasons | ||
- | pinMode(TRIGGER_PIN, | ||
- | digitalWrite(TRIGGER_PIN, | ||
- | pinMode(LED_PIN, | ||
- | digitalWrite(LED_PIN, | ||
- | pinMode(ECHO_PIN, | ||
- | |||
- | /* Moteurs */ | ||
- | // On définit tous les ports comme sorties pour piloter les moteurs | ||
- | pinMode(STBY, | ||
- | // Commandes Moteur A | ||
- | pinMode(PWMA, | ||
- | pinMode(AIN1, | ||
- | pinMode(AIN2, | ||
- | // Commandes Moteur B | ||
- | pinMode(PWMB, | ||
- | pinMode(BIN1, | ||
- | pinMode(BIN2, | ||
- | |||
- | } | ||
- | |||
- | |||
- | void loop() { | ||
- | move(1, 100, 1); //motor 1, full speed, left | ||
- | move(0, 100, 1); //motor 2, full speed, left | ||
- | |||
- | /* 1. Lance une mesure de distance en envoyant une impulsion HIGH de 10 microsec sur la broche TRIGGER */ | ||
- | digitalWrite(TRIGGER_PIN, | ||
- | delayMicroseconds(10); | ||
- | digitalWrite(TRIGGER_PIN, | ||
- | /* 2. Mesure le temps entre l' | ||
- | long measure = pulseIn(ECHO_PIN, | ||
- | /* 3. Calcule la distance à partir du temps mesuré */ | ||
- | float distance_mm = measure / 2.0 * SOUND_SPEED; | ||
- | |||
- | if (distance_mm / 1000 < 0.2) { | ||
- | digitalWrite(LED_PIN, | ||
- | stop(); // Stopper les moteurs | ||
- | delay(2000); | ||
- | |||
- | move(1, 50, 0); //motor 1, recule | ||
- | move(0, 50, 0); //motor 2, recule | ||
- | delay(3000); | ||
- | stop(); // Stopper les moteurs | ||
- | delay(1000); | ||
- | |||
- | // On fait tourner le robot dans une direction aléatoire | ||
- | randNumber = random(100.0); | ||
- | if (randNumber < 50.0) { | ||
- | move(1, 100, 1); //motor 1, tourne à gauche | ||
- | move(0, 100, 0); //motor 2, tourne | ||
- | } else { | ||
- | move(1, 100, 0); //motor 1, tourne à droite | ||
- | move(0, 100, 1); //motor 2, tourne | ||
- | } | ||
- | delay(1500); | ||
- | stop(); // Stopper les moteurs | ||
- | delay(1000); | ||
- | |||
- | digitalWrite(LED_PIN, | ||
- | } | ||
- | // // Affiche les résultats en m | ||
- | // Serial.print(F(" | ||
- | // Serial.print(distance_mm / 1000.0, 2); | ||
- | // Serial.println(F(" | ||
- | |||
- | |||
- | /* Délai d' | ||
- | delay(200); | ||
- | |||
- | |||
- | } | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | void move(int motor, int speed, int direction) { | ||
- | // Function move(): Move specific motor at speed and direction | ||
- | // | ||
- | // Inputs: | ||
- | // motor: 0 for B and 1 for A | ||
- | // speed: number between 0 and 255: 0 is off, and 255 is full speed | ||
- | // direction: 0 clockwise, 1 counter-clockwise | ||
- | |||
- | // DEMARRAGE | ||
- | digitalWrite(STBY, | ||
- | |||
- | // SENS DE ROTATION | ||
- | // Sens Horaire | ||
- | // Le moteur A tourne dans le sens horaire si le pin AIN1 est LOW et le pin AIN2 est HIGH (si les deux sont LOW ou les deux sont HIGH, il ne tourne pas) | ||
- | boolean inPin1 = LOW; | ||
- | boolean inPin2 = HIGH; | ||
- | // Sens Anti-Horaire | ||
- | if (direction == 1) { // Si on change la direction dans le sens antihoraire | ||
- | inPin1 = HIGH; | ||
- | inPin2 = LOW; | ||
- | } | ||
- | |||
- | // ENVOI DES INSTRUCTIONS DE SENS DE ROTATION ET DE VITESSE AUX MOTEURS | ||
- | if (motor == 1) { // MOTEUR A | ||
- | digitalWrite(AIN1, | ||
- | digitalWrite(AIN2, | ||
- | analogWrite(PWMA, | ||
- | } else { // if motor == 0 (MOTEUR B) | ||
- | digitalWrite(BIN1, | ||
- | digitalWrite(BIN2, | ||
- | analogWrite(PWMB, | ||
- | } | ||
- | } | ||
- | |||
- | void stop() { | ||
- | //Function stop(): Appeler cette fonction dans le programme pour stopper les moteurs | ||
- | digitalWrite(STBY, | ||
- | } | ||
- | |||
- | </ | ||
- | |||
- | La partie programmation est maintenant presque terminée. On peut à l' | ||
- | |||
- | Il faut maintenant construire le chassis du robot. | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ---- | ||
- | |||
- | |||
- | |||
- | ==== Partie 4 : Construction du chassis : Premier prototype de robot ! ==== | ||
- | |||
- | {{ : | ||
- | |||
- | Il faut ensuite construire un chassis pour porter notre électronique. | ||
- | |||
- | Il y a pas de chassis type mais voici quelques astuces pour le construire: | ||
- | |||
- | <note tip> | ||
- | |||
- | - Placer le capteur à ultrasons en hauteur par rapport au sol (au moins 10 cm) sinon le capteur verra le sol comme un obstacle. | ||
- | |||
- | - Les deux roues motrices du robot sont situées à l' | ||
- | |||
- | - J'ai utilisé des LEGO Technic pour construire le chassis. On peut imprimer des pièces en 3D pour adapter les moteurs aux LEGO; les pièces sont en noir sur la photo (cf le fichier donné dans la section " | ||
- | |||
- | - J'ai utilisé [[https:// | ||
- | |||
- | |||
- | |||
- | </ | ||
- | |||
- | |||
- | ---- | ||
- | |||
- | |||
- | |||
- | ===== Journal de bord ===== | ||
- | |||
- | <fs large>24 janvier 2018: | ||
- | </fs> \\ | ||
- | |||
- | - création de la page wiki du projet | ||
- | - Test du capteur à ultrasons | ||
- | |||
- | <fs large>25 janvier 2018: | ||
- | </fs> \\ | ||
- | |||
- | - Test du driver Dual TB6612FNG pour piloter des moteurs DC avec la carte Arduino | ||
- | |||
- | <fs large> | ||
- | </fs> \\ | ||
- | |||
- | - Construction du premier prototype du robot | ||
- | |||
- | <fs large>19 février 2018: | ||
- | </fs> \\ | ||
- | |||
- | - Mise à jour du wiki | ||