U bevindt zich hier: prak EE Arduino-toestanden Arduino gecontroleerde robot  
 ARDUINO-TOESTANDEN
fotoweerstand, motor oefening
servo-oefening
motorshieldoefening
Arduino gecontroleerde robot
pachube-cliënt
toerentalmonitor platendraaier
radiobestuurd wagentje
een aquaponic-systeem
geluidsgenerator
geluidsvervormer
lichtzoeker
ledstripdriver
7 segment display - oefening
99 teller
 PRAK EE
'droogte'-detector
spelen met een ouwe GSM
parallelle poortproefjes
ad-omvormertje
Lappie-detector
regenwatersysteem
dossier simpele leugendetectors
variabel voedinkje
renovatie platendraaiertje
detectorschakeling
renovatie versterker
vintage audio
'vintage'-teller
upgrade klokradio
LFR
lichtdetectie
deurbel
kristalradio
En-schakelingetje
zonnepaneeloefening
flatscreen
Arduino-toestanden
99 teller

ARDUINO GECONTROLEERDE ROBOT
 

4 wiel aangedreven robotplatform De 2 motoren vooraan zijn voorzien van encoders.




 

Lijnvolger-robotwagen: Een lijnvolger is een robotwagentje die een lijn volgt.

Hierboven het robotframe die we gaan gebruiken. Het is uitgerust met 4 motoren. De 2 motoren die zich aan de voorkant bevinden zijn ook voorzien van encoders. Deze encoders gaan we niet gebruiken voor het lijnvolgers-project. Zo'n frame kan je bijvoorbeeld hier aanschaffen...


 

robotframe opgetuigd met allerlei spulletjes... Om het solderen tot een minimum te beperken heb ik het frame voorzien van een breadbord. Daar kan je gemakkelijk je electronische onderdelen insteken. 't blijft tenslotte allemaal experimenteel. Ben niet van plan dit ontwerp eeuwig bij te houden...




 

Meer uitleg over de Arduino Uno controller vindt u hier.
Op de Arduino Uno controller plaatsen we een motor-shield, DFRduino L298P. Een korte uitleg over dit shield vindt u hier.


 

het relatief simpel schemaatje... Op het schema zien we 2 fotoweerstanden die zich in de echte wereld links en rechts van een donkere lijn zullen bevinden. Deze geven informatie door aan de controller. Een led die een wit licht uitzendt en zich uiteindelijk tussen de 2 fotoweerstanden bevindt. 4 motoren, de controller en het shield.




 

De witte led zorgt uiteraard voor voldoende licht en zorgt er ook voor dat veranderlijk licht van buitenaf de fotoweerstanden niet in de war brengen met verkeerde informatie. De fotoweerstanden geven de controller informatie van de buitenwereld. Hoe meer een fotoweerstand zich boven een donker vlak zal bevinden hoe hoger de weerstand zal worden en hoe hoger de spanning wordt die de controller binnenkrijgt. Deze spanningswaarde wordt vergeleken met de spanningswaarde van z'n collega fotoweerstand en al naargelang het geschreven programma worden de motoren links of deze van rechts meer of minder uitgestuurd. Het motorshield krijgt de uitsturingsdata van de controller en levert de nodige stromen aan de motoren. Bij ongelijke uitsturing zal het wagentje beginnen te draaien. Die ongelijke uitsturing kan je goed zien op onderstaand filmpje.



 



 

Het programma kan er als volgt uitzien:

int LDR_wit = 1;
int LDR_groen = 0;
int waarde_LDR_wit;
int waarde_LDR_groen;
int waarde_LDR_wit_map;
int waarde_LDR_groen_map;
int motorgroepgroen = 7;
int E1 = 6;
int motorgroepwit = 4;
int E2 = 5;
int waardegroen;
int waardewit;

void setup()
{
Serial.begin(9600);
pinMode(1, OUTPUT);
}

