Navn: Simon Banke Uggerhøj og Mathias Grøn Paulsen

Opbygning af system

Der er ikke nogen gearing på bilen og da farten på bilen styres ved at regulere på det PWM-signal der bliver sendt. Sensorerne er placeret foran hjulene og da denne placering gør forholdene bedre at arbejde med under drej. Dog kan det være problematisk hvis disse sensorer bliver placeret for langt fremme, da et drej i robotten vil give et stort udslag. For at finde den rette hastighed, er der blevet brugt en iterativ proces, hvor der er blevet ændret på farten så den opnår det optimale fart.

Selve bilens dimensioner er baseret på at jo mindre den fylder i forhold til længde og bredde, desto nemmere er det at bevæge sig rundt på banen uden at flytte på andre ting end selve kassen.

Bredden mellem de to sensorer er fundet ved at sammenligne bredden af stregen, med selve kloen og derefter finde en bredde der både passede til kassen og til at lave præcise nok målinger. Sensorerne er placeret ca. 4 cm foran motoren.  Placering er valgt på grundlaget af at skabe den bedste kontakt med underlaget, samt for at skabe bedst mulighed for at registrere krydsene på rigtige tidspunkt, og herefter kunne reagerer på disse.

Selve bilen har også taget udgangspunkt i at placere motorerne så lavt som muligt, da det vil betyde at man kan bruge hjulstørrelse, der kun er begrænset af størrelsen på på motoren.

Hjulenes har en diameter på ca. 4 cm. Disse er valgt da de er nemmere at kontrollerer i hastighed. Det vil altså sige at jo mindre hjulene er, desto bedre manøvrere, og jo større hjulene er, desto hurtigere vil den køre. I denne opgave er det mere vigtigt at manøvrere korrekt end det er at have en høj hastighed.

De ændringer der er kommet i løbet af projektet, er støttebenet, fangearmen og IR-sensorer. Støttebenet blev ændret da den kunne dreje rundt, og dermed blokere for sin egen bevægelighed. Støttebenet blev skiftet ud med den nuværende model, da denne ikke kan dreje og dermed ikke blokere for sig selv. Den nye udgave kan ikke dreje på nogen måde, hvilket betyder at den ikke kommer karambolage med sig selv. Den er udformet så den blot glider hen over underlaget, og derfor ikke skaber bemærkelsesværdig mængde af friktion.

Fangearmen er blevet forlænget da den gamle version var for kort til at få ordentligt fat i selve kassen. IR-sensorer er blevet rykket lidt for at finde den optimale placering eftersom hvis der er for stor afstand mellem sensorerne, kan det betyde at bilen drejer alt for meget, hvilket kan gøre at den ikke kommer korrekt ind til et sving. Sensorerne vil ramme den sorte linje på forskellige tidspunkter, hvilket kan betyde at der kommer en forkert aflæsning af sensor input. Den endelige placering i forhold til den oprindelige position er lidt tættere på hjulene.

Hardware

Systemets komponenter:

·         2 x IR-sensor

·         2 x Lego DC-motorer

·         Arduino UNO med motor shield (REV3)

·         Batteriholder med plads til seks AA-batterier

·         PCB-plade der indeholder fire LEDer og en 150Ω modstand

De to motorer og IR sensorer, samt de fire LEDer er forbundet via en Arduino UNO med et ”Motorshield (REV3). de fire LEDer er placeret på et PCB med en modstand, hvor forbindelsen til LED’erne kom fra Digital pins, og modstanden var connected til GND, på denne måde kunne hver enkelt LED tændes. De to DC-motorer er forbundet til motorshieldet gennem hver deres H-bro.

En H-bro styrer hvilken vej en DC-motor drejer. Dette gøres ved at kombinere fire MOSFET transistorer. For at styre hvilken retning motoren skal rotere, åbner man dem diagonalt. Det vil sige at S1 og S4 skal åbnes for at dreje den ene vej, og S2 sammen med S3 for at dreje den anden vej. Figur 1 viser opbygningen af en H-bro.

Motorshieldet bliver brugt, da arduinoen i sig ikke kan leverer nok amperer til at drive DC-motorerne. Som supplement til strøm levering blev der brugt en ekstern strømforsyning i form af en dc-transformer. I den første iteration blev der benyttet 6 stk AA.

