Lasse Fisker (lafis17) og Alexander Rol (alrol17)

Systemets udseende

TinkerCad repræsentation

Ovenstående billede illustrerer den endelige løsning i TinkerCad, dog uden voltage regulator, der gav problemer med TinkerCad simulationerne. De fem hoveddele af systemet er et 9v batteri som spændingskilde, en H-bro der sørger for at strømmen kan vendes, så motoren kan dreje i begge retninger og statusdioder, der lyser afhængig af om vi er i slow start, slow stop eller full speed fasen. Derudover er der et Arduino board, som styrer logikken i systemet, og tre lysmodstande, der fungerer som lyssensorer.

I det endelige system, ville dette naturligvis ikke blive lavet på 3 breadboards, men i TinkerCad er det gjort sådan, for at give bedre overblik og bedre mulighed for at fejlsøge.

Grafisk repræsentation

Ovenstående billede viser den grafiske repræsentation af systemet hvoraf man kan se alle 3 sensorer (‘sensor Back’ vil i den fysiske udgave være i skyggesiden af vores solcelle).
Dioderne i toppen benyttes til at vise brugeren hvilket stadie robottens bevægelse er i.

Rød indikerer ‘Slow Stop’
Blå indikerer maks bevægelseshastighed
Gul indikerer ‘Slow start’

Systemets opbygning

Tanker bag opbygning

Målet med opgaven har været at dele systemet op i mindre bidder, sådan at det var mere overskueligt at lave i TinkerCad for derefter at samle det hele til ét samlet system. Dette er hvad der kan ses i det ovenstående afsnit (“Systemets udseende”)

Gearing

Da vi blev nødt til at bygge systemet i TinkerCad i stedet for et fysisk kredsløb, var der forskel på hvilke motorer der blev brugt. Lego-motoren vil som regel køre med en hastighed på omkring 390 RPM ved 9v, hvorimod den DC motor der er brugt i simulationen, kører med en maks. hastighed på 17415 RPM. Derfor er gearingsforholdet også noget større på DC motoren, end den ville have været med den fysiske løsning med Lego-motoren.

Da det ikke giver mening at solcellens platform skal dreje med en hastighed på over 17000 RPM, er det valgt at bruge et gearingsforhold på 500.000:1. Det vil altså sige at hver gang DC-motoren har drejet 500.000 omgange, vil platformen have drejet sig en enkelt omgang.

Tre forskellige gearingssetups blev udregnet, inden den endelige løsning blev valgt. Disse muligheder var 1:10.000, 1:100.000 og 1:500.000.

360*(17415/10000)=626,94 grader per minut
360*(17415/100000)=62,694 grader per minut
360*(17415/500000)=12,5388 grader per minut

Med setup’et tager det cirka 5 sekunder at dreje selve platformen én grad, hvilket giver mere mening, end at køre 17000 omgange i minuttet, når vi drejer den.

Der er i koden implementeret ‘slow start’ og ‘slow stop’, samt at køre ved fuld hastighed. ‘Slow start’ er implementeret således at motoren vil køre 1/6 grad i hver af faserne, som består af tre forskellige hastigheder, nemlig 25%, 50% og 75% af maks. hastighed. ‘Slow stop’ kører på samme måde som ‘slow start’, bare spejlvendt. Når platformen skal dreje sig én grad, vil vi udelukkende bruge en kombination af ‘slow start’ og ‘slow stop’, derfor er hver enkelt fase delt op i 1/6 af en grad. Udregning af ‘slow start’ og ‘slow stop’ følger nedenunder, samt en illustration af forløbet.

25% af maks

17415/4=4353,75
360*(4353,75/500000)=3,1347 gpm(grader per minut)
3,1347/60=0,052245 gps(grader per sekund)
1/0,052246=19140 ms per grad

19140/6=3190 ms per 1/6 grad

50% af maks

4353,75*2 =8707,5
360*(8707,5/500000)=6,2694 gpm
6,2694/60=0,10449 gps
1/0,10449=9570 ms per grad
9570/6=1595 ms per 1/6 grad

75% af maks

4353,75 *3 =13061,25
360*(13061,25/500000)=9,4041 gpm
9,4041/60=0,156735 gps
1/0,156735=6380 ms per grad
6380/6=1063 ms per 1/6 grad

Illustration af slow start + slow stop

Platformen har også mulighed for at dreje enten 90 eller 180 grader, når større justeringer skal foretages. I den forbindelse, vil rotationen bestå af ‘slow start’, en periode afhængig af antal grader med maks. hastighed og afsluttes af en ‘slow stop’.

Illustration af slow start + full speed + slow stop

Da det er svært at få fremstillet en visuel repræsentation af et gearingsforhold 500000:1, valgte vi at bruge det vi fysisk har bygget i Lego, til at være basis for visning af udregning af et gearingsforhold.

