POPG01 – Porteføljeopgave 1 → Linje følger robot med LEGO og Arduino

Robotten IB

Gruppe 5: Nanna Bunkenborg, Samah A. Ajjawi, Stine Schmidt Nielsen & Didde Marie Hellestrup

IB1 IB2

Robottens opbygning

Baghjulene er de største og er placeret i midten af robotten. Samtidig er batterierne også placeret oven over baghjulene for bedst muligt at bære vægten. Forhjulene er mindre og er kun af plastik for at der er mindst mulig modstand og for at holde en højere hastighed. Baghjulene er smalle for at der er mindst mulig kontaktflade med underlaget. Vi har valgt denne type hjul for at sikre en høj fart og så lidt friktion som muligt, således at robotten også let kunne dreje.

Til gearing har vi valgt to forskellige størrelser af tandhjul – det mindste og det største. Vi har valgt at sætte det allermindste tandhjul på motoren og det største tandhjul på selve hjulet. Dette giver en gearing med faktor fem, som væsentligt reducerer robottens hastighed og får den til at køre mere præcist.

Robotten er baghjulstrukket. Motorerne er placeret bagest på robotten, bagved baghjulene. Dette har vi valgt at gøre for at give mest mulig fremdrift.

Der er benyttet to lyssensorer, som er placeret på robottens front, pegende nedad for at registrere underlaget. De to sensorer er placeret med ca. 5 cm mellemrum og så tæt på underlaget som muligt for at sikre en præcis aflæsning. Desuden er der benyttet en ultralydssonar til at registrere eventuelle forhindringer. Denne er også placeret på robottens front, men pegende fremad.

Vi har bygget vores robot om flere gange, fordi den først blev for høj og klodset, og derefter havde vi problemer med at finde passende forhjul. Selv da sensorerne var påsat, modificerede vi robottens udseende og opbygning. Vi justerede en smule på lyssensorerne, fordi de til at starte med var placeret for langt fra hinanden, så robotten ikke kunne nå at ændre retning efter sensorværdierne. Dette kunne dog justeres ved blot at flytte ledningerne.

Robottens hardware

Diagramtegning:

robotDiagram

Udregning af modstande til lysdioderne:

For at lysdioden i vores infrarøde lyssensor ikke får for meget strøm, har vi sat en modstand ind. Denne modstand har vi udregnet vha. Ohms lov:

U=R*I

Systemets spænding = 5V
Diodens max spænding = 1,25V (datablad)
U = 5V – 1,25V = 3,75V

Diodens strøm er 5mA = 0,05A (datablad)

R = 3,75V / 0,05A = 75 Ω

Derfor har vi indsat modstande på 75 Ω ind ved begge lyssensorer.

Billede med beskrivelser:

ting-tegning

Problemer med hardwaren undervejs

Vi oplevede et problem, da den ene motor pludselig havde mindre kraft end den anden. Vi byttede om på strømforsyningen til motorerne for at undersøge om det var selve motoren, der var noget galt med, eller om det var et andet problem. Det viste sig, at det var selve motorshieldet der var noget galt med, og vi kunne således erstatte dette med et nyt.

Vi oplevede også et andet problem i forhold til ultralydssonaren. Den kunne ikke registrere forhindringen på banen, og vi fandt ud af, at det var fordi sonaren var placeret for højt på robotten. Dette kunne vi desværre ikke ændre på da ledningen allerede var loddet fast, så vi blev nødt til at lave en forhøjning på forhindringen i stedet.

Endvidere oplevede vi også at batteritilslutningen brændte af og den måtte dermed erstattes af en ny.

Opbyggelsen af vores robot har nogle flere gange givet os problemer, da vores lego ved især vores motorer tit faldt hurtigt fra hinanden, samtidig har vi bygget vores robot om og om igen, da i ikke var helt tilfredse med resultatet af, hvordan den endte med at se ud. Igennem testningen af vores robot fandt vi ud af at batterierne var blevet placeret et besværligt sted, da de tit skulle på og af. Det ville helt sikkert have fungeret bedre, hvis de var sat et sted, hvor der ikke ville være noget rundt om, det ville helt sikkert have fungeret bedre og der ville ikke have været besværligheder med robotten igennem testningen.

Robottens opførsel

Robotten kan følge en sort streg på hvidt underlag. Hvis den sorte streg indgår i et kryds, kører robotten stadig ligeud. Hvis der er et brud i den lige linje kører robotten også stadig ligeud til den finder linjen igen. Derudover kan robotten registrere om der er en forhindring foran den, undvige og finde linjen igen.