void loop()
{
waarde_LDR_wit = analogRead(LDR_wit);
waarde_LDR_groen= analogRead(LDR_groen);
waarde_LDR_wit_map = map(waarde_LDR_wit, 0, 1023, 0, 255) ;
waarde_LDR_groen_map = map(waarde_LDR_groen, 0, 1023, 0, 255) ;
if (waarde_LDR_wit == waarde_LDR_groen)
{
waarde_LDR_groen_map = waarde_LDR_groen_map;
}
else
{
if (waarde_LDR_wit > (waarde_LDR_groen))
{ waarde_LDR_groen_map = waarde_LDR_groen_map - 160;
}
if ((waarde_LDR_wit ) < waarde_LDR_groen)
{
waarde_LDR_wit_map = waarde_LDR_wit_map - 160;
}
}
// testregels om waarden mee te volgen op laptop
Serial.print(waarde_LDR_wit);
Serial.print(" ");
Serial.print(waarde_LDR_groen);
Serial.print(" ");
Serial.print(waarde_LDR_wit_map);
Serial.print(" ");
Serial.println(waarde_LDR_groen_map);
// het witte ledje
digitalWrite(1, HIGH);
delay(30);
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit,HIGH);
analogWrite(E2, waarde_LDR_wit_map);
}




 

...en dan uiteindelijk de eerste testen. In deze configuratie en met bovenstaand programma volgt hij redelijk goed bredere donkere lijnen op de grond. De robotwagen is niet in staat om scherpe bochten te maken. Dit komt niet door de hardware maar door de software. Een beter programma zou het wagentje veel wendbaarder maken. 't Is aan u...



 



 

Het batterijpakket is voor het motorshield en de 4 motoren. Had helaas geen batterijen meer over voor de controller vandaar het voedingssnoer dat hij meesleept.






 

Lichtvolger-robotwagen: Ga naar het licht!





 

Schema van de lichtvolger Lijkt dus heel sterk op de lijnvolger met dit verschil dat er hier een fotoweerstand bijgekomen is. De witte led is weg.




 

voorkant lichtvolger Hier zien we drie fotoweerstanden gemonteerd aan de voorzijde.




 




 

Het ingevoerde programma kan er als volgt uitzien:

int LDR_wit = 1;
int LDR_groen = 0;
int LDR_zwart = 2;
int waarde_LDR_wit;
int waarde_LDR_groen;
int waarde_LDR_zwart;
int waarde_LDR_wit_map;
int waarde_LDR_groen_map;
int waarde_LDR_zwart_map;
int motorgroepgroen = 7;
int E1 = 6;
int motorgroepwit = 4;
int E2 = 5;
int waardegroen;
int waardewit;

void setup()
{
// dit is nodig om variabelen te kunnen bekijken op de monitor van de laptop.
Serial.begin(9600);
}

void loop()

{

// analoge waarden fotoweerstanden worden in een integervariabelen gestopt.
waarde_LDR_wit = analogRead(LDR_wit);

waarde_LDR_groen= analogRead(LDR_groen);

waarde_LDR_zwart= analogRead(LDR_zwart);

// de analoge waarden van de fotoweerstanden worden weergegeven van 0 tot 1023 en worden omgezet naar een
// waarde van 0 tot 255, deze laatste waarden zijn dan geschikt voor de aansturing van de motoren.
waarde_LDR_wit_map = map(waarde_LDR_wit, 0, 1023, 0, 255) ;

waarde_LDR_groen_map = map(waarde_LDR_groen, 0, 1023, 0, 255) ;

waarde_LDR_zwart_map = map(waarde_LDR_zwart, 0, 1023, 0, 255);

// een lage waarde wijst erop dat er licht in de buurt is. hieronder worden de waarden van de 3 fotoweerstanden
// vergeleken en daar worden dan acties aan verbonden.

if ((waarde_LDR_zwart < waarde_LDR_wit) && (waarde_LDR_zwart < waarde_LDR_groen))


{

// hieronder wordt de zin weergegeven hoe de motor moet draaien, de zin van de motor wordt ook
// bepaald op de wijze waarop de motor electrisch is aangesloten op het shield.
digitalWrite(motorgroepgroen,LOW);

// hieronder wordt het toerental van een motor aangegeven.
analogWrite(E1, waarde_LDR_groen_map-50);

digitalWrite(motorgroepwit, HIGH);

analogWrite(E2, waarde_LDR_wit_map-50);


}
else

{

if (waarde_LDR_wit < waarde_LDR_groen)

{

digitalWrite(motorgroepgroen,HIGH);

analogWrite(E1, waarde_LDR_groen_map);

digitalWrite(motorgroepwit, HIGH);

analogWrite(E2, waarde_LDR_wit_map);

}

if (waarde_LDR_wit > waarde_LDR_groen)

{

digitalWrite(motorgroepgroen,LOW);

analogWrite(E1, waarde_LDR_groen_map);

digitalWrite(motorgroepwit,LOW);

analogWrite(E2, waarde_LDR_wit_map);

}

}

// hieronder enkele regels die gebruikt worden om waarden weer te geven op de aangesloten laptop.



Serial.print(waarde_LDR_wit);

Serial.print(" ");

Serial.print(waarde_LDR_zwart);

Serial.print(" ");

Serial.println(waarde_LDR_groen);


delay(20);



}


 



 

