POPG02 – Porteføljeopgave 2

Navn på robotten

Monster Tank!

Navn på gruppemedlemmerne / forfatterne

Ling Siu Chang, Katja Nanche Aagaard Nordin og Peter Gissel Christensen

Video af testkørsel

MVI_0148

Bedste konkurrence tid (af de 3 forsøg)

Test tid: 1.32 min

Bedste konkurrence tid: 0.49 min

Opbygning af hardware – brug fritzing

*IR – sensor er ikke dem som er på billede.

På ovenstående billede ses opbygningen af vores robots hardware, som er opbygget af en Arduino Uno, Motor-shield, Arduino Breadboard, otte batterier, en switch, to LEGO motorer, to linje sensorer og en sonar sensor.

Opbygning af robot i Lego – brug Lego digital designer

Basis opbygningen af robotten er lavet ud fra LEGO Mindstorm – Robotics Invention System 2.0. Hvor vi har modificeret designet, for at indkludere Arduino Uno, Motor-shield, Arduino Breadboard, otte batterier, en switch, to LEGO motorer, to linje sensorer og en sonar sensor. Derudover har vi valgt at bruge bælter, da det giver øget kontrol og dermed mulighed for at præcisere vores sving. Og vi har valgt at sætte linje sensorerne forrest nederst på robotten for at komme tættere på den sorte streg. Sonar sensoren sidder på højre side, så den er på samme side som muren. Derudover er den placeret forrest, så den opfanger mere data, så den justeres bedre efter muren. Batterierne er placeret ovenpå bælterne for at vægten fra batterierne presser ned på bælterne så de er stabiliseret. Motorerne er tunge og sidder derfor i midten af robotten, så vægten er bedst fordelt, hvilket gøre den stabil. Arduinoen er placeret ovenpå motorerne med Breadboardet foran, således at den er placeret i midten af robotten så ledningerne fra de forskellige komponenter nemt kan kobles til eller fra Arduinoen. Derudover kan man nemt komme til boardet og Arduinoen, hvis der skal foretages ændringer. Switchen er placeret øverst så vi nemt kan få adgang til den.

Lego digital designer: 

Download her: PF-2-Monstertank

Opbygning af program

const int motorBremseA = 8;
const int motorBremseB = 9;
const int motorRetningA = 12;
const int motorRetningB = 13;
const int motorHastighedA = 3;
const int motorHastighedB = 11;

//const int trigPin = 2;
//const int echoPin = 1;
//const int irPin = A0;

// IP = IR pin og r er right og l er left
int IPR = 2;
int IPL = 3;
int IR_write = 650;

//Sonar brugen
boolean irMode = true; //IR sensor
boolean freedriveMode = false;
boolean driveSonar = false;
boolean roundWall = false;
boolean aktivIR = false;
long duration, distance;
int xN = 0;
int xO = 0;
int fMin = 29;
int fMax = 31;
int openSpace = 300;


void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);

    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(12, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(7, INPUT); // Echo pin
    pinMode(5, OUTPUT); // Trigger pin

}

void loop() {
//---------------IR Kørelse --------------------------
    while (irMode == true) {
        //IR sensor input
        //Hvid er under 100 på begge sensorer 
        //Sort er omkring 850
        int IPRvalue1 = analogRead(IPR);
        Serial.println(IPRvalue1);

        int IPLValue2 = analogRead(IPL);
        Serial.println(IPLValue2);
        delay(50);

         Serial.println("irMode");
        //Styre over igennem Linjen 
        // Kører lige ud hvis begge sider er hvide
        if (IPRvalue1 <= IR_write and IPLValue2 <= IR_write) {
            //motorA
            digitalWrite(12, LOW); //Retning
            digitalWrite(8, LOW); //Bremsen
            analogWrite(3, 50); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, LOW); //Bremsen
            analogWrite(11, 50); //Hastigheden
            Serial.println("FORWARD");

            //drejer til højre hvis højre sensor går under freashole 
        } else if (IPRvalue1 >= IR_write and IPLValue2 <= IR_write) {
            //højresving
            //motorA
            digitalWrite(12, LOW); //Retning
            digitalWrite(8, LOW); //Bremsen
            analogWrite(3, 200); //Hastigheden
            //motorB
            digitalWrite(13, HIGH); //Retning
            digitalWrite(9, LOW); //Bremsen
            analogWrite(11, 200); //Hastigheden
            Serial.println("RIGHT");
            
            //drejer til venstre hvis venstre sensor går under freashole 
        } else if (IPRvalue1 <= IR_write and IPLValue2 >= IR_write) {
            //venstre sving
            //motorA
            digitalWrite(12, HIGH); //Retning
            digitalWrite(8, LOW); //Bremsen
            analogWrite(3, 200); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, LOW); //Bremsen
            analogWrite(11, 200); //Hastigheden
            Serial.println("LEFT");

            //Stopper hvis begge sensor er under freashole
            //Skifter også her mode
        } else if (IPRvalue1 >= IR_write and IPLValue2 >= IR_write) {
            //stop
            //motorA
            digitalWrite(12, HIGH); //Retning
            digitalWrite(8, HIGH); //Bremsen
            analogWrite(3, 0); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, HIGH); //Bremsen
            analogWrite(11, 0); //Hastigheden
            delay(500);
            freedriveMode = true;
            irMode = false;
        }
    }
