Gruppe:
Thomas Steenfeldt Laursen & Morten Krogh Jensen

Opbygning af Solar Trackeren

Til det overordnede design har vi taget to papkasser, hvoraf den ene fungerer som base for robotten og holder for motoren. Ovenover har vi et stykke bukket pap monteret til motoren hvor de to Photo resistorer (LDR) sidder med en skillevæg til at kaste skygge på dem efterhånden som solen bevæger sig over himlen.

Dette design tillader at robotten kan bevæge den ene plade uafhængigt af basen, og dermed med minimal friktion rette vores LDR’er mod solen.

De 2 LDR’er er forbundet til breadboardet hvor vi med modstande har lavet en spændingsdeler, som giver os den værdi vi bruger som input til vores Arduino. Selve stepper motoren er forbundet til et stepper motor driver modul, som derefter er forbundet til strømmen som vi alligevel har på breadboardet, og til 4 digitale porte på Arduinoen, hvorfra motoren får sine instruktioner. Sidst men ikke mindst så har vi på breadboardet placeret 3 status LED i henholdsvis hvid, grøn og rød, hvor Rød lyser ved rotation mod venstre, og Grøn lyser ved rotation mod højre, og hvid lyser ved ingen rotation, som et symbol på at den er placeringen er blevet udregnet til at være optimal for den nuværende mængde sollys. Hver LED er udstyret med hver sin 330 ohms modstand, for at sikre at LED’erne ikke springer.

Teknisk sammensætning af hardware

Herunder ses et kredsløbsdiagram over hele konstruktionen.

Spændingsdelere

En photo-resistor er en modstand hvis størrelse afhænger af mængden af lys den udsættes for. I tilfældet med disse LDR-modstande, så sænkes modstanden når belysningen øges. I vores projekt udnytter vi denne egenskab til at justere solpanelernes retning i forhold til hvilken modstand der bliver udsat for mest lys.

På kredsløbsdiagrammet kan man se de to LDR-modstande sat sammen i hver sin spændingsdeler-kredsløb. Hver LDR-modstand er serieforbundet med en almindelig modstand på 10k ohm. Spændingen imellem LDR-modstanden og den almindelige modstand vil variere når LDR-modstanden udsættes for forskellige mængder lys. Denne spænding måles ved at forbinde den en af til Arduinoens analoge porte (A0 og A1), som det kan ses på kredsløbsdiagrammet. Hvis man kender størrelsen for de to modstande, kan man finde spændingen imellem dem ved hjælp af følgende formel:

Det Arduinoen måler er V_out, og ud fra denne kan det bestemmes om LDR-modstanden udsættes for meget eller lidt lys. Arduinoen har en 10-bit A/D-converter og vil derfor returnere et heltal mellem 0 og 1023, hvor 0 svarer til 0V og 1023 svarer til 5V. For et heltal n, vil spændingen svare til følgende udregning:

