Gruppe: Diana Ismail, Jamila Abdulkarim, Sidsel Vanselow-Rasmussen

Mexineseren har solgt sin solcelle på ebay og købt en bil i stedet for

Opgavebeskrivelse

I denne opgave skal vi konstruere en autonom linje-følge robot, der kan fragte kasser rundt i et netværk bestående af sorte streger på hvid baggrund, med tydelige markeringer for opsamlings- og afleverings-steder.

Systemets opbygning

Systemet består af to linje sensorer, to DC motorer, en Arduino UNO med tilhørende motorshield, en PCB plade med 4 LED’er – alle LED’er deler samme 220 ohms modstand – og et 9V batteri.

Ved hjulene er der gearing for at have mere kontrol over køretøjets hastighed. Hjulenes størrelse er af valgt af samme årsag. Sensorernes placering har vi valgt for at give bilen den mest optimale dreje mulighed.

Bilen er bygget om et par gange for at få den mest stabile kørsel. Første iteration af bilen havde større hjul, de blev skiftet ud med nogle mindre hjul for at gøre det nemmere at justere hastigheden. Samt har vi i løbet af processen udskiftet baghjul to gange, hvorefter vi tilsidst vurderede at bilen ikke havde brug for et baghjul men blot et par legoklodser til at støtte bilen.

Motorshield

Vi benytter en Arduino Motor Shield som er baseret på L298, som er en dual-bridge motor driver. Den har flere h-broer indbygget. En h-bro er en konstruktion af 4 transistorer som muliggør at man kan drive en eller anden belastning både i positiv og i negativ retning. Det betyder at vi kan bruge motor shieldet til at køre med DC motorer og styrer hastigheden og retningen af motoren.

LED’erne

De fire LED’er indikerer hvilken kommando bilen udfører. LED-H lyser når bilen drejer til højre, LED-V lyser når bilen drejer til venstre, LED-F lyser når bilen kører frem, LED-B lyser når bilen kører baglæns og ved u-turn lyser både LED-B og LED-F.

Udfordringer med hardware

Vi har under udarbejdelsen af bilen, oplevet problemer med sensorerne som ikke var fastgjort nok. Sensorerne bevægede sig dermed fra at røre overfladen, til være alt for langt væk.   Dette betød at vi under test, fik alt for afvigende værdier, i forhold til sort/ lyst og derfor kunne sensorerne ikke registrere forskellen på sort/hvid hurtigt nok. Dette problem blev løst ved at benytte nogen hårde ledninger som blev viklet rundt om sensorerne og fastgjort på lego.

Fritzing diagram af Mexinesern – half throttle

Robottens opførsel og kode

Robottens opførsel

Robotten har 5 overordnede opførsler; followLine der lader robotten køre ligeud, turnLeft og turnRight som får robotten til at dreje til venstre eller højre, uTurn som får robotten til at dreje 180° og goBack som får robotten til at bakke.

Flow diagram

Transition conditions

Vores transition conditions er lavet på baggrund af, at robotten skal udføre de adskillige kommandoer når den kommer til sorte krydser. Herved kan vi bruge de sorte streger til at orientere robotten mere nøjagtigt end hvis man f.eks. fortalte den at køre/dreje i x sekunder i stedet for, da den kunne køre/dreje for meget eller for lidt i den givne tid, mens den vil køre/dreje så meget som den skal hvis den orienterer sig på stregerne.

Kode

Vi bruger en command list til at holde styr på robottens kommandoer og hvornår den skal gøre hvad. Dette er gjort i form af en liste med int’er hvor hver int står for en bestemt kommando.

int commandList[] = {0, 0, 0, 1, 0, 0, 3, 0, 2, 0, 3, 0, 0, 4, 2, 0, 0, 1, 0, 2, 0, 3, 0, 0, 1, 0, 3, 0};

Dertil har vi de 5 kommandoer som robotten kan gøre.

I followLine() er der et while loop som kører så længe at en boolean ”followNow” er true, samt et while loop der der kører når den er false.