Bemerk dat het wagentje hier veel wendbaarder is dan bij het lijnvolgerproject. Dit komt vooral doordat de draaizin van de motoren nu ook aangesproken wordt in de software.



 

Lichtvolger-robotwagen met IR-sensor gemonteerd op een servo.

In het pad van het licht komen soms obstakels voor. Bedoeling is dat de robot voor deze obstakels uitwijkt. Hij moet dus voorrang geven aan het ontwijken van obstakels dan aan het volgen van het licht. Om het detectieveld van de IR-sensor te vergroten is deze gemonteerd op een servo. Zo kijkt onze robot van links naar rechts en terug....





 



 

In bovenstaand filmpje zie je de IR-sensor gemonteerd op een servo. De IR-sensor is een Sharp 0A41SK F 15. In de datasheet van deze sensor vind je een grafiek waar je een formule over de afstand tot een object kan afleiden. Een voldoende accurate formule voor deze toepassing vind je terug in het programma verderop. De servo is een Micro Servo 9g FS90.



 

Schematische voorstelling: Op dit schema zie je de IR-sensor en de servo. Verder zie je dat we ook gebruik maken van de encoders. Wanneer de encoders zullen bewegen gaan die enkele ledjes laten knipperen...




 



 

Dit is dan de ultieme lichtvolger. Steevast het licht volgend doch op z'n hoede voor hindernissen...
Hieronder het programma...



 

#include <Servo.h>
Servo myservo;
int LDR_wit = 1;
int LDR_groen = 0;
int LDR_zwart = 2;
int IRpin = 5;
int waarde_LDR_wit;
int waarde_LDR_groen;
int waarde_LDR_zwart;
int waarde_LDR_wit_map;
int waarde_LDR_groen_map;
int waarde_LDR_zwart_map;
int motorgroepgroen = 7;
int E1 = 6;
int motorgroepwit = 4;
int E2 = 5;
int waardegroen;
int waardewit;
int encoderwit =2;
int led = 3;
int encodergroen = 10;
int led2 = 11;
int pos = 0;
int teller = 1;

void setup()
{
Serial.begin(9600);
myservo.attach(12);
pinMode(encoderwit, INPUT);
pinMode(led, OUTPUT);
pinMode(encodergroen, INPUT);
pinMode(led2, OUTPUT);
}

void loop()
{

for(pos = 0; pos < 180; pos += 1)
{
myservo.write(pos);
delay(10);
float volts = analogRead(IRpin) * 0.0048828125 *2 ;
float distance = 27*pow(volts, -1) ;
if (((pos == 90) && (distance < 40)))
{
while (distance < 50) {
volts = analogRead(IRpin) * 0.0048828125 *2 ;
distance = 27*pow(volts, -1) ;
//Serial.println(distance);
digitalWrite(motorgroepgroen,HIGH);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit, LOW);
analogWrite(E2, waarde_LDR_wit_map);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);
}
}
if (((pos == 45) && (distance < 40)) || ((pos == 30) && (distance < 40)) || ((pos == 60) && (distance < 40)) || ((pos == 10) && (distance < 40)) || ((pos == 75) && (distance < 40)) ||((pos == 20) && (distance < 40)) )
{
while (distance < 50) {
volts = analogRead(IRpin) * 0.0048828125 *2 ;
distance = 27*pow(volts, -1) ;
//Serial.println("te dicht");
digitalWrite(motorgroepgroen,HIGH);
analogWrite(E1, waarde_LDR_groen_map);
//analogWrite(E1, 250);
digitalWrite(motorgroepwit, HIGH);
analogWrite(E2, waarde_LDR_wit_map);
//analogWrite(E2, 250);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);
}


}
if (((pos == 135) && (distance < 40)) || ((pos == 120) && (distance < 40)) || ((pos == 150) && (distance < 40)) || ((pos == 170) && (distance < 40)) || ((pos == 105) && (distance < 40)) || ((pos == 160) && (distance < 40)) )
{
while (distance < 50) {
volts = analogRead(IRpin) * 0.0048828125 *2 ;
distance = 27*pow(volts, -1) ;
//Serial.println("te dicht");
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
//analogWrite(E1,250);
digitalWrite(motorgroepwit, LOW);
analogWrite(E2, waarde_LDR_wit_map);
//analogWrite(E2,250);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);
}


}

