Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

LEGO Wall-E avec Arduino

Composants et fournitures

LEGO Wall-E
J'ai dû en avoir une seconde car ils ne les fabriquent plus
× 1
Arduino Nano R3
× 1
Moteur à courant continu (générique)
× 2
Contrôleur de moteur double L298N
× 1
LED bicolore
avec 3 broches
× 1
Capteur infrarouge
× 1
Sonnerie
Un qui peut jouer des tons différents
× 1
Batterie 9V
× 1
Résistance 330 ohm
× 3
Câbles de raccordement (générique)
× 20

Outils et machines nécessaires

Fer à souder (générique)

Applications et services en ligne

Arduino IDE

À propos de ce projet

Tout le monde connaît le film Wall-E (et si vous ne le connaissez pas, allez le regarder maintenant !) et le héros jaune qui essaie de nettoyer la terre. Dans ce projet, j'ai utilisé une version Lego de notre petit ami et lui ai appris à éviter les obstacles. C'était mon premier projet et une excellente expérience d'apprentissage pour comprendre les bases de l'électronique.

Étape 1 - Le Code

En tant que développeur de logiciels de formation, j'ai réfléchi à ce que je voulais qu'il fasse et j'ai commencé avec le code.

 // Ce programme sert à contrôler le robot Wall-E Lego.// Wall-E se déplace. Lorsqu'il voit un obstacle, il s'arrête pour regarder autour de lui et choisit un autre chemin.// Arduino Nano a 21 broches qui peuvent être utilisées pour digitalRead et digitalWrite// Les broches PWM 3, 5, 6, 9, 10, 11 peuvent être utilisées pour analogWrite// les broches 0 et 1 peuvent être utilisées pour TTL// les broches 2 et 3 peuvent être utilisées pour les interruptions externes// les broches 10, 11, 12, 13 prennent en charge la communication SPI// la broche 13 peut être une LED interne// les broches 14 à 21 sont également des broches analogiques A0 à A7 et peuvent être utilisées pour analogRead#define INFRA_RED 9 // peut être n'importe quelle broche#define GREEN_LED 7 // peut être n'importe quelle broche mais nécessite une résistance, peut-être 220 Ohm - ou la broche de terre obtient 1 kOhm# define RED_LED 8 // peut être n'importe quelle broche mais nécessite une résistance, peut-être 220 Ohm - ou la broche de terre obtient 1 kOhm #define BUZZER 10 // doit être une broche PWM pour définir la fréquence, nécessite une résistance, peut-être 1 kOhm // MR est le moteur droit, ML est le moteur gauche#define MR_1 A1 // peut être n'importe quelle broche, alors faisons-les correspondre aux numéros de broche sur le bouclier L289N#define MR_2 A2 // peut être n'importe quelle broche, alors faisons-les correspondre au p en chiffres sur le blindage L289N#define MR_ENABLE 5 // doit être une broche PWM pour le contrôle de la vitesse#define ML_1 A3 // peut être n'importe quelle broche, alors faisons-les correspondre aux numéros de broche sur le blindage L289N#define ML_2 A4 // peut être n'importe quelle broche, alors faisons-les correspondre aux numéros de broche sur le bouclier L289N#define ML_ENABLE 6 // doit être une broche PWM pour le contrôle de la vitesse // réglez sa vitesse normale sur maximumconst int NORMAL_SPEED =255;void setup() { // juste après avoir appuyé sur le bouton de réinitialisation, attendez un peu pour que nous puissions l'éteindre sans endommager les composants par le biais de pics de tension delay (2000); // initialise les LED et le buzzer pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT);// pinMode(BUZZER, OUTPUT); // pas nécessaire // remettre la LED au vert digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HAUT); // définir les broches du moteur CC pinMode(MR_ENABLE, OUTPUT); // moteur droit pinMode(MR_1, OUTPUT); pinMode(MR_2, SORTIE); pinMode(ML_ENABLE, SORTIE); // moteur gauche pinMode(ML_1, OUTPUT); pinMode(ML_2, SORTIE); // initialise pinMode infrarouge (INFRA_RED, INPUT); // initialise le générateur de nombres aléatoires pour les tours aléatoires randomSeed(analogRead(0)); // dites bonjour playHello();}void loop() { // opérations normales driveForwards(NORMAL_SPEED); // met la LED sur verte digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HAUT); // vérifier les obstacles if (digitalRead(INFRA_RED) ==LOW) { //LOW signifie obstacle détecté // changer la LED en rouge digitalWrite(GREEN_LED, LOW); digitalWrite(RED_LED, HAUT); // arrêt des moteurs stopDriving(); // joue le son uh-oh playUhOh(); // vérifier le virage à gauche (500); obstacle booléenLeft =false; if (digitalRead(INFRA_RED) ==LOW) { obstacleLeft =true; } // retour au centre delay(100); tourner à droite (500); // attendez un peu, nous ne voulons pas paraître pressés delay(500); // vérifier le virage à droiteRight(500); obstacle booléenDroit =​​faux; if (digitalRead(INFRA_RED) ==LOW) { obstacleRight =true; } // retour au centre delay(100); tourner à gauche (500); // maintenant vérifier comment sortir d'ici if (obstacleLeft &&obstacleRight) { driveBackwards(NORMAL_SPEED / 3); // bip en reculant pendant 5 secondes pour (int i =0; i <5; i++) { tone(BUZZER, 1000, 500); retard(1000); } // pour éviter de rester coincé quelque part, tournez au hasard dans une direction avant de continuer le voyage randomTurn(800, 1600); } else if (obstacleLeft) { turnRight(1000); } else if (obstacleRight) { turnLeft(1000); } else { randomTurn(1000, 1800); } } // faire des trucs aléatoires pour plus d'interaction int number =random(100); // crée un nombre aléatoire entre 0 et 99 if (number ==0) { randomTurn(200,2000); }}void driveForwards(int speed) { // régler les moteurs pour qu'ils aillent dans la même direction digitalWrite(MR_1, LOW); digitalWrite(MR_2, HAUT); digitalWrite(ML_1, HAUT); digitalWrite(ML_2, LOW); setSpeed(speed);}void driveBackwards(int speed) { // définit les moteurs pour qu'ils aillent dans la direction opposée digitalWrite(MR_1, HIGH); digitalWrite(MR_2, LOW); digitalWrite(ML_1, LOW); digitalWrite(ML_2, HAUT); setSpeed(speed);}void turnLeft(int duration) { // tourner à gauche en avançant avec la roue droite et en arrière avec la roue gauche digitalWrite(MR_1, HIGH); digitalWrite(MR_2, LOW); digitalWrite(ML_1, HAUT); digitalWrite(ML_2, LOW); // ralentir pour tourner setSpeed(NORMAL_SPEED / 2); retard(durée); stopDriving();}void turnRight(int duration) { // tourner à droite en reculant avec la roue droite et en avant avec la roue gauche digitalWrite(MR_1, LOW); digitalWrite(MR_2, HAUT); digitalWrite(ML_1, LOW); digitalWrite(ML_2, HAUT); // ralentir pour tourner setSpeed(NORMAL_SPEED / 2); retard(durée); stopDriving();}void stopDriving() { // désactiver toutes les broches du moteur digitalWrite(MR_1, LOW); digitalWrite(MR_2, LOW); digitalWrite(ML_1, LOW); digitalWrite(ML_2, LOW); // je ne sais pas quoi faire avec les broches ENABLE, mais cela ne fait pas de mal de les désactiver aussi, je suppose que digitalWrite(MR_ENABLE, LOW); digitalWrite(ML_ENABLE, LOW);}void setSpeed(int speed) { // la vitesse doit être comprise entre 0 et 255 speed =constrain(speed, 0, 255); // définit la vitesse pour faire tourner les moteurs sur analogWrite(MR_ENABLE, speed); analogWrite(ML_ENABLE, speed);}void randomTurn(int minimum, int maximum) { unsigned long time =millis(); durée int =aléatoire(minimum, maximum); if (temps % 2) { turnRight(duration); } else { tournerGauche(durée); }} void playHello() { tone(BUZZER, 262, 250); // joue le délai C4 (300); tonalité (BUZZER, 330, 250); // joue le délai E4 (300); tonalité (BUZZER, 392, 250); // joue le retard G4 (300); tonalité (BUZZER, 523, 500); // joue C5 delay(550);}void playUhOh() { tone(BUZZER, 523, 250); // joue le délai C5 (300); tonalité (BUZZER, 415, 500); // joue le délai Gis4 (600);} 