Når den er false kører robotten fremad indtil at begge linje sensorer ser hvidt hvorefter den sætter ”followNow” til true. Dette gøres for at være sikker på at robotten kommer over et kryds og ikke bliver stående mit på det sorte felt.

Når den er true kører robotten fremad og tjekker i en række if statements hvad farve hver sensor ser. Når en sensor ser hvidt, så kører dens korresponderende motor fremad, mens motoren stopper hvis sensoren ser sort. Hvis begge linje sensorer ser sort så tæller den en op i int’en ”counter” for at komme videre i vores commandList og sætter ”followNow” til false.

void followLine() {
  Serial.println("follow line");

  while (followNow == false){
    leftSensorValue = analogRead(leftSensor);
    rightSensorValue = analogRead(rightSensor);

    digitalWrite(dir_A, LOW);
    digitalWrite(dir_B, HIGH);

    analogWrite(PWM_A, 90);
    analogWrite(PWM_B, 90);
    
    if (rightSensorValue < 400 || leftSensorValue < 400) {
      followNow = true;
    }
  }
  while (followNow == true){
    leftSensorValue = analogRead(leftSensor);
    rightSensorValue = analogRead(rightSensor);

    digitalWrite(dir_A, LOW);
    digitalWrite(dir_B, HIGH);

    if (leftSensorValue < 400) {
      analogWrite(PWM_A, 90);
    }
    else {
      analogWrite(PWM_A, 0);
    }

    if (rightSensorValue < 400) {
      analogWrite(PWM_B, 90);
    }
    else {
      analogWrite(PWM_B, 0);
    }

    //if both sensors black, go to next state
    if (rightSensorValue > 600 && leftSensorValue > 600) {
      counter++;
      followNow = false;
    }
  }
}

I turnRight() sætter robotten den venstre motor til at køre mens den højre er stoppet. Den tjekker herefter i et if statement hvilken værdi en int ”blackCounter” har. Hvis den er mindre end 1 tjekker den i indnu et if statement om den venstre sensor ser sort. Hvis den gør sætter den en bool ”hasBeenBlack” til true. Herefter tjekker den i en else-if om den venstre sensor er hvid og om ”hasBeenBlack” er true, hvis ja så tæller den en op i ”blackCounter” og sætter ”hasBeenBlack” til false.

Hvis ”blackCounter” er 1 eller mere så sætter den ”blackCounter” til 0 og tæller en op i ”counter”.

void turnRight() {
  Serial.println("turn right");
  Serial.println(blackCounter);
  Serial.println(hasBeenBlack);

  leftSensorValue = analogRead(leftSensor);
  rightSensorValue = analogRead(rightSensor);

  digitalWrite(dir_A, LOW);
  digitalWrite(dir_B, HIGH);

  analogWrite(PWM_B, 0);
  analogWrite(PWM_A, 90);

  //turn indtil venstre dreje sensor har set sort 1 gang
  if ( blackCounter < 1 ) {
    if (leftSensorValue > 600) {
      hasBeenBlack = true;
    }
    else if (leftSensorValue < 400 && hasBeenBlack == true) {
      hasBeenBlack = false;
      blackCounter++;
    }
  } else if (blackCounter >= 1 ) {
    blackCounter = 0;
    counter++;
  }
}

uTurn() gør præcis det samme som turnRight() bare hvor ”blackCounter” skal være 2 eller derover før den sætter ”blackCounter” til 0 og tæller 1 op i ”counter”.

void uTurn() {
  Serial.println("uturn");

  leftSensorValue = analogRead(leftSensor);
  rightSensorValue = analogRead(rightSensor);

  digitalWrite(dir_A, HIGH);
  digitalWrite(dir_B, HIGH);

  analogWrite(PWM_B, 90);
  analogWrite(PWM_A, 90);

  //turn indtil venstre dreje sensor har set sort 2 gange
  if ( blackCounter < 2 ) {
    if (leftSensorValue > 600) {
      hasBeenBlack = true;
    }
    else if (leftSensorValue < 400 && hasBeenBlack == true) {
      hasBeenBlack = false;
      blackCounter++;
    }
  } else if (blackCounter >= 2 ) {
    blackCounter = 0;
    counter++;
  }
}