Det var ikke ligegyldigt hvilken størrelse fast modstand vi valgte at bruge til spændingsdelerne (R1 og R2). Man ønsker at vælge modstande som giver stor variation i V_out siden det giver en højere ”opløsning”, og man kan registrere finere ændringer i lysstyrken. Vi oplevede at en fast modstand på 10k ohm gav mulighed for meget stor variation (ca. fra 30 til 900 på Arduinoens A/D-converter.

Stepper Motor

Til at drive rotationen på vores robot valgte vi at bruge en stepper motor da den tilbød en nem mulighed for at styre hastigheden og antallet af steps. Dette bruger vi blandt andet til at sætte robotten tilbage til udgangsposition lige så snart at solen går ned, denne del er videre beskrevet i kodeafsnittet.

Stepper motoren er en 4 faset 5vdc motor[1], og fungerer ved at vi via vores stepper motor driver modul kan aktivere hver enkelt spole indeni, sådan at den rotor der sidder inden i som har en række tænder, drejer over og står på linje men de aktiverede statore.

Statore er de grupper af spoler som findes inden i stepper motoren og er den ikke bevægende del, og det er disse spoler som kan aktiveres for at skabe rotation i rotoren. Rotoren er den bevægende del som flytter sig hen til det næste set tænder, og dermed har motoren nu taget et skridt.

I datasheet for vores stepper motor kan vi læse os frem til at motoren skal bruge 64 skridt af 5,625 grader/skridt til at nå en hel rotation, derudover kan vi se at gearingen i motoren er en 64:1, så for at udregne det total antal steps motoren tager, så skal vi altså gange de 64 skridt på en omgang, med de 64 fra vores 64 til 1 gearing:

64 * 64 = 4096

Da vi i vores programmering tager 8 steps ad gangen grundet den sekvens vi aktiverer spolerne i, så skal vi dividere med 8 for at få det totale antal steps vi skal bruge i koden på en rotation.

4096 / 8 = 512

Dette resultat ville man i koden kunne bruge til at udregne antal steps for f.eks. hele, halve og kvarte rotationer, hvis man ønskede sin robot skulle kunne lave dem.

Solsystemets opførsel

Overordnet flowdiagram

Følgende flowdiagram beskriver robottens overordnede opførsel. Kort sagt, så læser den værdierne af de to spændingsdelere og sammenligner dem med hinanden. Den ene værdi er tilstrækkeligt højere end den anden, så vil robotten dreje for at udligne værdierne. Hvis sensorværdierne er ens, foretages der intet. Hvis begge sensorværdier viser lav belysning, vil robotten se det som et tegn på at solen er gået ned, og den vil dreje tilbage til sin startposition (positionen robotten havde da den tændtes). Denne opførsel vil køre i et konstant loop så længe robotten er tændt.

Kode

Herunder ses hele koden til solsystemet. Den første metode der eksekveres er setup(). Her initialiseres alle porte til deres formål. Porte A, B, C, og D (digital port 4, 5, 6, og 7) initialiseres som OUTPUT siden disse skal styre motorens bevægelser. De tre LED-porte sættes også til output.

Herefter begynder loop()-metoden at eksekvere. Den læser de to spændingsdelere med analogRead()-metoden og gør dem klar til sammenligning. Bemærk at variablen margin  initialiseres. Denne fungerer som en buffer og sørger for at solar trackeren ikke reagerer på de små usikkerheder og svingninger på spændingsdelerne. Vi oplevede også at de LDR-modstande ikke reagerede ens på lys. Når udsat for samme lys-mængde, ville den venstre spændingsdeler altid give en højere V_out end den højre. Denne forskel blev mere markant jo mindre lys de blev udsat for. Derfor stiger “margin” i takt med at spændingsdelernes værdier stiger for at modvirke forskellens ændrende markanthed.

Solar trackerens hovedfunktionalitet foregår på linje 114 i koden. Her tjekkes det om forskellen på de to sensorværdier er over margin. Hvis det er tilfældet, vil motoren enten dreje ét step med eller mod uret baseret på hvilken af sensorværdierne der er højest. Arduinoen får motoren til at dreje ved at kalde onestep()-metoden. Som beskrevet tidligere, så foretager denne metode rent faktisk otte steps. Ét enkelt step foretages ved at kalde metoden write() med værdier for hvilke spoler der skal aktiveres. Otte af disse write()-metoder er i onestep() sat sammen i den rigtige sekvens så motoren enten drejer lidt med eller mod uret. Variablen  styrer hvor hurtigt motoren drejer. Efter onestep() er kaldt, ændrer Arduinoen heltallet step_pos med +1 eller -1 afhængig af hvilken retning motoren drejede. step_pos hjælper med at holde styr på motorens position.

If-sætningen på linje 109 tjekker om solen er gået ned. Vi oplevede at Arduinoen læser værdier omkring 800 når LDR-modstandene udsættes for aften-lignende lys. Hvis begge er over denne værdi, kaldes metoden return_to_start(). Denne metode bliver ved med at dreje motoren indtil variablen step_pos er nul og motoren har fundet sin oprindelige startposition.

int A = 4;
int B = 5;
int C = 6;
int D = 7;
int step_pos = 0;

int sensorLeft = A1;
int sensorRight = A0;

int ledRedPin = 11;
int ledGreenPin = 12;
int ledWhitePin = 13;

long t = 0;

void setup() {
  Serial.begin(9600);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(ledRedPin, OUTPUT);
  pinMode(ledGreenPin, OUTPUT);
  pinMode(ledWhitePin, OUTPUT);
}

void write(int a, int b, int c, int d) {
  digitalWrite(A, a);
  digitalWrite(B, b);
  digitalWrite(C, c);
  digitalWrite(D, d);
}

void onestep(bool clockwise) {
  int d = 15;

  if (clockwise) {
    write(1, 0, 0, 1);
    delay(d);
    write(0, 0, 0, 1);
    delay(d);
    write(0, 0, 1, 1);
    delay(d);
    write(0, 0, 1, 0);
    delay(d);
    write(0, 1, 1, 0);
    delay(d);
    write(0, 1, 0, 0);
    delay(d);
    write(1, 1, 0, 0);
    delay(d);
    write(1, 0, 0, 0);
    delay(d);
  } else {
    write(1, 0, 0, 0);
    delay(d);
    write(1, 1, 0, 0);
    delay(d);
    write(0, 1, 0, 0);
    delay(d);
    write(0, 1, 1, 0);
    delay(d);
    write(0, 0, 1, 0);
    delay(d);
    write(0, 0, 1, 1);
    delay(d);
    write(0, 0, 0, 1);
    delay(d);
    write(1, 0, 0, 1);
    delay(d);
  }
}

void return_to_start() {
  while (step_pos != 0) {
    if (step_pos > 0) {
      onestep(false);
      step_pos--;
    } else {
      onestep(true);
      step_pos++;
    }
  }
}


void loop() {
  digitalWrite(ledRedPin, LOW);
  digitalWrite(ledGreenPin, LOW);
  digitalWrite(ledWhitePin, LOW);

  int leftValue = analogRead(sensorLeft);
  int rightValue = analogRead(sensorRight);
  int margin = 5 + 0.05 * (leftValue + rightValue);

  if (millis() >= t + 1000) {
    t = millis();

    Serial.println();
    Serial.print(leftValue);
    Serial.print("  ");
    Serial.print(rightValue);
    Serial.print("  ");
    Serial.print(step_pos);
    Serial.print("  ");
    Serial.print(margin);
  }

  if (leftValue > 800 && rightValue > 800) {
    return_to_start();
    return;
  }

  if (abs(leftValue - rightValue) > margin) {
    if (leftValue < rightValue) {
      digitalWrite(ledGreenPin, HIGH);
      onestep(true);
      step_pos++;
    }
    else if (rightValue < leftValue) {
      digitalWrite(ledRedPin, HIGH);
      onestep(false);
      step_pos--;
    }
  } else {
    digitalWrite(ledWhitePin, HIGH);
  }
}

Test

Vi testede solsystemet ved at sætte det i vinduet over et par timer. Det var hensigten at robotten skulle følge solen som bevægede sig over himlen. En video af testen kan ses herunder:


Under hele testen opsamlede vores computer data om solar trackerens placering og sensor-værdier. Grafen herunder viser variablen step_pos (blå) og forskellen mellem de to sensorers værdier (orange) som funktion af tiden. Det fremgår af grafen at forskellen mellem de to sensorværdier er rimelig konstant igennem hele testen. Det har altså lykkes af solar trackeren at opnå dette ved at dreje sig (som den blå graf viser).

Konklusion

I projektet skulle der bygges en robot som afhængig af sollys justerede sig til altid at så vinkelret på lyskilden, dette er lykkedes ved hjælp af pap samt de elektroniske komponenter som vi havde tilgængeligt fra vores Elegoo start kit. Robotten vurderer på baggrund af 2 LDR hvor lyskilden er stærkest, og retter sig derefter ind hvis der er behov.

Såfremt at robotten skulle forbedres, ville et mere robust design til at modstå vejr miljøet være at foretrække da den nuværende konstruktion i pap ville miste bæreevne så snart det blev vådt, eller kunne blæse væk hvis der kom vind. Derudover kunne man tilføje endnu en motor som justerede robotten vertikalt, således at robotten ville kunne justere sig opad hvis solen stod højt på himlen. Sammen med den ekstra motor og eventuelt et ekstra sæt LDR kan vi sikre at robotten altid vil kigge direkte imod lyskilden.

[1] https://ardustore.dk/error/Manuel%20-%2028BYJ-48%20Stepper%20Motor.pdf