Lorsque vous déconnectez un moteur en marche, des pointes de tension peuvent se produire et endommager vos composants électroniques. Par conséquent, je fais attendre Wall-E pendant deux secondes avant qu'il ne fasse quoi que ce soit. Cela signifie que je peux simplement appuyer sur le bouton de réinitialisation de l'Arduino et déconnecter rapidement la batterie sans rien endommager.

Il joue une petite mélodie quand il se réveille puis se met à conduire. Lorsqu'il voit un obstacle, il s'arrête, émet un son « Uh-oh » et regarde autour de lui pour déterminer le meilleur chemin. Le type de capteur infrarouge que j'ai utilisé a une petite vis à l'arrière qui vous permet de déterminer la distance à laquelle il crée un signal. C'est pourquoi il n'y a pas de calculs de distance dans le code. (Je voulais d'abord utiliser un capteur à ultrasons, mais il ne correspond pas à ses yeux.)

Wall-E vérifie d'abord si le côté gauche est dégagé, puis si le côté droit est dégagé. Si les deux côtés sont bloqués, il recule en émettant un bip comme de la machinerie lourde sur un chantier de construction, puis tourne dans une direction aléatoire et continue. Si un seul côté est bloqué, il continue de l'autre côté. Si les deux camps sont libres, il en choisit un au hasard et continue son chemin.

J'ai essayé de lui faire faire des virages aléatoires, mais cette partie n'est pas encore tout à fait terminée. J'essaie d'utiliser la minuterie Arduino intégrée. Faites-moi savoir dans les commentaires si vous avez une idée pour l'optimiser !

Étape 2 - Le câbler

La première chose était d'intégrer le capteur infrarouge dans l'œil pour qu'il ne semble pas trop évident. Je l'ai démonté, j'ai collé une épingle Lego sur le capteur (afin que son œil puisse se déplacer de haut en bas), puis j'ai utilisé du blue-tack pour remettre les morceaux de Lego autour du capteur :

La chose la plus importante à propos des moteurs était qu'ils avaient suffisamment de couple, car la configuration des roues de Wall-E a besoin d'un peu de force pour se déplacer. J'ai dû souder des fils aux moteurs et les attacher de manière à ce qu'ils se connectent solidement au Lego. J'ai donc démonté ses roues, commandé un sac entier d'épingles Lego Technic, enveloppé de ruban de plâtre (c'est comme ça que vous l'appelez ? C'est comme du ruban adhésif souple qui peut aller sur votre peau) autour des arbres du moteur, et je les ai collés dans deux épingles qui est devenu l'essieu principal pour chaque roue. Cela a fonctionné pendant quelques minutes, mais ensuite le frottement était trop élevé pour que la colle dans le ruban tienne. Heureusement, les broches Technic ont de petites rainures sur le côté, donc le ruban avait un endroit pour se tenir, ce qu'ils ont fait avec plaisir après avoir été trempé dans de la super colle.

J'ai aussi enlevé un peu de sa poitrine pour faire passer la LED. Ensuite, j'ai connecté toutes les pièces et l'Arduino.

Le bouclier moteur juste rentrer dans son ventre :

Le schéma n'est pas très clair non plus, mais j'ai essayé de colorer les fils pour une meilleure vue d'ensemble :

Conformément à la convention, tous les fils rouges sont positifs (délivrent de l'électricité) et tous les fils noirs sont négatifs (reçoivent de l'électricité). Le fil jaune en haut à droite porte le signal du capteur infrarouge; les fils orange et vert sont pour la LED bicolore à trois broches, les fils violets sont pour indiquer au blindage du moteur dans quelle direction tourner les moteurs, et les câbles bleus indiquent au blindage du moteur à quelle vitesse les tourner.

Le bouclier moteur avait un très bon tutoriel qui le rendait facile à connecter et à utiliser. Malheureusement, la partie Fritzing n'avait pas les deux broches pour régler la vitesse, donc les câbles bleus se retrouvent au hasard sur le blindage du moteur dans le schéma.

Un autre problème auquel j'ai été confronté en collant le tout ensemble était un manque de broches de tension et de masse. Je voulais alimenter les moteurs directement à travers le blindage du moteur afin qu'ils puissent obtenir autant de puissance que possible, mais je devais d'une manière ou d'une autre alimenter l'Arduino et le capteur infrarouge en 5 V. J'ai donc fait ce que presque tout le monde sur le Web a dit que je ne devrais pas faire :j'ai connecté la sortie 5V du blindage du moteur à la broche 5V de l'Arduino en tant qu'entrée. Maintenant, avec le blindage que j'utilise, je peux être absolument sûr qu'il délivre un 5V régulé sans pointes désagréables qui pourraient endommager mon Arduino. Si vous connectez une source d'alimentation non régulée à cette broche, vous ferez probablement frire quelque chose. Je voulais d'abord utiliser la broche Vin, mais celle-ci a un mécanisme intégré qui régule tout, donc mon 5V se serait transformé en 3,8V environ, ce qui n'est pas suffisant pour que l'Arduino fonctionne correctement. Au lieu de cela, j'ai utilisé le Vin gratuit pour alimenter (!) Le capteur infrarouge avec 5V, car je n'avais pas de répartiteur de câble, et je savais qu'il y aurait aussi du 5V qui en sortirait. Ouais, ça a commencé à ressembler un peu à Frankenstein à ce stade. Mais ça a marché !

Étape 3 - Wall-E en action

Voici quelques vidéos le montrant en action :

Et là j'ai testé ce qu'il ferait s'il était coincé dans un coin :

C'était donc mon premier petit projet. Je prévois maintenant d'optimiser les connexions des câbles et peut-être d'ajouter un servomoteur pour qu'il puisse tourner la tête. Je pourrais même acheter des séparateurs et un bouclier et une carte de moteur plus petits pour que je puisse tout mettre dans son ventre.

Et alors Mur-E vécu heureusement jamais après. Le fin.

Code

  • Wall_e_control
Wall_e_controlArduino
Il s'agit du fichier de contrôle central de Wall-E. C'est basique, mais tout ce dont il a besoin pour le moment.
// Ce programme sert à contrôler le robot Wall-E Lego.// Wall-E se déplace. Lorsqu'il voit un obstacle, il s'arrête pour regarder autour de lui et choisit un autre chemin.// Arduino Nano a 21 broches qui peuvent être utilisées pour digitalRead et digitalWrite// Les broches PWM 3, 5, 6, 9, 10, 11 peuvent être utilisées pour analogWrite// les broches 0 et 1 peuvent être utilisées pour TTL// les broches 2 et 3 peuvent être utilisées pour les interruptions externes// les broches 10, 11, 12, 13 prennent en charge la communication SPI// la broche 13 peut être une LED interne// les broches 14 à 21 sont également des broches analogiques A0 à A7 et peuvent être utilisées pour analogRead#define INFRA_RED 9 // peut être n'importe quelle broche#define GREEN_LED 7 // peut être n'importe quelle broche mais nécessite une résistance, peut-être 220 Ohm - ou la broche de terre obtient 1 kOhm# define RED_LED 8 // peut être n'importe quelle broche mais nécessite une résistance, peut-être 220 Ohm - ou la broche de terre obtient 1 kOhm #define BUZZER 10 // doit être une broche PWM pour définir la fréquence, nécessite une résistance, peut-être 1 kOhm // MR est le moteur droit, ML est le moteur gauche#define MR_1 A1 // peut être n'importe quelle broche, alors faisons-les correspondre aux numéros de broche sur le bouclier L289N#define MR_2 A2 // peut être n'importe quelle broche, alors faisons-les correspondre au p en chiffres sur le blindage L289N#define MR_ENABLE 5 // doit être une broche PWM pour le contrôle de la vitesse#define ML_1 A3 // peut être n'importe quelle broche, alors faisons-les correspondre aux numéros de broche sur le blindage L289N#define ML_2 A4 // peut être n'importe quelle broche, alors faisons-les correspondre aux numéros de broche sur le bouclier L289N#define ML_ENABLE 6 // doit être une broche PWM pour le contrôle de la vitesse // réglez sa vitesse normale sur maximumconst int NORMAL_SPEED =255;void setup() { // juste après avoir appuyé sur le bouton de réinitialisation, attendez un peu pour que nous puissions l'éteindre sans endommager les composants par le biais de pics de tension delay (2000); // initialise les LED et le buzzer pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT);// pinMode(BUZZER, OUTPUT); // pas nécessaire // remettre la LED au vert digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HAUT); // définir les broches du moteur CC pinMode(MR_ENABLE, OUTPUT); // moteur droit pinMode(MR_1, OUTPUT); pinMode(MR_2, SORTIE); pinMode(ML_ENABLE, SORTIE); // moteur gauche pinMode(ML_1, OUTPUT); pinMode(ML_2, SORTIE); // initialise pinMode infrarouge (INFRA_RED, INPUT); // initialise le générateur de nombres aléatoires pour les tours aléatoires randomSeed(analogRead(0)); // dites bonjour playHello();}void loop() { // opérations normales driveForwards(NORMAL_SPEED); // met la LED sur verte digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HAUT); // vérifier les obstacles if (digitalRead(INFRA_RED) ==LOW) { //LOW signifie obstacle détecté // changer la LED en rouge digitalWrite(GREEN_LED, LOW); digitalWrite(RED_LED, HAUT); // arrêt des moteurs stopDriving(); // joue le son uh-oh playUhOh(); // vérifier le virage à gauche (500); obstacle booléenLeft =false; if (digitalRead(INFRA_RED) ==LOW) { obstacleLeft =true; } // retour au centre delay(100); tourner à droite (500); // attendez un peu, nous ne voulons pas paraître pressés delay(500); // vérifier le virage à droiteRight(500); obstacle booléenDroit =​​faux; if (digitalRead(INFRA_RED) ==LOW) { obstacleRight =true; } // retour au centre delay(100); tourner à gauche (500); // maintenant vérifier comment sortir d'ici if (obstacleLeft &&obstacleRight) { driveBackwards(NORMAL_SPEED / 3); // bip en reculant pendant 5 secondes pour (int i =0; i <5; i++) { tone(BUZZER, 1000, 500); retard(1000); } // pour éviter de rester coincé quelque part, tournez au hasard dans une direction avant de continuer le voyage randomTurn(800, 1600); } else if (obstacleLeft) { turnRight(1000); } else if (obstacleRight) { turnLeft(1000); } else { randomTurn(1000, 1800); } } // faire des trucs aléatoires pour plus d'interaction int number =random(100); // crée un nombre aléatoire entre 0 et 99 if (number ==0) { randomTurn(200,2000); } }void driveForwards(int speed) { // régler les moteurs pour qu'ils aillent dans la même direction digitalWrite(MR_1, LOW); digitalWrite(MR_2, HAUT); digitalWrite(ML_1, HAUT); digitalWrite(ML_2, LOW); setSpeed(speed);}void driveBackwards(int speed) { // définit les moteurs pour qu'ils aillent dans la direction opposée digitalWrite(MR_1, HIGH); digitalWrite(MR_2, LOW); digitalWrite(ML_1, LOW); digitalWrite(ML_2, HAUT); setSpeed(speed);}void turnLeft(int duration) { // tourner à gauche en avançant avec la roue droite et en arrière avec la roue gauche digitalWrite(MR_1, HIGH); digitalWrite(MR_2, LOW); digitalWrite(ML_1, HAUT); digitalWrite(ML_2, LOW); // ralentir pour tourner setSpeed(NORMAL_SPEED / 2); retard(durée); stopDriving();}void turnRight(int duration) { // tourner à droite en reculant avec la roue droite et en avant avec la roue gauche digitalWrite(MR_1, LOW); digitalWrite(MR_2, HAUT); digitalWrite(ML_1, LOW); digitalWrite(ML_2, HAUT); // ralentir pour tourner setSpeed(NORMAL_SPEED / 2); retard(durée); stopDriving();}void stopDriving() { // désactiver toutes les broches du moteur digitalWrite(MR_1, LOW); digitalWrite(MR_2, LOW); digitalWrite(ML_1, LOW); digitalWrite(ML_2, LOW); // je ne sais pas quoi faire avec les broches ENABLE, mais cela ne fait pas de mal de les désactiver aussi, je suppose que digitalWrite(MR_ENABLE, LOW); digitalWrite(ML_ENABLE, LOW);}void setSpeed(int speed) { // la vitesse doit être comprise entre 0 et 255 speed =constrain(speed, 0, 255); // définit la vitesse pour faire tourner les moteurs sur analogWrite(MR_ENABLE, speed); analogWrite(ML_ENABLE, speed);}void randomTurn(int minimum, int maximum) { unsigned long time =millis(); durée int =aléatoire(minimum, maximum); if (temps % 2) { turnRight(duration); } else { tournerGauche(durée); }} void playHello() { tone(BUZZER, 262, 250); // joue le délai C4 (300); tonalité (BUZZER, 330, 250); // joue le délai E4 (300); tonalité (BUZZER, 392, 250); // joue le retard G4 (300); tonalité (BUZZER, 523, 500); // joue C5 delay(550);}void playUhOh() { tone(BUZZER, 523, 250); // joue le délai C5 (300); tonalité (BUZZER, 415, 500); // joue le délai Gis4 (600);}

Schémas

Signification des couleurs de câble :
rouge =tension (positive)
noir =masse (négatif)
jaune =signal pour capteur infrarouge
orange et vert =connexions pour entrée LED rouge et verte
violet =contrôle de la direction du moteur
bleu =contrôle de la vitesse du moteur (malheureusement, la partie Fritzing n'avait pas les deux broches que mon pont moteur avait pour ces connexions, cela ressemble donc à des fils lâches pour le moment) mur-e2_3P6X71BCnP.fzz

Processus de fabrication

  1. Surveillance du CO2 avec le capteur K30
  2. Communication sourds-aveugles avec 1Sheeld/Arduino
  3. Contrôler l'accepteur de pièces avec Arduino
  4. tireur Lego automatisé
  5. Obstacles pour éviter le robot avec servomoteur
  6. Arduino avec Bluetooth pour contrôler une LED !
  7. Capteur d'empreintes digitales capacitif avec un Arduino ou ESP8266
  8. Robot suiveur de ligne
  9. Jouer avec Nextion Display