waarde_LDR_wit = analogRead(LDR_wit);
waarde_LDR_groen= analogRead(LDR_groen);
waarde_LDR_zwart= analogRead(LDR_zwart);
waarde_LDR_wit_map = map(waarde_LDR_wit, 0, 1023, 0, 255) ;
waarde_LDR_groen_map = map(waarde_LDR_groen, 0, 1023, 0, 255) ;
waarde_LDR_zwart_map = map(waarde_LDR_zwart, 0, 1023, 0, 255);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);

if ((waarde_LDR_zwart < waarde_LDR_wit) && (waarde_LDR_zwart < waarde_LDR_groen))
{
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit, HIGH);
analogWrite(E2, waarde_LDR_wit_map);
}
else
{
if (waarde_LDR_wit < waarde_LDR_groen)
{
digitalWrite(motorgroepgroen,HIGH);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit, HIGH);
analogWrite(E2, waarde_LDR_wit_map);
}
if (waarde_LDR_wit > waarde_LDR_groen)
{
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit,LOW);
analogWrite(E2, waarde_LDR_wit_map);
}
}

}

for(pos = 180; pos > 0; pos -= 1)
{
myservo.write(pos);
delay(10);
float volts = analogRead(IRpin) * 0.0048828125 *2 ;
float distance = 27*pow(volts, -1) ;
if (((pos == 90) && (distance < 40)))
{
while (distance < 50) {
volts = analogRead(IRpin) * 0.0048828125 *2 ;
distance = 27*pow(volts, -1) ;
//Serial.println("te dicht");
digitalWrite(motorgroepgroen,HIGH);
analogWrite(E1, waarde_LDR_groen_map);
//analogWrite(E1,250);
digitalWrite(motorgroepwit, LOW);
analogWrite(E2, waarde_LDR_wit_map);
//analogWrite(E2,250);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);
}
}
if (((pos == 45) && (distance < 40)) || ((pos == 30) && (distance < 40)) || ((pos == 60) && (distance < 40)) || ((pos == 10) && (distance < 40)) || ((pos == 75) && (distance < 40)) ||((pos == 20) && (distance < 40)) )
{
while (distance < 50) {
volts = analogRead(IRpin) * 0.0048828125 *2 ;
distance = 27*pow(volts, -1) ;
//Serial.println("te dicht");
digitalWrite(motorgroepgroen,HIGH);
analogWrite(E1, waarde_LDR_groen_map);
//analogWrite(E1,250);
digitalWrite(motorgroepwit, HIGH);
analogWrite(E2, waarde_LDR_wit_map);
//analogWrite(E2,250);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);
}


}
if (((pos == 135) && (distance < 40)) || ((pos == 120) && (distance < 40)) || ((pos == 150) && (distance < 40)) || ((pos == 170) && (distance < 40)) || ((pos == 160) && (distance < 40)) || ((pos == 105) && (distance < 40)) )
{
while (distance < 50) {
volts = analogRead(IRpin) * 0.0048828125 *2 ;
distance = 27*pow(volts, -1) ;
//Serial.println("te dicht");
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
//analogWrite(E1,250);
digitalWrite(motorgroepwit, LOW);
analogWrite(E2, waarde_LDR_wit_map);
//analogWrite(E2,250);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);
}


}

waarde_LDR_wit = analogRead(LDR_wit);
waarde_LDR_groen= analogRead(LDR_groen);
waarde_LDR_zwart= analogRead(LDR_zwart);
waarde_LDR_wit_map = map(waarde_LDR_wit, 0, 1023, 0, 255) ;
waarde_LDR_groen_map = map(waarde_LDR_groen, 0, 1023, 0, 255) ;
waarde_LDR_zwart_map = map(waarde_LDR_zwart, 0, 1023, 0, 255);
int encoderwitwaarde = digitalRead(encoderwit);
int encodergroenwaarde = digitalRead(encodergroen);
digitalWrite(led,encoderwitwaarde);
digitalWrite(led2,encodergroenwaarde);

if ((waarde_LDR_zwart < waarde_LDR_wit) && (waarde_LDR_zwart < waarde_LDR_groen))
{
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit, HIGH);
analogWrite(E2, waarde_LDR_wit_map);
}
else
{
if (waarde_LDR_wit < waarde_LDR_groen)
{
digitalWrite(motorgroepgroen,HIGH);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit, HIGH);
analogWrite(E2, waarde_LDR_wit_map);
}
if (waarde_LDR_wit > waarde_LDR_groen)
{
digitalWrite(motorgroepgroen,LOW);
analogWrite(E1, waarde_LDR_groen_map);
digitalWrite(motorgroepwit,LOW);
analogWrite(E2, waarde_LDR_wit_map);
}
}
}
}



 