I goBack() skifter robotten først motorernes retning så den kører baglæns. Herefter tjekker den i et while loop om en bool”backNow” er true. Hvis den er, så tjekker den i et if statement om begge linje sensorer ser hvidt, hvis de gør så sætter den motorerne til at køre. Hvis de ikke gør så tjekker den om en af linje sensorerne ser sort og sætter derefter den korresponderende motor til at køre lidt mindre end halv hastighed.

Herefter tjekker den i et nyt if statement om vores ”blackCounter” er mindre end 2. Hvis den er tjekker den i endnu et if statement om begge linje sensorer ser sort. Hvis de gør sætter den ”hasBeenBlack” til true. Hvis ikke tjekker den om den højre sensor ser hvid og ”hasBeenBlack” er true og hvis ja, sætter den ”hasBeenBlack” til false og tæller en op i ”blackCounter”. Hvis nej tjekker den det samme bare med venstre sensor.

Hvis ”blackCounter” derimod er 2 eller derover, så sætter den ”blackCounter” til 0 og ”backNow” til false.

Efter alt det sætter den motorerne til at køre fremad.

Hvis vores ”backNow” bool I stedet for er false, så opfanger et andet while loop det. I dette while loop sætter den motorerne til at køre og tjekker herefter et if statement om begge sensorer ser hvidt. Hvis de gør så tæller den en op i ”counter” og sætter ”backNow” tilbage til true.

void goBack() {
  Serial.println("go back");

  while (backNow == true){
    leftSensorValue = analogRead(leftSensor);
    rightSensorValue = analogRead(rightSensor);

    digitalWrite(dir_A, HIGH);
    digitalWrite(dir_B, LOW);

    if (leftSensorValue < 400 && rightSensorValue < 400){
      analogWrite(PWM_A, 90);
      analogWrite(PWM_B, 90);
    } else if (leftSensorValue < 600) {
      analogWrite(PWM_B, 40);
    } else if (rightSensorValue < 600) {
      analogWrite(PWM_A, 40);
    }

    if ( blackCounter < 2 ) {
      if (rightSensorValue > 600 && leftSensorValue > 600) {
        hasBeenBlack = true;
      }
      else if (rightSensorValue < 400 && hasBeenBlack == true) {
        hasBeenBlack = false;
        blackCounter++;
      }
      else if (leftSensorValue < 400 && hasBeenBlack == true){
        hasBeenBlack = false;
        blackCounter++;
      }
    } else if (blackCounter >= 2 ) {
      blackCounter = 0;
      backNow = false;
    }
    analogWrite(PWM_A, 90);
    analogWrite(PWM_B, 90);
  }
  while (backNow == false){
    leftSensorValue = analogRead(leftSensor);
    rightSensorValue = analogRead(rightSensor);

    digitalWrite(dir_A, HIGH);
    digitalWrite(dir_B, LOW);

    analogWrite(PWM_A, 90);
    analogWrite(PWM_B, 90);
    
    if (rightSensorValue < 400 || leftSensorValue < 400) {
      counter++;
      backNow = true;
    }
  }
}

Udfordringer i koden

Koden har været temmelig overkommelig når først man satte sig ind i den tankegang som robotten skulle have. Det sværeste ved koden har været at få goBack() funktionen til at virke til en tilfredsstillende grad, da linje sensorerne jo pludselig sidder bagved motorerne når robotten bakker og det derved kan være et problem at reagerer ordentligt på linje sensorernes feedback når denne feedback jo først kommer efter at motorerne har drejet.

Konklusion

Banen der skal udførers

Mexineseren fuldfører de obligatoriske baner, A og B, rimelig stabilt og uden for store problemer. Forbedringer kunne komme i form af en optimeret goBack funktion, da den kan få lidt problemer hvis den skal bakke en længerer distance. Derudover kan man få robotten til at gennemfører de resterende baner.

Mexineseren fuldfører bane A & B

Leave a Reply