IR sensorerne fungerer ved at den bliver forsynet fra Arduino boardet, der gør at den udsender et infrarødt lys. Dette bliver så reflekteret tilbage i en IR sensitive Photo resistor. Det vil altså sige at desto mere der bliver reflekteret tilbage, desto lavere en værdi vil der blive aflæst i sensor output. Det vil sige at der vil komme lave værdier ved den hvide farve, da denne farve reflektere det meste, hvorimod den sorte farve stort set ikke reflektere noget lys, og dermed vil der komme en højere værdi. Et problem der har været med IR-sensorerne er at der kan være stort udsving i de målte værdier. Dog skyldes de udsving at underlaget er meget beskidt grundet snavs og den derfor måler en falsk værdi på sensorerne, der betyder at den hopper til næste del i koden selvom den ikke er på den rigtige placering. Et andet problem med sensorerne er højden mellem underlaget og sensoren. Dette skyldes at robotten er konstrueret således at dens højde afhænger af hvordan den er stillet på støttebenet, og hvor meget man er kommet til at skubbe til fangearmen. Det vil sige at hver gang man flytter på den er der en risiko for at ændre på højden mellem sensor og underlag.

Selve PCB’et er opbygget ved at der kommer en strøm på en af de fire pins på venstre side af figur 2. Derefter går strømmen gennem modstanden der skal være mellem de midterste to tekstfelter. De fire LEDer bliver exciteret fra Arduinoen, og er forbundet til en ground på Arduinoen. De pins der aktiverer LEDerne er digital pins 2,4,7 og 10.

Hvordan er robottens opførsel implementeret

·         Hvad er de overordnede opførsler / metoder for robotten

De primære funktioner i robotten er FollowBlack, som sørger for at robotten følger de sorte linjer. Der er implementeret småkorrektionsmoduler undervejs. Så er der CrossBlack, som er funktion der sørger for at lade robotten passerer de sorte kryds.

Så er der RightTurn og LeftTurn, som gør om robotten kan dreje til højre eller venstre.

·         Lav et flow-diagram, der beskriver robottens opførsel og model – de enkelte states og transition conditions.

Hele koden bygger på et array indeholdende Char værdierne, S, F, C, R eller L. Disse forskellige Charværdier repræsenterer en commando. Denne commando resulterer i forskellige funktioner, som gør at robotten kører den retning, som der er ønsket. Transitions mellem de forskellige cases sker ved STOP funktionen. Grunden til at det sker her, er for at sikre at det sker samme sted hver gang. I de forskellige funktioner er der forskellige statements der resulterer i, at funktionen STOP bliver kaldt. Kigger man på FollowBlack, sker det, når begge sensorer har en værdi større end 250. Dette er for at sikrer så vidt muligt, at robotten er placeret i en lige retning, inden transitionsskift. Hvis robotten f.eks registerer at højre sensor er over 250, men venstre ikke er, laver den en retningskorrektion. På denne måde sikres altså, at robotten peger ligeud når loopet er færdigt. Ved Crossblack, er vi ikke længere interesseret i, at robotten skal følge den sorte, men at den skal køre over det sorte. Derfor kalder den funktionen forward, så længe at sensorværdierne er over 250, eller sagt med andre ord, sorte. Når sensorværdierne igen er under 150 på en af sensorne, ved vi, at robotten har krydset det sorte kryds, og transition kan ske. Ved RightTurn vil vi sikrer os, at robotten laver et komplet sving. Derfor er if loopet sat til, at så længe venstre er større end 200 og højre sensor er større end 250, så skal den kalde funktionen LeftMotorDir. Dette resulterer i, at robotten drejer mod højre, og når begge sensorer er i hvid, så outputter de en værdi lavere end 150, hvilket passer med næste if loop, som kalder funktionen stop. I LeftTurn, er funktionen som i RightTurn, bare med lidt forandringer. Her er det Leftsensor der skal være større end 250, og Rightsensor skal være større end 200. Hvis dette er tilfældet, kaldes funktionen RightMotorDir. Så snart sensorne er i hvid igen, kaldes funktionen stop, og transition sker.

·         Inkludér kode + beskrivelse – Til at formattere og highlighte jeres kode på blog’en kan i bruge Crayon Syntax Highlighter. Dette gøres ved at anvende ikonet: i menubjælken under ”Add new post” i wordpress. Bare benyt standardindstillingerne i ”Add Crayon Code”-popup’en. Sketching-sproget formateres fint med JAVA-indstillingerne!

int setspeed = 0;
double input1 = A2;
double input2 = A3;
bool RUN = true;
const int FollowLED = 5;
const int LeftLED = 10;
const int RightLED = 7;
const int TurnLED = 4;

// kanal B venstre
const int LeftPWM = 11;
const int LeftDir = 13;
const int LeftBrake = 8;

// kanal A Højre
const int RightPWM = 3;
const int RightDir = 12;
const int RightBrake = 9;