Gearsystemet består af 4 drevne tandhjul, med følgende antal tænder: Tandhjul 1 har 12, 2 har 36, 3 har 24 og 4 har 40 tænder.
Der er et forhold på 3:1 mellem hjul 1 og 2, da hjul 1 skal drejes rundt 3 gange for at hjul 2 drejer en gang. Da hjul 3 sidder aksel-monteret med nummer 2, vil den køre med det samme forhold. Da hjul 3 har 24 tænder og hjul 4 har 40 tænder er forholdet 40/24=1,6667, altså er forholdet mellem 3 og 4 1,6667:1. For at få det samlede gearingsforhold, ganger vi de to forhold sammen:

3*1,6667=5

Dermed er det samlede forhold for gearsystemet 5:1, altså skal hjul 1 drejes 5 omgange, for at hjul 4 har nået en enkelt omgang.

Motoren og H-broen

Motorens placering er valgt, grundet behovet for at den skal kunne køre i begge retninger. Derfor har vi placeret den mellem de fire MOSFETs.

H-broen er bygget op efter de diagrammer vi har fået udleveret fra undervisningen. En forskel er dog at vi benytter os af NPN-transistorer i stedet for switches, da disse kan styres gennem Arduino’en i stedet for at vi fysisk skal flippe en kontakt.

Spændings regulator

Spændingsregulatoren har til formål at give strøm til hele vores system fra ét 9 volt batteri. Der benyttes to kondensatorer for at sikre en i forvejen fast spænding til det videre system (i dette tilfælde til vores Arduino, som skal bruge 5 volt).
Vores 9 volt batteri skulle i forvejen give os jævnstrøm, men her hjælper kondensatorerne med at fastholde en mere konstant gennemgang ved små svingninger. En anden fordel ved dette er også at det kan hindre visse dele i at overophede og i værste tilfælde springe i luften.

Grundet problemer med TinkerCad simulationer har vi lavet spændingsregulatoren separat. Når vi sætter et multimeter på de valgte udgange, får vi den spænding vi ønsker, men TinkerCad vil ikke køre simulationen.
Vi ser da stadig denne del af opgaven som løst, da vi får det ønskede output på henholdsvis 5 og 9 volt til at køre en Arduino samt en motor.
Dette er én af de ting vi vil kigge på når vi engang har mulighed for at gå i lab igen.

Sensorer og deres placering

2 sensorer vs. 3 sensorer

Som udgangspunkt lægger opgaven op til at man skal bruge to lys-sensorer/lys-modstande (LDR) til robotten. Vi har dog valgt at bruge tre i stedet. Grunden til dette er, at det vil mindske risikoen for at robotten vender den forkerte vej. Da solcellen som udgangspunkt bliver installeret med en hældning på 45 grader, har dens orientering større betydning end hvis den blev installeret vandret og derfor har sensorerne også større betydning. Hvis man laver løsningen med kun to sensorer, vil man have en risiko for at solen lyser på bagsiden af solcellen, således at der ikke bliver opsamlet nok energi fra solen. Med 3 sensorer, der er med til at give systemet et pejlemærke for hvad der er bagside og hvad der er front, bliver dette problem elimineret, da man ved at hvis sensoren på bagsiden får den højeste værdi, skinner solen på bagsiden af cellerne, ikke på fronten.

System med 3 sensorer
System med 2 sensorer

Placeringen af sensorerne er udelukkende baseret på at der skal være to sensorer i siderne, som skal sørge for at vi har cellerne rettet i den rigtige retning af solen, og en bagsensor der skal sørge for at det er den rigtige af side af cellerne der peger i den retning.

Problemer undervejs

Corona epidemien/pandemien har gjort det betydeligt sværere at kunne samarbejde, da vi har forsøgt at undlade fysiske møder efter sundhedsstyrelsens anbefalinger. Dette har gjort det svært at forklare for hinanden, hvordan man hver især opfatter teorien og dens overførsel til praksis. Dog føler vi, at vi er kommet nogenlunde godt i mål med opgaven.

Spændingsregulator i TinkerCad ville ikke simulere, da den blev koblet op til det fulde system. Vi har forsøgt at fejlsøge problemet, men er kommet frem til den konklusion at det er en fejl i TinkerCad, da beregningerne til det måske bliver for tungt at gøre i realtime.

H-Bro diagrammet vi fik udleveret var forkert, hvilket gjorde at vi brugte hele to lab-timer på at få det til at virke, men uden held. Vi har fået hjælp af samtlige instruktorer samt underviser, men heller ikke de kunne forstå hvorfor den ikke virkede som den skulle. Først 4 uger senere bliver fejlen fundet i selve diagrammet vi fik udleveret. Dette har været med til at sætte os en smule tilbage i udviklingen af vores portfolies praktiske del.

Robottens opbygning

Kredsløbsdiagram af det endelige system

Ovenfor ses et kredsløbsdiagram der beskriver det endelige system i en simpel illustration. Kredsløbsdiagrammet har til formål at give et mere konkret overblik over systemet, da det ofte er nemmere at følge kredsløbet i dette diagram, frem for et billede af et breadboard med ledninger og komponenter alle vegne.

Arduino-kode

Herunder ses et flowchart af hvilke opførelser vores system kan have gennem koden.

Flowchart af systemets kodedel