Hvis en af IR-sensorerne registrerer lysintensiteten med en værdi over 700, er underlaget sort. Dette vil få den pågældende sides motor til at bakke, hvilket vil få robotten til at dreje væk fra den sorte linje. Det samme gælder for den modsatte sensor og tilhørende motor.

Flow-chart diagram for robottens opførsel

Flow chart - IB

Koden

#include <Wire.h>

// Variabler:
int motorADir = 12;
int motorBDir = 13;
int motorAPWM = 3;
int motorBPWM = 11;

int sensorPinH = 2;
int sensorPinV = 3;
int sensorValueH = 0;
int sensorValueV = 0;

int forhindring = 0;

int reading = 0; // Sonar værdier

int state = 0;   // Starter med at være i state 0

void setup()
{
  pinMode(motorADir, OUTPUT);
  pinMode(motorBDir, OUTPUT);
  pinMode(motorAPWM, OUTPUT);
  pinMode(motorBPWM, OUTPUT);

  Wire.begin();                // join i2c bus (address optional for master)
  Serial.begin(9600);          // start serial communication at 9600bps
}

void loop() {
  //
  sensorValueH = analogRead(sensorPinH);
  sensorValueV = analogRead(sensorPinV);

  // Sonar aflæsning
  // step 1: instruct sensor to read echoes
  Wire.beginTransmission(112); // transmit to device #112 (0x70) 
                               // the address specified in the datasheet is 224 (0xE0) 
                               // but i2c adressing uses the high 7 bits so it's 112
  Wire.write(byte(0x00));      // sets register pointer to the command register (0x00)  
  Wire.write(byte(0x50));      // command sensor to measure in "inches" (0x50)
  Wire.endTransmission();      // stop transmitting

  // step 2: wait for readings to happen
  delay(70);                   // datasheet suggests at least 65 milliseconds

  // step 3: instruct sensor to return a particular echo reading
  Wire.beginTransmission(112); // transmit to device #112
  Wire.write(byte(0x02));      // sets register pointer to echo #1 register (0x02)
  Wire.endTransmission();      // stop transmitting

  // step 4: request reading from sensor
  Wire.requestFrom(112, 2);    // request 2 bytes from slave device #112

  // step 5: receive reading from sensor
  if(2 <= Wire.available())    // if two bytes were received
  {
    reading = Wire.read();     // receive high byte (overwrites previous reading)
    reading = reading << 8;    // shift high byte to be high 8 bits
    reading |= Wire.read();    // receive low byte as lower 8 bits
    Serial.println(reading);   // print the reading
  }

  // Robotten kører med to states
  // state 1: Linjeføring
  // state 2: Unvigelse af objekt
  switch (state) {
    // Linjeføring
    case 0:
    // Hvis begge sensorer opfatter værdier under 700 (hvid), skal begge motorer køre ligeud med samme hastighed
      if (sensorValueH < 700 && sensorValueV < 700) {
        digitalWrite(motorADir, LOW);
        digitalWrite(motorBDir, LOW);
        analogWrite(motorAPWM, 40);
        analogWrite(motorBPWM, 40);
      } 
      // Ellers hvis begge sensorer opfatter værdier over 700 (sort), skal begge motorer køre ligeud med samme hastighed
      else if (sensorValueH > 700 && sensorValueV > 700) {
        digitalWrite(motorADir, LOW);
        digitalWrite(motorBDir, LOW);
        analogWrite(motorAPWM, 40);
        analogWrite(motorBPWM, 40);
      }
      // Ellers hvis venstre sensor opfatter en værdi over 700 (sort), skal venstre motor køre bagud (robotten drejer til venstre)
      else if (sensorValueH < 700 && sensorValueV >700) {
        digitalWrite(motorADir, LOW);
        digitalWrite(motorBDir, HIGH);
        analogWrite(motorAPWM, 50);
        analogWrite(motorBPWM, 50);
      }
      // Ellers hvis højre sensor opfatter en værdi over 700 (sort), skal højre motor køre bagud (robotten drejer til højre)
      else if (sensorValueH > 700 && sensorValueV < 700) {
        digitalWrite(motorADir, HIGH);
        digitalWrite(motorBDir, LOW);
        analogWrite(motorAPWM, 50);
        analogWrite(motorBPWM, 50);
      }
      // Hvis en forhindring registreres på en afstand under 8 inches og denne registreres 4 gange, skifter robotten til state 1
      if (reading < 8) {
        forhindring = forhindring + 1;
        if (forhindring > 4) {
          forhindring = 0;
          state = 1;
        }
      }
      break;

    case 1:
    // Undvigelse af objekt
      // Robotten drejer blødt til venstre
      digitalWrite(motorADir, LOW);
      digitalWrite(motorBDir, HIGH);
      analogWrite(motorAPWM, 35);
      analogWrite(motorBPWM, 35);
      delay(1000);
      // Robotten kører ligeud
      digitalWrite(motorADir, LOW);
      digitalWrite(motorBDir, LOW);
      analogWrite(motorAPWM, 50);
      analogWrite(motorBPWM, 50);
      delay(2500);
      // Robotten drejer skarpt til højre
      digitalWrite(motorADir, HIGH);
      digitalWrite(motorBDir, LOW);
      analogWrite(motorAPWM, 60);
      analogWrite(motorBPWM, 60);
      delay(1000);
      // Robotten kører ligeud
      digitalWrite(motorADir, LOW);
      digitalWrite(motorBDir, LOW);
      analogWrite(motorAPWM, 30);
      analogWrite(motorBPWM, 30);

      // Robottens venstre sensor søger efter værdier over 800 (sort), når det findes skiftes der til state 0
      while(analogRead(sensorPinV) < 800){};
      state = 0;
      break;
  }
}

