Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Bouw een LEGO Wall-E Robot met Arduino Nano: Stap-voor-stap Gids

Onderdelen en benodigdheden

  • LEGO Wall-E – 1 stuk (tweedehands, niet meer in productie)
  • Arduino Nano R3 – 1 stuk
  • DC-motor (generiek) – 2 stuks
  • L298N Dual Motor Controller – 1 stuk
  • Bi-kleur LED – 1 stuk (3 pinnen)
  • Infrarood sensor – 1 stuk
  • Buzzer – 1 stuk (verschillende tonen mogelijk)
  • 9V batterij – 1 stuk
  • Weerstand 330 ohm – 3 stuks
  • Jumper wires (generiek) – 20 stuks

Benodigde tools en machines

  • Solderbout (generiek)

Apps en online diensten

  • Arduino IDE

Over dit project

Iedereen kent de film Wall-E (en als niet: ga nu kijken!) en de gele held die probeert de aarde op te schonen. In dit project gebruikte ik een LEGO-versie van ons kleine vriend en leerde hem obstakels te vermijden. Dit was mijn eerste project en een geweldige leerervaring voor de basis van elektronica.

Stap 1 - De Code

Als softwareontwikkler dacht ik na over wat ik wilde dat hij deed en begon met de code.

// Dit programma controleert de Wall-E LEGO robot.
// Wall-E rijdt rond. Als hij een obstakel ziet, stopt hij, kijkt om zich heen en kiest een ander pad.
// Arduino Nano heeft 21 pinnen voor digitalRead/digitalWrite
// PWM pinnen 3, 5, 6, 9, 10, 11 voor analogWrite
// Pinnen 0, 1 voor TTL; 2, 3 voor externe interrupts
// Pinnen 10, 11, 12, 13 voor SPI; pin 13 interne LED
// Pinnen 14-21 zijn analoge pinnen A0-A7 voor analogRead

#define INFRA_RED 9
#define GREEN_LED 7 // met weerstand ~220 Ohm
#define RED_LED 8   // met weerstand ~220 Ohm
#define BUZZER 10   // PWM pin voor frequentie, weerstand ~1k Ohm

// MR = rechter motor, ML = linker motor
#define MR_1 A1
#define MR_2 A2
#define MR_ENABLE 5 // PWM voor snelheid
#define ML_1 A3
#define ML_2 A4
#define ML_ENABLE 6 // PWM voor snelheid

const int NORMAL_SPEED = 255;

void setup() {
  delay(2000); // Wacht na reset om spanningspieken te voorkomen bij loskoppelen batterij
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  // pinMode(BUZZER, OUTPUT); // niet noodzakelijk
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  
  pinMode(MR_ENABLE, OUTPUT);
  pinMode(MR_1, OUTPUT);
  pinMode(MR_2, OUTPUT);
  pinMode(ML_ENABLE, OUTPUT);
  pinMode(ML_1, OUTPUT);
  pinMode(ML_2, OUTPUT);
  
  pinMode(INFRA_RED, INPUT);
  randomSeed(analogRead(0));
  playHello();
}

void loop() {
  driveForwards(NORMAL_SPEED);
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  
  if (digitalRead(INFRA_RED) == LOW) { // LOW = obstakel gedetecteerd
    digitalWrite(GREEN_LED, LOW);
    digitalWrite(RED_LED, HIGH);
    stopDriving();
    playUhOh();
    
    // Check links
    turnLeft(500);
    boolean obstacleLeft = false;
    if (digitalRead(INFRA_RED) == LOW) obstacleLeft = true;
    
    // Terug naar centrum
    delay(100);
    turnRight(500);
    delay(500);
    
    // Check rechts
    turnRight(500);
    boolean obstacleRight = false;
    if (digitalRead(INFRA_RED) == LOW) obstacleRight = true;
    
    // Terug naar centrum
    delay(100);
    turnLeft(500);
    
    // Beslis hoe te ontsnappen
    if (obstacleLeft && obstacleRight) {
      driveBackwards(NORMAL_SPEED / 3);
      for (int i = 0; i < 5; i++) {
        tone(BUZZER, 1000, 500);
        delay(1000);
      }
      randomTurn(800, 1600);
    } else if (obstacleLeft) {
      turnRight(1000);
    } else if (obstacleRight) {
      turnLeft(1000);
    } else {
      randomTurn(1000, 1800);
    }
  }
  
  // Willekeurige gedragingen voor meer interactie
  int number = random(100);
  if (number == 0) {
    randomTurn(200, 2000);
  }
}