double leftsensor = 0;
double rightsensor = 0;

// command system
int CMD = 0;
char commandList [] ={'F','C','F','C','F', 'R','F','C','F', 'L','F','L','F','L','F','L','F','C','F','C','F','S','R','F','R','F','R','F','L','F','C','F','R','F','R','F','R','F','L','F','R','F','L','F','S'};
char currentCMD = commandList[CMD];

void setup() 
{
Serial.begin(9600);
pinMode(FollowLED,OUTPUT);
pinMode(LeftLED,OUTPUT);
pinMode(RightLED,OUTPUT);
pinMode(TurnLED,OUTPUT);
  
pinMode(A2,INPUT); //Venstre sensor
pinMode(A3,INPUT); //Højre sensor

pinMode(RightDir, OUTPUT);
pinMode(RightBrake, OUTPUT);
pinMode(RightPWM, OUTPUT);
pinMode(LeftDir, OUTPUT);
pinMode(LeftBrake, OUTPUT);
pinMode(LeftPWM, OUTPUT);

}

void loop(){
leftsensor = analogRead(A2);
rightsensor = analogRead(A3);
Serial.println(leftsensor);
Serial.println(rightsensor);

switch (currentCMD)
{
case 'F':
FollowBlack();
break;

case 'C':
CrossBlack();
break;

case 'R':
RightTurn();
break;

case 'L':
LeftTurn();
break;

case 'S':
STOP();
break;
}
delay(10000);
}

void FollowBlack()
{
  setspeed = 85;
ForwardLED();
  while (RUN)
  {
    leftsensor = analogRead(A2);
    rightsensor = analogRead(A3);
    if (leftsensor < 150 && (rightsensor < 150))
    {
      Forward(); 
    }
    if (leftsensor > 250 && (rightsensor > 250))
    {
      STOP(); 
      RUN = false;
      delay(500);
    }
    else if (leftsensor < 150 && (rightsensor > 250))
    {
      RunRight(); 
    }
    else if (leftsensor > 250 && (rightsensor < 150))
    {
      RunLeft();
    }
  }
  RUN = true;
  return;
}

void Forward()
{
  Serial.println("Frem");
  digitalWrite(RightDir, HIGH);
  digitalWrite(RightBrake, LOW);
  analogWrite(RightPWM, setspeed);
  digitalWrite(LeftDir, HIGH);
  digitalWrite(LeftBrake, LOW);
  analogWrite(LeftPWM, setspeed);
}
void RunRight()
{
  digitalWrite(RightDir, HIGH);
  digitalWrite(RightBrake, LOW);
  analogWrite(RightPWM, 75);
  digitalWrite(LeftDir, LOW);
  digitalWrite(LeftBrake, LOW);
}
void RunLeft()
{
  digitalWrite(LeftDir, HIGH);
  digitalWrite(LeftBrake, LOW);
  analogWrite(LeftPWM, 75);
  digitalWrite(RightDir, LOW);
  digitalWrite(RightBrake, HIGH);
}

void STOP()
{
  STOPLED();
  CMD++;
  Serial.println("STOP");
  digitalWrite(RightDir, LOW);
  digitalWrite(RightBrake, HIGH);
  analogWrite(RightPWM, setspeed);
  digitalWrite(LeftDir, LOW);
  digitalWrite(LeftBrake, HIGH);
  analogWrite(LeftPWM, setspeed);
}

void CrossBlack()

{
  setspeed = 100;
  ForwardLED();

  while(RUN)
  {
    leftsensor = analogRead(A2);
    rightsensor = analogRead(A3);

    if (leftsensor > 250 && (rightsensor > 250))
    {
      Forward();
    }
    if (leftsensor < 150 || (rightsensor < 150))
    {
      STOP();
      delay(300);
      return;
    }
  }
  
}

void RightTurn()
{
  Serial.println("Højre");
  setspeed = 100;
  TurnRightLED();
  while(RUN)
  {
    leftsensor = analogRead(A2);
    rightsensor = analogRead(A3);

    if ( leftsensor > 200 && ( rightsensor > 250));
    { 
      LeftMotorDir();
    }
    if (leftsensor < 150 && (rightsensor < 150))
    {
      STOP();
      delay(300);
      return;
    }   
  } 
}

void LeftMotorDir()
{
      digitalWrite(LeftDir, HIGH);
      digitalWrite(LeftBrake, LOW);
      analogWrite(LeftPWM, setspeed);
      digitalWrite(RightDir, LOW);
      digitalWrite(RightBrake, LOW);
      analogWrite(RightPWM, 60);
}