//--------køre frem og drejer til venstre bestem efter tid------------
    //skifter til sidst til sonarmode
    while (freedriveMode == true) {
      Serial.println("freedriveMode");
        //lige ud
        //motorA
        digitalWrite(12, LOW); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 50); //Hastigheden
        //motorB
        digitalWrite(13, LOW); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 50); //Hastigheden
        delay(4000);

        //venstre sving
        //motorA
        digitalWrite(12, HIGH); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 200); //Hastigheden
        //motorB
        digitalWrite(13, LOW); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 200); //Hastigheden

        delay(1300);

        driveSonar = true;
        freedriveMode = false;

    }

//----------Kørelse med sonar langs væg------------
    while (driveSonar == true) {
          
          Serial.println("driveSonar");
//Køre selve sonar målingerne i dette afsnit
          // under 20 for tæt 
          // over 45 for langt væk
          // optimalt 30
          digitalWrite(5, LOW);
          delayMicroseconds(2);
          digitalWrite(5, HIGH);
          delayMicroseconds(10);
          digitalWrite(5, LOW);
          duration = pulseIn(7, HIGH);
          distance = duration / 10;
          
          Serial.print("distance: ");
          Serial.println(distance);
          Serial.println();

             //hvis afstand er passende kør lige ud
        if (fMax >= distance and fMin <= distance) {
            //lige ud
            //motorA
            digitalWrite(12, LOW); //Retning
            digitalWrite(8, LOW); //Bremsen
            analogWrite(3, 50); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, LOW); //Bremsen
            analogWrite(11, 50); //Hastigheden
            Serial.println("forward");
            delay(10);
            //hvis afstanden til væggen bliver for lille ret væk fra den
        } else if (fMax <= distance and fMin <= distance and openSpace >= distance) {
            //venstre sving
            //motorA
            digitalWrite(12, LOW); //Retning
            digitalWrite(8, LOW); //Bremsen
            analogWrite(3, 125); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, LOW); //Bremsen
            analogWrite(11, 20); //Hastigheden
            //hvis afstanden til væggen bliver for stor ret ind mod den
        } else if (fMax >= distance and fMin >= distance) {
            //højre sving
            //motorA
            digitalWrite(12, LOW); //Retning
            digitalWrite(8, LOW); //Bremsen
            analogWrite(3, 20); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, LOW); //Bremsen
            analogWrite(11, 125); //Hastigheden
        } else if (openSpace <= distance) {
            driveSonar = false;
            roundWall = true;
       //når den er kommet om på den anden side aktivers IR sensor
        } else if(aktivIR == true){
               //IR sensor input
              //Hvid er under 100 på begge sensorer 
              //Sort er omkring 850
              int IPRvalue1 = analogRead(IPR);
              Serial.println(IPRvalue1);
      
              int IPLValue2 = analogRead(IPL);
              Serial.println(IPLValue2);
              delay(50);
              //begge over freashole STOP
          if (IPRvalue1 >= IR_write and IPLValue2 >= IR_write) {
        
            //stop
            //motorA
            digitalWrite(12, HIGH); //Retning
            digitalWrite(8, HIGH); //Bremsen
            analogWrite(3, 0); //Hastigheden
            //motorB
            digitalWrite(13, LOW); //Retning
            digitalWrite(9, HIGH); //Bremsen
            analogWrite(11, 0); //Hastigheden
            delay(10000000000000);
    }
    }
    }

 //--------køre frem og drejer til højre bestem efter tid------------   
    while(roundWall == true) {
        Serial.println("roundWall");
        //lige ud
        //motorA
        digitalWrite(12, LOW); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 50); //Hastigheden
        //motorB
        digitalWrite(13, LOW); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 50); //Hastigheden

        delay(3500);

        //højre sving
        //motorA
        digitalWrite(12, LOW); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 200); //Hastigheden
        //motorB
        digitalWrite(13, HIGH); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 200); //Hastigheden

        delay(1200);
        //lige ud
        //motorA
        digitalWrite(12, LOW); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 50); //Hastigheden
        //motorB
        digitalWrite(13, LOW); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 50); //Hastigheden
        delay(6300);

        //højre sving
        //motorA
        digitalWrite(12, LOW); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 200); //Hastigheden
        //motorB
        digitalWrite(13, HIGH); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 200); //Hastigheden

        delay(1200);

        //motorA
        digitalWrite(12, LOW); //Retning
        digitalWrite(8, LOW); //Bremsen
        analogWrite(3, 50); //Hastigheden
        //motorB
        digitalWrite(13, LOW); //Retning
        digitalWrite(9, LOW); //Bremsen
        analogWrite(11, 50); //Hastigheden
        delay(2000);

                      //stop
        //motorA
        digitalWrite(12,HIGH); //Retning
        digitalWrite(8,HIGH); //Bremsen
        analogWrite(3,0); //Hastigheden
        //motorB
        digitalWrite(13,LOW); //Retning
        digitalWrite(9,HIGH); //Bremsen
        analogWrite(11,0); //Hastigheden
        
        delay(500);
        driveSonar = true;
        roundWall = false;
        aktivIR = true;
    }