// Motor control functies...
void driveForwards(int speed) {
  digitalWrite(MR_1, LOW); digitalWrite(MR_2, HIGH);
  digitalWrite(ML_1, HIGH); digitalWrite(ML_2, LOW);
  setSpeed(speed);
}

void driveBackwards(int speed) {
  digitalWrite(MR_1, HIGH); digitalWrite(MR_2, LOW);
  digitalWrite(ML_1, LOW); digitalWrite(ML_2, HIGH);
  setSpeed(speed);
}

void turnLeft(int duration) {
  digitalWrite(MR_1, HIGH); digitalWrite(MR_2, LOW);
  digitalWrite(ML_1, HIGH); digitalWrite(ML_2, LOW);
  setSpeed(NORMAL_SPEED / 2);
  delay(duration);
  stopDriving();
}

void turnRight(int duration) {
  digitalWrite(MR_1, LOW); digitalWrite(MR_2, HIGH);
  digitalWrite(ML_1, LOW); digitalWrite(ML_2, HIGH);
  setSpeed(NORMAL_SPEED / 2);
  delay(duration);
  stopDriving();
}

void stopDriving() {
  digitalWrite(MR_1, LOW); digitalWrite(MR_2, LOW);
  digitalWrite(ML_1, LOW); digitalWrite(ML_2, LOW);
  digitalWrite(MR_ENABLE, LOW); digitalWrite(ML_ENABLE, LOW);
}

void setSpeed(int speed) {
  speed = constrain(speed, 0, 255);
  analogWrite(MR_ENABLE, speed);
  analogWrite(ML_ENABLE, speed);
}

void randomTurn(int minimum, int maximum) {
  unsigned long time = millis();
  int duration = random(minimum, maximum);
  if (time % 2) turnRight(duration);
  else turnLeft(duration);
}

void playHello() {
  tone(BUZZER, 262, 250); delay(300); // C4
  tone(BUZZER, 330, 250); delay(300); // E4
  tone(BUZZER, 392, 250); delay(300); // G4
  tone(BUZZER, 523, 500); delay(550); // C5
}

void playUhOh() {
  tone(BUZZER, 523, 250); delay(300); // C5
  tone(BUZZER, 415, 500); delay(600); // Gis4
}

Wanneer je een draaiende motor loskoppelt, kunnen spanningspieken optreden die je electronica beschadigen. Daarom laat ik Wall-E 2 seconden wachten na reset. Ik kan de resetknop indrukken en snel de batterij loskoppelen zonder schade.

Hij speelt een melodie bij opstarten en begint te rijden. Bij een obstakel stopt hij, speelt "Uh-oh", en kijkt om zich heen. De infraroodsensor heeft een schroefje achterin voor de detectieafstand. Daarom geen afstandsberekeningen in de code. (Ik wilde eerst een ultrasone sensor, maar die paste niet in zijn ogen.)

Wall-E checkt eerst links, dan rechts. Als beide geblokkeerd: achteruit met piepgeluid als bouwmachines, dan willekeurige draai en verder. Alleen één kant geblokkeerd? Ga de andere kant op. Beide vrij? Willekeurig kiezen.

Willekeurige draaien is nog niet af. Ik probeer de ingebouwde Arduino-timer. Ideëen? Laat het in de comments weten!

Stap 2 - Hem opknopen

Eerst de infraroodsensor in het oog verwerken zodat het niet opvalt. Ik haalde hem uit elkaar, lijmde een LEGO-pin aan de sensor (zijn oog kan omhoog/omlaag) en gebruikte blue-tack om de LEGO-stukken terug te zetten:

