Robotsystem Solfølger
lavet af: Ellen Lorenzen og Lærke Bøg
Opbygning
Systemet bliver styret af 2 lyssensorer, der er placeret på et breadboard. Lyssensorerne sidder på hver side af en skygge-mur, hvis formål er at kaste skygge over den sensor der er længst væk fra solen. Breadboardet er placeret på en skrå legoopsætning. Den er skrå for at vinkle solcellerne, som skal placeres på breadboardet, mod solen. Breadboardet er forbundet med motoren via flere tandhjul, for at opnå en gearing der får pladen til at bevæge sig langsommere. Derfor går det fra små tandhjul til store tandhjul. Dette blev tilføjet da motoren kørte for hurtigt og havde for lidt kræft.
Opsætningen er også via tandhjul forbundet med et potentiometer der bruges til at måle hvor meget pladen er drejet. Her sidder tandhjulene så der opnås en gearing der sikrer samme drejning af potentiometert som breadboardet. Idet potentiometeret kan dreje 270 grader, muliggør dette, at boardet kan følge solen hele dagen på alle tider af året. Monitoreringen af positionen gør det muligt, at køre til udgangsposition når solen går ned, så solcellerne står klar til at fange morgensolen.
Se opsætningen på billedet herunder.
Hardware
Robotten kan elektronisk opdeles i tre områder. Der er selve arduinoen med motor shielded, en del der registrerer lysretning og en del der registrerer motorens position.
Selve arduinoen med motor shield, bruges dels som spændingskilde til både motoren og de elektroniske kredsløb. Den har tilsluttet 5V fra batterier, ud over det den får fra computeren. Desuden bruges den til analog måling af signalerne, fra de andre områder, gennem sine analoge porte.
Lysretningen registreres ved hjælp af to light dependent resistors (LDR). De ses både på billedet og i diagrammerne. De virker ved, at modstanden i dem ændres afhængigt af lysstyrken de bliver påvirket af. Da de to sensorer er adskilt af muren, der kaster skygge, vil den ene sensor opfange mere sollys end den anden, og dermed vil der blive registreret en forskel. Måden det måles på, er ved at have en spændingsdeler for hver af lyssensorerne, således at det kan måles hvor stor en del af spændingsfaldet der sker over den faste modstand, og hvor stor en del der sker over sensoren.
Potentiometeret er monteret så det drejes sammen med motoren. Når der drejes på potentiometeret ændres dets modstand, og dermed kan det registrere en position. Elektronisk er det opbygget lig lyssensorerne ved, at der tages en analog måling ud fra en spændingsdeler. Måden der er opbygget kan ligeledes ses på billedet og i diagrammerne.
Der er valgt modstande på 5,1 kΩ til både LDR og potentiometeret som den faste modstand i spændingsdelingen. Grunden til der er valgt 5,1 kΩ, er at det ligger nogenlunde midt i begge deles interval, og dermed er med til at give størst mulig spredning i de målte værdier.
Software
Robotten er programmeret så den løbende sammenligner inputtet fra de to lyssensorer. Hvis deres værdi afviger signifikant drejes pladen mod den sensor der måler den højeste lysmængde. Hvis potentiometeret indikerer at pladen er nået til en yderposition drejes den ikke yderliger.
For at sikre at pladen bliver kørt tilbage til udgangspositionen efter solnedgang er følgende blevet skrevet ind i programmet. En tæller tæller op for hvert gennemløb af programmet. Når tælleren når en fastlagt værdi, registreres den aktuelle position. Positionen sammenlignes med den foregående positions. Hvis disse to positioner er ens, opfattes det som om, at solen er gået ned og pladen køres tilbage til udgangspositionen.
Toleranceværdier for forskellen mellem lyssensor og positions ændringer er fundet ud fra test i sollys.
Koden for programmet og et flowchat over koden, kan ses herunder.
// pinde til motoren const int retningPin= 12; // Pinden der styre retningen const int bremsPin = 9 ; // Pind der aktivere bremsen const int PWM = 3 ; // Pind der bruges til at indstille PVM // pinde til lyssensore const int lyssensorHPin= 0; // Pind der modtager input fra højre lyssensor const int lyssensorVPin= 1; // Pind der modtager input fra venster lyssensor const int margen = 4; // Værdi for signafikant forskel mellem de to sensorer const int hastighed=250; // Hastighed til motoren int tid= 0 ; // Tidstæller int TidForTjek=19200; // Antal gennemløb før tjek af position int PositionPin=2; // Pind for input fra potentionsmeter int Position ; // Variabel til positionens værdi int PositionTidligere; // Variabel til tidligere positions værdi const int Positionbegin=353; // Værdi for udgangsposition int PositionT=0; // Variabel til positionstjek void setup() { //Setup af pind mode pinMode(retningPin, OUTPUT); // Sæt retningspind til udgangspind pinMode(bremsPin, OUTPUT); // Sæt brems pind til udgangspind pinMode(lyssensorHPin, INPUT); // Sæt lyssensor 1 pind til input pinMode(lyssensorVPin, INPUT); // Sæt lyssensor 2 pind til input PositionTidligere=analogRead(PositionPin); // Sæt tidligere pindvariable til positionssensorens værdi Serial.begin(9600); // Klargør til at skrive på skrærm } void loop(){ // Læs lyssensors værdig, og sæt variable til den. int HLys = analogRead(lyssensorHPin); int VLys = analogRead(lyssensorVPin); // Udskriv sensorværdier til motitor Serial.print("h"); Serial.print(HLys); Serial.print(" v"); Serial.println(VLys); // Aflæs position Position=analogRead(PositionPin); // Aflæs positionssensors værdig og sæt til variablen Position Serial.print("Position"); // Skriv position i monitor Serial.println(Position); // Skriv Positionsvariables værdi i monitor if(VLys-HLys < margen && VLys-HLys > - margen ) // Tjek om lyssensores værdier ikke er signifikat forskellige { // brems digitalWrite(bremsPin, HIGH); // Aktiver bremse analogWrite(PWM, 0); // Sæt motor kraft til 0 } else if ( HLys > VLys ) // Tjek om der er mere lys på Højre end vestere sensor { if (Position< 357) // Tjek om den er kørt helt til højre { digitalWrite(bremsPin, HIGH); // Aktiver bremse analogWrite(PWM, 0); // Sæt motorkraft til 0 } else { digitalWrite(retningPin, HIGH); // Sæt retning til Højre digitalWrite(bremsPin, LOW); // Slå bremsen fra analogWrite(PWM, hastighed); // Sæt hastighed til den valgte hastighed } } else if (HLys < VLys)// Tjek om der er mere lys på venstre end på højre { if (Position> 1020)// Tjek om den er kørt helt til venstre { digitalWrite(bremsPin, HIGH); // Aktiver bremse analogWrite(PWM, 0); // Sæt motorkraft til 0 } else { digitalWrite(retningPin, LOW); // Sæt retning til venstre digitalWrite(bremsPin, LOW); // Slå bremsen fra analogWrite(PWM, hastighed); // Sæt hastighed til valgte hastighed } } delay(10); // Delay for at kunne holde styr på tiden // Håndtering af solnedgange tid +=1 ; // Tæl tid eller antal gennemløb en op Serial.print("tid "); Serial.println(tid); // Udskriv antal omgange eller tid i monitoren if( tid > TidForTjek) // Tjek om det valgte antal omgange (tid) er gået { tid =0 ; // Nulstil tidstæller PositionTidligere=PositionT; // Sæt tidligere målte position til PositionTidligere PositionT=analogRead(PositionPin); // Aflæs ny position if ((PositionT-PositionTidligere>(-5) && PositionT-PositionTidligere<5) && PositionT>Positionbegin+5 ) // Tjek at position er over 10 enheder forskellig for tidligere position og forskellige fra udgangs positionen { while (PositionT>Positionbegin+2) // Forsæt indtil position er ved begyndelsespositionen { digitalWrite(retningPin, HIGH); // Sæt retning til højre digitalWrite(bremsPin, LOW); // Slå bremsen fra analogWrite(PWM, hastighed); // Sæt PWM til valgte hastighed PositionT=analogRead(PositionPin); // Aflæs positionssensor } } } }
Problematikker
Hardware
En af de største udfordringer i forhold til hardware, har været at bevægelige og ikke-bevægelige dele har skulle være forbundet med ledninger. Desuden har der været problemer med en motor der ikke virkede, og tidspunkter hvor der ikke er blevet registreret det der blev forventet, hovedsageligt fordi der var blevet byttet rundt på nogle ledninger. Det har virket overskueligt at skulle opsætte kredsløbene.
Solnedgang
Først blev det overvejet at opfatte en solnedgang når der ikke længere var lys på sensoren, men hvis solcellen står tæt på kunstigt lys ville denne metode ikke virke. Det antages at kunstigt lys fx en gadelygte ikke bevæger sig derfor opfattes en solnedgang som det tidspunkt hvor pladen ikke har bevæget sig i en givet periode.
For at solcellepladen skal kunne køre tilbage til samme position, er det nødvendigt at kunne holde øje med dens position. Dette problem blev løst med potentiometeret.
For at afgøre hvor mange omgange programmet skal køre, før den ønskede tid mellem positionstjekkene er gået, er følgende gjort. Først tages der tid på 250 omgange. Den tid deles så med 250 for at finde frem til, hvor lang tid en omgang tager. Den ønskede tid deles så med tiden for en omgang. Herved er antal gennemløb af programmet i løbet af den ønskede tid fundet. Den værdi bruges i variablen TidForTjek i koden.
Interval
Det har været en udfordring at få robotten til at reagere på en værdi indenfor et interval. For eksempel skal den stoppe hvis de to lyssensorer giver sammen værdi. Det er urealistisk at de er præcis ens og derfor er der lavet en margen, der bestemmer at de bare skal være tæt på hinanden.
Det er løst ved at trække de to værdier fra hinanden og måle om forskellen er mindre end margen. Her opstod et nyt problem med at fjerne fortegnet, da det er lige meget om sensoren havde drejet sig lidt i den ene eller anden retning. Første blev en unsigned kommando brugt. Dette havde dog ikke den ønskede effekt da outputtet var en tilfældig værdi. Derfor blev det valgt først at tjekke om forskellen lå under den positive marven og derefter om den lå over den negative marven.
Forbedringsmuligheder
Tandhjulene og positionsmålerens position kan nemt rykke sig i forhold til hinanden, for eksempel ved flytning af robotten. Derfor er yderpositionen ikke fast fra test til test. Det kan give nogle problemer i forhold til ledningerne, som lettere vikles ind i hinanden og sætter sig fast. Dette kunne være løst ved at have en knap på robotten der blev trykket ind hvis en fast yderposition blev nået.
Når robotten kører rykker tandhjulene sig i forhold til hinanden så de ikke længere drejes. Dette kunne løses med en bedre fastspænding af tandhjulene.
En forbedring kunne være at solcelleholderen ikke kun drejer om en horisontal akse, men også om en vertikal akse.
Ledningerne sidder frit mellem robottens bevægelige dele og de dele der er placeret på jorden. Dette kan give problemer ved at ledningerne sætter sig fast og bremser robottens bevægelser. Dette problem kunne fjernes ved at sætte ledningerne bedre.
Konklusion
Robotten opfylder de overordnede mål ved at følge lysets bevægelser og har en strategi for at komme tilbage til udgangspunktet efter solnedgang.
Ved en to-timers test udendørs med vekslende skydække levede robotten op til forventningerne ved at vende sig mod det sted på himlen hvor der slap mest lys igennem.
Ved en test af simuleret nat hvor sensoren over en længere periode målte det samme kørte pladen som forventet tilbage til udgangspositionen.