Programmet er opbygget af 4 while loops der sidder inde i void loop. Det første while loop kører pathfinding, til at robotten kan køre på linjen. Dette styres med en serie af if statements, hvor det er afhængig af om IR af sensorernes værdi bliver højere end thresholdet, skal den dreje i en retning der vil få den værdien under igen. Hvis begge er under skal robotten køre lige ud og når begge kommer over skal den stoppe og skifte til næste loop. Denne while er sat op til at robotten i bestemte delays kører frem i en bestemt tid og drejer derefter til venstre i en bestemt tid. Igen efter dette skifter den til næste while. Denne bruger sonar data til at guide den lange mur. Her bruges igen if statements til at styre den til højre og venstre. Hvis sonaren registrere en værdi der er over 300 vil den skifte til sidste while loop. Dette loop bruges der delay til at styre hvor meget den skal køre frem, og derefter dreje til højre. Når loopet når til ende skifter den tilbage til sonar loop.   

Hvordan er samspillet mellem mekanik, elektronik og software?

Mekanisk er vores robot opbygget af LEGO og bælter. Elektronisk består den af en Arduino Uno, Motor-shield, Arduino Breadboard, otte batterier, en switch, to LEGO motorer, to linje sensorer og en sonar sensor. Softwaren er opbygget i Arduino programmet. Samspillet mellem disse er meget vigtig for at robotten kan køre efter banen.

Mekanisk kan robotten ikke køre, hvis den ikke har hjul til at bevæge sig med og uden LEGO-køretøjet kunne vi ikke sætte de forskellige elektroniske dele på robotten og den ville derfor ikke kunne køre uden strøm, og Arduino Uno og Motor-shield da den ikke kan modtage koden vi har programmeret.

Placeringen af sensorerne er også en vigtig faktor for at robotten fungere optimalt. Vi har valgt at placere linje sensorerne forrest forneden, for at komme tættere på banen, så den bedre kan opfange den sorte linje. Sonar sensoren er placeret på robottens højre side, så den opfanger muren, for når robotten svinger, er muren placeret på dens højre side. Derudover er sonar sensoren placeret så den passer i højden med muren

Robotten er programmeret til at køre efter banens opbygning og softwaren modtager signal fra sensorerne. Når linje sensorerne opfanger hvid farve så kører robotten lige ud, og når den opfanger sort så retter den sig ind, ved at svinge fra den ene til den anden side, så den sorte linje er mellem sensorerne. Sonar sensoren opfanger hvor tæt muren er på sensoren. Hvis sonaren får en værdi over 31 retter den sig ind mod muren. Hvis værdien er under 29 retter den sig væk fra muren, for ikke at ramme den. Hvis værdien er på 30 kører den lige ud. Hvis sonaren har en værdi over 300 opfanger den at muren ikke længere er der og den gøre klar til at svinge.

Således kan der konkluderes at samspillet mellem mekanik, elektronik og software er meget vigtig for at robotten kan køre korrekt efter banens opbygning. Hvis den ikke har et køretøj der kan køre med strøm og sensorerne ikke kan give til signal til softwaren så kan den ikke køre efter banens opbygning.

Konklusion – hvor godt løser robotten opgaven

Vi kan hermed konkludere at vi har konstrueret en automom kørende Arduino LEGO robot, ved hjælp af LEGO, Arduino Uno, Motor-shield, Arduino Breadboard, otte batterier, en switch, to LEGO motorer, to linje sensorer og en sonar sensor. Og robotten er programmeret i Arduino. Overordnet set løser vores robot opgaven udmærket. I den første del af banen kan den følge og indordne sig den sorte streg. Og i den anden del af banen kan den opfange muren og følge den. Svingene som robotten foretager sig er hardcoded og virker nogenlunde. Derudover var vores 3 bedste konkurrencetider på 1.27 min, 0.49 min og 1.09 min. I det første forsøg var hastigheden sat til 50, det andet forsøg var den sat op til 150 og det sidste forsøg var den sat helt op til 250. I det sidste forsøg kunne vores robot ikke følge den sorte streg optimalt, og vi måtte starte forfra 2 gange. Vi kan konkludere at vores robot kører gennem banen med en nogenlunde god tid, i forhold til den bedste konkurrence tid der var på 0.19 min og den længste tid på 3 min.

Perspektivering – Hvad kan man gøre for at gøre den bedre?

Det ville have været nemmere at løse den anden del af banen, hvis muren havde været tykkere da vi så kunne have brugt sonar sensoren mere optimalt i svingene. Da vi så muligvis ikke skulle have hardcoded svingene. Og vi kunne have brugt en ekstra sonar sensor som skulle placeres forrest på robotten, hvilket ville gøre at den i det første sving ville kunne registrere hvor muren starter, og svinge derefter. Robotten kan desuden altid finjusteres mht. hastighed og sving.

Leave a Reply