Herunder er koden for projektet. Der er forsøgt at lave kommentarer de steder der kan opstå tvivl i forhold til hvad den enkelte del gør i det fulde system.
Kodedelen har ikke umiddelbart givet anledning til problemer. Der har været lidt udfordringer i forhold til at forstå hvordan man taler med Arduinoen, men dette ligger der masser af information om på nettet.

#define left A0
#define back A1
#define right A2

int orientation = 180;
int leftVal = 0;
int backVal = 0;
int rightVal = 0;
long ONE_DEGREE_FULL_MS = 4785;

// precalculated delays for turning 1/6th of a degree at different motor speeds
int DELAY25 = 3190;
int DELAY50 = 1595;
int DELAY75 = 1063;

void setup()
{
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  Serial.println("Current orientation: ");
  Serial.println(orientation);

  leftVal = analogRead(left);
  backVal = analogRead(back);
  rightVal = analogRead(right);

  if (leftVal == rightVal && backVal > leftVal)
  {
    move(180); // turn 180 degrees - it seems like the sun is directly behind us
  }
  else if (leftVal < rightVal)
  {
    if (backVal > rightVal)
    {
      move(90); // 90 degrees right - our back is getting more sun than our front, so we should turn a large amount before rechecking.
    }
    else
    {
      move(1); // 1 degree right - we are facing the sun, just not directly, so we should only make small adjustments until we find the perfect spot.
    }
  }
  else if (leftVal > rightVal)
  {
    if (backVal > leftVal)
    {
      move(-90); // turn 90 degrees left
    }
    else
    {
      move(-1); // turn 1 degree left
    }
  }
}

void move(int movement)
{
  // check if movement is possible (due to wires - never go above 360 orientation, or below 0)
  // and update orientation
  if ((orientation + movement > 360) || (orientation + movement < 0))
  {
    // invert movement
    if (movement > 0)
    {
      turn(-360 + movement);
      orientation = (orientation + (-360 + movement)) % 360;
    }
    else
    {
      turn(360 + movement);
      orientation = (orientation + (360 + movement)) % 360;
    }
  }
  else
  {
    turn(movement);
    orientation += movement;
  }
}

void turn(int degrees)
{
  // turn the specified amount of degrees.
  // Negative = left, positive = right.
  slowStart(degrees);

  // slowStart and slowStop turns 1 degree.
  // therefore full speed is only reached w/ more than 1 degree movement.
  if (abs(degrees) > 1)
  {
    fullSpeed(degrees);
  }

  slowStop(degrees);
}

void slowStart(int degrees)
{
  digitalWrite(8, HIGH);

  if (degrees < 0)
  { // turn left
    // 25% power
    analogWrite(5, 63);
    delay(DELAY25);

    // 50% power
    analogWrite(5, 127);
    delay(DELAY50);

    // 75% power
    analogWrite(5, 191);
    delay(DELAY75);
  }
  else
  { // turn right
    // 25% power
    analogWrite(3, 63);
    delay(DELAY25);

    // 50% power
    analogWrite(3, 127);
    delay(DELAY50);

    // 75% power
    analogWrite(3, 191);
    delay(DELAY75);
  }

  digitalWrite(8, LOW);
}

void fullSpeed(int degrees)
{
  digitalWrite(9, HIGH);

  // the time needed to turn this amount of degrees
  // 1 degree of movement has already been handled by start/stop
  long delaytimer = (abs(degrees) - 1) * ONE_DEGREE_FULL_MS;
  Serial.println("Will be turning at full speed for: ");
  Serial.print(delaytimer);
  Serial.println(" ms.");

  if (degrees < 0)
  {
    // turn left
    Serial.println("Turning left at full speed");
    analogWrite(5, 255);
    delay(delaytimer);
    analogWrite(5, 0);
  }
  else
  {
    // turn right
    Serial.println("Turning right at full speed");
    analogWrite(3, 255);
    delay(delaytimer);
    analogWrite(3, 0);
  }

  digitalWrite(9, LOW);
}

void slowStop(int degrees)
{
  digitalWrite(10, HIGH);

  if (degrees < 0)
  { // turn left
    // 75% power
    analogWrite(5, 191);
    delay(DELAY75);

    // 50% power
    analogWrite(5, 127);
    delay(DELAY50);

    // 25% power
    analogWrite(5, 63);
    delay(DELAY25);

    // stop turning
    analogWrite(5, 0);
  }
  else
  { // turn right
    // 75% power
    analogWrite(3, 191);
    delay(DELAY75);

    // 50% power
    analogWrite(3, 127);
    delay(DELAY50);

    // 25% power
    analogWrite(3, 63);
    delay(DELAY25);

    // stop turning
    analogWrite(3, 0);
  }

  digitalWrite(10, LOW);
}

Konklusion

Vi føler at vi er nået i mål med opgaven på trods af de udfordringer der har været med blandt andet Corona-krisen (Covid-19). Vi har formået at lave et virtuelt system der opfører sig som opgavebeskrivelsen foreskriver.
Vi kunne godt have ønsket os at kunne udvikle robotten i en fysisk model, men dette var der desværre ikke mulighed for grundet Sundhedsstyrelsens anbefalinger.

Video af systemet

Youtube video for fremvisning af funktionelt system

Leave a Reply