Eco-wagen: Het robot-wagentje moet zien te overleven met de energie die hij onderweg op z'n zonnepaneel kan sprokkelen. Deze oefening is niet tot een goed einde gebracht en dat is dat de robot nog altijd 'dood' gaat na een tijdje. Hieronder hetgene wat ik wel al heb en 't is aan u om het te verbeteren want er kan nog veel verbeterd worden maar ik heb het nu wel een beetje gehad met deze robotwagen.





 

de voorkant van Eco'tje: Als dak heeft deze wagen een zonnepaneeltje. Verder op de foto ziet u dat de wagen zich naar het licht richt met 2 foto-weerstanden. Om objecten te ontwijken heeft deze wagen ook nog 2 IR-sensoren. De analoge uitgangen van alle sensoren staan via het breadbord en hier en daar wat extra weerstanden in verbinding met de Arduino-controller.




 

de zijflank: Hier een redelijk goed zicht op de motordriver die op de Arduino geklikt staat.




 

achterkant is de energiekant: zicht op de laadregelaar en de Accu.




 

sombere dagen: Nauwelijks 10mA kwam er binnen via het zonnepaneel in sombere dagen. In rust gebruikte de Arduino en z'n motorshield bijna 100mA...




 

Beetje babbelen over energie:
Op zonnige dagen was de stroom van het paneel natuurlijk veel beter. Dan was het een stukje boven 200mA. De hellingshoek van het zonnepaneel speelde ook een belangrijke rol in de stroom die van het zonnepaneel kwam. Van mijn robotwagentje was die niet scherp genoeg... Om het stroomverbruik in rust nog wat te laten zakken liet ik de controller inslapen. De verbruiksstroom zakte toen naar 60mA. Het was wel geen sinecure om de controller weer te laten ontwaken via een externe trigger. Verder kwam het er altijd op neer om de robot zo weinig mogelijk te laten bewegen want de 4 motoren trokken nogal rap de accu slap. Dat kwam omdat het wagentje om en bij de 3kg woog. (het logge zonnepaneel en de zware accu... ) Het stroomverbruik bij een motor die niet meer draaide maar toch bekrachtigd werd was om en bij 470mA. ...en het gebeurde veel dat
ze niet meer draaiden door de manouvres die werden uitgevoerd op zoek naar licht . Een draaiende motor die geen last te verslepen had verbruikte ongeveer 70mA. Helaas waren er hier wel lasten te verslepen met name de volledige wagen dus lag dat verbruik ook aanzienlijk hoger. Tot slot werd de plaats waar de wagen werd stilgehouden om te zonnen volledig bepaalt door het signaal van de fotoweerstanden en niet door de maximum stroom die door het zonnepaneel werd afgegeven. Dit laatste is ook een tekortkoming!

dus:
1)grotere accucapaciteit versus gewicht accu.
2)positiebepaling zonnen laten afhangen van maxstroomafgifte zonnepaneel.
3)hellingshoek zonnepaneel optimaliseren.
4)sleep in modus arduino optimaliseren.
5)gewicht wagen
6)betere code

't is aan u... 'k heb de onderdelen van de wagen voor iets anders nodig...