void LeftTurn()
{
  Serial.println("Venstre");
  setspeed = 100;
  TurnLeftLED();
  while(RUN)
  {
    leftsensor = analogRead(A2);
    rightsensor = analogRead(A3);

    if (leftsensor > 250 && (rightsensor > 200))
    {
      RightMotorDir();
    }
    if (leftsensor < 150 && (rightsensor < 150))
    {
      STOP();
      delay(300);
      return;
    }
  }
}

void RightMotorDir()
{
      digitalWrite(RightDir, HIGH);
      digitalWrite(RightBrake, LOW);
      analogWrite(RightPWM, setspeed);
      digitalWrite(LeftDir, LOW);
      digitalWrite(LeftBrake, LOW);
      analogWrite(LeftPWM, 60);
}

void ForwardLED()
{
digitalWrite(FollowLED,HIGH);
digitalWrite(LeftLED,LOW);
digitalWrite(RightLED,LOW);
digitalWrite(TurnLED,LOW);
}

void TurnRightLED(){
digitalWrite(FollowLED,LOW);
digitalWrite(LeftLED,LOW);
digitalWrite(RightLED,HIGH);
digitalWrite(TurnLED,LOW);
}

void TurnLeftLED(){
digitalWrite(FollowLED,LOW);
digitalWrite(LeftLED,HIGH);
digitalWrite(RightLED,LOW);
digitalWrite(TurnLED,LOW);
}

void STOPLED()
{
digitalWrite(FollowLED,LOW);
digitalWrite(LeftLED,LOW);
digitalWrite(RightLED,LOW);
digitalWrite(TurnLED,HIGH);
}

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

En af de største udfordringer der har været med koden, har været at finde et passende threshold, hvor de forskellige loops skulle “aktiveres”.

Problem lå i, at det blev antaget, at de først skulle aktiveres når værdien lå meget højt. Dette fandt vi, gjorde at robotten nogle gange “overså” krydsene. Derfor blev disse korrigeret løbende.

Næste problematik der var, var strømforsyningen. Til at starte med, var strømforsyningen 6 stk AA batterier. Desværre havde de den indflydelse, at deres varierende spænding nærmest umuliggjorde udviklingen. Et alternativ til en anden gang, ville være at sørge for at bruge batterier med større kapacitet.

Et andet stort problem i kode var, at efter de forskellige funktioner var sat på plads, at sætte funktionerne rigtigt sammen. I og med, at robotten skulle flytte sig relativt langt, så krævede det sammensætning af en del kommandoer.

Det allerstørste problem med kodningen bestod af fejlfindingen. Når funktionerne var på plads for sig, antog man at det hele var fint. Det var desværre IKKE tilfældet, da underlaget gjorde, at man ofte skulle lave gentagne forsøg før robotten gjorde som tiltænkt og der ikke skete noget undervejs (Demovideoen er video optagelse nr. 14, uden ændring af kode). Dette gjorde arbejdet ekstremt frusterende og til tider umuligt at vide hvor der skulle ændres.

KONKLUSION.

Løser robotten opgaven ift. opgaveformuleringen?

Robotten Løser opgaveformulering, med et tvist. Den løser ikke umiddelbart den problematik med at leverer et produkt fra punkt A til B, men kører forbi punktet, hvor operatøren så kan sørge for at der bliver smidt ting af og på.

Forbedringer:

Hvis man skulle forbedre bilen, skulle man måske gøre den lidt længere, da dette vil gøre at der ville være nemmere adgang til de forskellige komponenter, og ville gøre det nemmere at troubleshoote på de forskellige ledninger.

Det kunne være fordelagtigt at implementer gearing, da PWM “gearingen” ikke var tilstrækkeligt præcist.

Desuden var vi nødsaget til at gå fra Batterier til direkte strømkilde, da batterierne varierende spændingsforhold gjorde opgave konteksten svære at debugge. Det kunne både være kode, sensor, og batteri.

Derfor er den nuværende funktion ikke tilstrækkelig til implementering i et større regi.

Et andet problematik der blev stødt på, var at underlaget var problematisk. Der blev oplevet gentagende gange, at grundet “pletter” på måtten, og sensorerne registrerer disse som et kryds, hvilket resulterede i et transition skift. Grundet disse miljømæssige faktorer, vil det ved fremtiden også være fordelagtigt, at underlaget sikres for smuds, eller andre påvirkningere, der kan influere på hvordan/hvornår sensorne sender ud, at der er “linjeskift”.

Inkludér demo-video, hvor robotten ses aflevere kasserne.

Leave a Reply