Bouw een LEGO Wall-E Robot met Arduino Nano: Stap-voor-stap Gids

De motoren moesten voldoende kracht hebben. Ik soldeerde draden aan de motoren en bevestigde ze stevig aan LEGO. Wielen afgehald, zak LEGO Technic-pins besteld, gipsband om de motorassen gewikkeld, in twee pins gestoken die de hoofdas worden. Werkte enkele minuten, dan was wrijving te groot. Gelukkig hebben Technic-pins gaatjes aan de zijkant, dus de band hield na in superlijm te dopen.

Bouw een LEGO Wall-E Robot met Arduino Nano: Stap-voor-stap Gids

Ik haalde een beetje van zijn borstkaf af voor de LED. Alles aangesloten op de Arduino.

Bouw een LEGO Wall-E Robot met Arduino Nano: Stap-voor-stap Gids

De motor shield past net in zijn buik:

Bouw een LEGO Wall-E Robot met Arduino Nano: Stap-voor-stap Gids

Schema met kleurencodering voor overzicht:

Bouw een LEGO Wall-E Robot met Arduino Nano: Stap-voor-stap Gids

Volgens conventie: rood = plus, zwart = min. Geel (rechtsboven) = infrarood signaal. Oranje/groen = bi-kleur LED. Paars = motorrichting. Blauw = motorsnelheid (Fritzing-deel had geen pinnen voor snelheid, dus losse draden in schema).

Probleem: tekort aan 5V en GND pinnen. Ik wilde motoren direct via shield voeden voor maximale kracht, maar moest ook 5V aan Arduino en infraroodsensor geven. Ik deed wat het internet afraadt: 5V-uitgang van motor shield aangesloten op 5V-pin van Arduino als invoer. Met mijn shield is dit een geregelde 5V zonder pieken. Ongeregelde bron op die pin = Arduino kapot. Vin-pin regelt af (5V wordt ~3.8V, ontoereikend). Dus Vin gebruikte ik voor de infraroodsensor (weet dat er 5V uitkomt). Voelde als Frankenstein, maar het werkt!

Stap 3 - Wall-E in Actie

Video's van hem in actie (zie originele projectpagina). Getest in een hoek:

Dit was mijn eerste project. Plannen: kabelverbeteringen, servo voor kopdraaien, splitters en kleinere shield/bord zodat alles in zijn buik past.

En zo leefde Wall-E gelukkig tot aan het einde van zijn dagen. Het einde.

Code

Wall_e_control (Arduino)

Centrale besturingscode. Basis, maar alles wat hij nu nodig heeft. (Zie bovenstaande volledige code in Stap 1)

Schema's

Kabelkleuren betekenis:
rood = spanning (positief)
zwart = ground (negatief)
geel = signaal infraroodsensor
oranje/groen = rode/groene LED ingangen
paars = motorrichting
blauw = motorsnelheid (Fritzing-deel had geen pinnen voor snelheid, dus losse draden in schema)
wall-e2_3P6X71BCnP.fzz

Productieproces

  1. K30 CO2-sensor: Real-time binnenluchtkwaliteitmonitoring met Arduino
  2. Communicatie voor doofblinden vergemakkelijken met 1Sheeld en Arduino
  3. Slimme spaarpot bouwen: Muntenacceptor besturen met Arduino Nano
  4. Bouw een Geautomatiseerde LEGO Star Wars Kanon met Arduino Uno
  5. Servo-gestuurde obstakelvermijdende robot: Bouw met Arduino & HC-SR04
  6. Een LED bedienen via Bluetooth met Arduino – Eenvoudige DIY Handleiding
  7. Een DFRobot Capacitieve Vingerafdruksensor integreren met Arduino of ESP8266
  8. Bouw Een Autonome Lijnvolgende Robot Met Arduino UNO
  9. Interactief Nextion HMI-weerstation met Arduino Mega en sensoren
  10. Arduino-gebaseerde 6-DoF Robotarm Gestoeerd met Wii Nunchuk
  11. Arduino & MPU6050: Precieze Servomotor Besturing met SG90 & MG996R