Hvilke udfordringer har der været ift. til at få koden til at virke?

Meget af vores endelige kode, var også det første kode vi forsøgte os med. Men på daværende tidspunkt kunne vi ikke få robotten til at opføre sig som den skulle og derfor prøvede vi med en anden tilgangsvinkel. Da vi heller ikke kunne få dette til at virke, gik vi tilbage og forsøgte os med en opbygning af if og if else statements, hvilket nu virkede. Grunden til at det ikke virkede for os første gang, var højst sandsynligvis at vi ikke havde fået gear på vores robot på daværende tidspunkt.

Den anden kode vi forsøgte os med, var bygget op efter at robottens bevægelser skulle være mere afrundede. Derfor forsøgte vi at skrive en ligning som gjorde at jo højere værdier (mørkere) den højre infrarøde sensor registrerede, des langsommere skulle den højre motor køre. På den måde skulle vi i teorien have fået en robot der ikke hakkede når den drejede væk fra den mørke streg og dermed en robot der ville få en “korte” vej rundt på banen.

int motorSpH = (1000 - sensorValueH)/20;

int motorSpV = (1000 - sensorValueV)/20;
  • Hvis den infrarødesensor opfatter en værdi på 800 (sort), vil hastigheden blive 10
  • Hvis den infrarødesensor opfatter en værdi på 40 (hvid), vil hastigheden blive 48

Vi var igennem mange forskellige variationer af den, men det lykkedes os ikke at finde den rigtige.

Vi oplevede også flere problemer ift. ultralydssensoren. Bla. oplevede vi at den opfattede objekter der var langt væk, på trods af at den ikke var programmeret til det. Dette løste vi ved at fortælle den, at først når den havde set en forhindring 4 gange, skulle den udføre programmet for undvigelse af et objekt.

Konklusion

Robotten løser alle opgaver i forhold til opgaveformuleringen, den følger stregen rundt vha. autonom opførsel. Når der opstår steder med et kryds, eller steder med et “hul” i stregen, fortsætter den ligeud. Den undviger også, hvis den spotter et objekt på dens vej.

Den hurtigste tid vi fik, blev ca. 51 sek.

Evt. forbedringer

Robotten kører ikke ret hurtigt. For at forbedre dette skulle selve opbygningen af robotten være anderledes, da den stadig er for tung og for høj.

Desuden er robotten temmelig skrøbelig og går let fra hinanden. Dette kan dog nemt løses ved at sætte nogle stabiliserende, vertikale klodser på robotten.

Derudover kunne den forbedres ved at flytte ultralydssonaren, idet placeringen er for høj og den kan dermed ikke så forhindringen på banen uden at forhindringen bliver højere. For at flytte sonaren ville det kræve at ledningerne skulle loddes om og længere ledninger skulle loddes på.

Både lyssensorer og ultralydssonar er meget følsomme overfor omgivelserne. For at forbedre dette kunne der sættes en form for afskærmning på robotten, så lyssensorerne befandt sig i et mere konstant miljø. Ligeledes kunne der laves en afskærmning rundt om sonaren, så denne ikke lige så let blev påvirket af omgivelserne.

Ift. koden, ville det have været bedre hvis robotten havde fået en mindre hakkende opførsel. Dette kunne løses ved hjælp af en ligning der ville give robotten en blødere og dermed “kortere” linje.

Leave a Reply