Tai pats paprasčiausias važiuojantis robotukas, galintis išvengti susidūrimų ir apvažiuoti kliūtis. Čia aprašysiu, kaip tokį robotuką pasidaryti. Šiam projektui reikės: Arduino, LM298N shieldo, dviejų SHARP GP2D12 analoginių opto daviklių ir važiuojančios platformos su dviem varikliais, tiks bet koks važiuojantis žaislas, kurio ratams sukti naudojami elektros varikliai. Jei turite laiko, tokią platformą galite ir patys lengvai pasidaryti.

Akims šis robotukas naudoja SHARP GP2D12 analoginius IR atstumo jutiklius. Jie geri tuo, kad yra labai tikslūs, mato net iki 80 cm ir nebijo išorinių šviesos šaltinių, tad robotui dzin ar jis artėja prie lango ar prie sienos, signalas bus toks pat. Vienintelė šių daviklių problema, kad priartėjus prie kliūties arčiau kaip 5 cm. davikliai nieko nebemato. Tad robotas ne visada išvengs kliūčių. O vietoj GP2D12 geriau rekomenduoju GP2D120 daviklius, nes mažam robotukui jie labiau pritaikyti, jų matymo riba nuo 4 iki 30 cm. Šie atstumo jutikliai prijungti prie 1-ojo ir 3-ojo arduino analoginio įėjimo. Tik nepadarykit klaidos ir nenusipirkite skaitmeninių atstumo jutiklių :)

Ant Arduino Duamilanove plokštės uždėtas L298N shieldas, jis gali valdyti 2 iki 2A srovės DC variklius. Nors L298N Arduino shieldų yra didžiulė įvairovė, rekomenduoju šį, jau išbandytas.

Kad būtų galima stebėti ratų sukimosi greitį, prie abiejų ratų įtaisiau LTH209-1 IR foto daviklius. Šie davikliai reaguoja į 2 – 4mm atstumu esantį paviršių. Tokius daviklius naudojau pirmą kartą, tad pagalvojau, kad jie skiria juodą spalvą nuo baltos. Atsispausdinau ant balto popieriaus juodų juostelių apskritimus. Juos pritvirtinau prie ratų, bet greit paaiškėjo, kad be reikalo dirbau. Šiuose davikliuose signalo stiprumas tarp juodos ir baltos skiriasi tik apie 10%. Nusprendžiau daryti kitaip, popieriniuose apskritimuose išpjausčiau plonas juosteles, tuomet supratau, kad davikliai dirba. Tačiau signalo lygis iš daviklio buvo tik 2V amplitudės. Tokį signalą galėjau prijungti tik prie analoginio arduino įėjimo, o man reikėjo gražaus skaitmeninio 6V amplitudės impulso, kad galėčiau perduoti rato sukimosi pertraukimą į arduino. O kodėl pertraukimą? Palieku pagalvoti patiems :) Na o čia pateikiu pilną roboto ratų sukimosi kontrolės schemą:

Čia panaudojau populiarujį LM393N komparatorių, kurį buvau išlitaves iš kažkur jau net nepamenu. Schema paskaičiuota robotukui, kurio maitinimas yra 5-6V. Jei maitinimas didesnis negu 6V, tuomet reikia perskaičiuoti LTH209-1 spinduolio srovę ir pakeisti rezistorius R3, R6 į didesnius. O komparatorių galima naudoti net ir iki 30V. OUT1, tai kairiojo rato signalo išėjimas prijungtas prie arduino plokštės 3-iojo skaitmeninio pino. OUT2 – dešiniojo rato, prijungtas prie arduino plokštės 1-ojo skaitmeninio pino. Kaip vėliau paaiškėjo Duamilanove, nesugeba vienu metu apdoroti trijų pertraukimų, nes 1-asis pertraukimo pinas naudojamas serial interfeisui, taigi negali būti dalinamas su dešiniojo rato davikliu. Čia buvo staigmena, kurios nesitikėjau :( . Aišku yra variantas išjungti serial, bet kaip tuomet derinti programą?
Robotas maitinamas, nuo vieno 6V maitinimo šaltinio – keturi Alkaline AA tipo elementai po 1,5V. Su maniškiais varikliais tikrai ilgam užteko. Toks sprendimas nėra labai vykes, nes galios ir skaitmeninėms grandims rekomenduojama atskirti maitinimą, bet tingėjau :) Taigi nusekus batareikoms iki 4,7V, kai koks ratas pasisuka greičiau robotas pradeda “apmirinėti”.

Roboto programa:

// Greicio davikliai prijungti prie 3 ir 1 pino
const int fotoDaviklisKaire = 3;
const int fotoDaviklisDesine = 1; //nenaudosim (zr. paaiskinima)
// Kairiojo rato greicio daviklio impulsus sumuosime i skaitliuka
int skaitliukasKaire = 0;
// Greicio konstantos (nuo 0 iki 255) Jei maziau negu 100, jau ratas pats nebeisisuka
const int labaiLetai = 100;
const int letai = 130;
const int normaliai = 170;
const int greitai = 195;
const int labaiGreitai = 255;
// Desiniojo variklio (A) valdymo pinai per kuriuos siusim komandas i L298N valdikli
const int kryptis1PinA = 13;
const int kryptis2PinA = 12;
const int greicioPinasDesiniam = 10;
// Kairiojo variklio (B) valdymo pinai per kuriuos siusim komandas i L298N valdikli
const int kryptis1PinB = 11;
const int kryptis2PinB = 8;
const int greicioPinasKairiam = 9;
// Varikliu greiciai bus reguliuojami siais kintamaisiais
int desinioGreitis;
int kairioGreitis;
// Krypti keisime siuo kintamuoju
int kryptis;
// Nuvaziuota atstuma matuosime siuo kintamuoju
int atstumas;
// Cia fiksuosim roboto paleidimo laika
int time;
// #########################  Inicializacija
void setup() {
  // Desiniojo variklio valdymo pinus pervedame i OUTPUT rezima
  pinMode(kryptis1PinA, OUTPUT);
  pinMode(kryptis2PinA, OUTPUT);
  pinMode(greicioPinasDesiniam, OUTPUT);

 // Kairiojo variklio valdymo pinus pervedame i OUTPUT rezima
  pinMode(kryptis1PinB, OUTPUT);
  pinMode(kryptis2PinB, OUTPUT);
  pinMode(greicioPinasKairiam, OUTPUT);
 // Is greicio davikliu paimsime signala, todel pinus pervedam i INPUT rezima
  pinMode(fotoDaviklisKaire, INPUT);
  pinMode(fotoDaviklisDesine, INPUT);   //nepanaudojamas su Duamilanove

 // Nuimam paleidimo laika
  time = millis();
 // Pradiniai varikliu greiciai = 0, o kryptis i prieki
  desinioGreitis = 0;
  kairioGreitis = 0;
  kryptis = 1;

 // Inicializuojama pertraukimo funkcija - kairiojoRatoPertraukimas, kuri reaguoja i kylanti impulso fronta is kairiojo greicio daviklio.
 // 1 reiskia, kad pertraukimas paimamas  nuo 3-iojo pino.

  attachInterrupt(1, kairiojoRatoPertraukimas, RISING);

 // Derinimui inicializuojam serial interfeisa
  Serial.begin(9600);
}
// ################# Pagrindinis ciklas
void loop() {

// Varikliu greicio reguliavimas
  analogWrite(greicioPinasDesiniam, desinioGreitis);
  analogWrite(greicioPinasKairiam, kairioGreitis);

// xx impulsu reiks nuvaziuota metra, reikes individualiai isismatuoti savo robotui
 if (skaitliukasKaire >= 57)  {
    atstumas = atstumas + 1;
    skaitliukasKaire = 0;
 }
// Nuskaitome SHARP GP2D12 atstumo daviklius
  int atstumoJutiklisKaire = analogRead(1);
  delay(10);
  int atstumoJutiklisDesine = analogRead(5);
  delay(10);
// Nustatytus atstumus konvertuojame i intervala 100-200
  atstumoJutiklisKaire = map(atstumoJutiklisKaire,150,560,100,200);
  atstumoJutiklisDesine = map(atstumoJutiklisDesine,150,560,100,200);

  //64 - 128 greita zona
  //130 - 160 letinam
  //160 - 180 stabdom
  // 180 - 190 sukames atgal

  //Isvedam duomenis i terminala
  Serial.print(" Nuvaziuota m: ");
  Serial.print(skaitliukasKaire);
  Serial.print(" - ");
  Serial.print(atstumas);
  Serial.print(" | Greiciai: ");
  Serial.print(desinioGreitis);
  Serial.print(" - ");
  Serial.print(kairioGreitis);
  Serial.print(" | Atstumai: ");
  Serial.print(atstumoJutiklisKaire);
  Serial.print(" - ");
  Serial.print(atstumoJutiklisDesine);
  Serial.println();
  delay(50);
//Roboto logika
if ((atstumoJutiklisDesine <=100) && (atstumoJutiklisKaire <=100)) {
    kryptis = 1;
    kairioGreitis = greitai;
    desinioGreitis = greitai;
      }

if ((atstumoJutiklisDesine <=120) && (atstumoJutiklisDesine >=101) && (atstumoJutiklisKaire <=120)) {
    kryptis = 1;
    kairioGreitis = letai;
    desinioGreitis = greitai;
      }

if ((atstumoJutiklisDesine <=150) && (atstumoJutiklisDesine >=121) && (atstumoJutiklisKaire <=120)) {
    kryptis = 1;
    kairioGreitis = 0;
    desinioGreitis = greitai;
      }

if ((atstumoJutiklisDesine <=180) && (atstumoJutiklisDesine >=151) && (atstumoJutiklisKaire <=120)) {     kryptis = 4;     kairioGreitis = greitai;     desinioGreitis = greitai;       }     if  (atstumoJutiklisDesine >=181) {
    kryptis = 2;
    kairioGreitis = greitai;
    desinioGreitis = greitai;
      }
if ((atstumoJutiklisKaire <=120) && (atstumoJutiklisKaire >=101) && (atstumoJutiklisDesine <=120) ) {
    kryptis = 1;
    desinioGreitis = letai;
    kairioGreitis = greitai;
      }
if ((atstumoJutiklisKaire <=150) && (atstumoJutiklisKaire >=121) && (atstumoJutiklisDesine <=120)) {
    kryptis = 1;
    desinioGreitis = 0;
    kairioGreitis = greitai;
  }
if ((atstumoJutiklisKaire <=180) && (atstumoJutiklisKaire >=151) && (atstumoJutiklisDesine <=120)) {     kryptis = 3;     desinioGreitis = greitai;     kairioGreitis = greitai;   }     if  (atstumoJutiklisKaire >=181) {
    kryptis = 2;
    desinioGreitis = greitai;
    kairioGreitis = greitai;
  }  

if (kryptis == 1 ) {
  // vaziuojam pirmyn
    digitalWrite(kryptis1PinA, LOW);
    digitalWrite(kryptis2PinA, HIGH);
    digitalWrite(kryptis1PinB, HIGH);
    digitalWrite(kryptis2PinB, LOW);
}
if (kryptis == 2) {
  // vaziuojam atgal
    digitalWrite(kryptis1PinA, HIGH);
    digitalWrite(kryptis2PinA, LOW);
    digitalWrite(kryptis1PinB, LOW);
    digitalWrite(kryptis2PinB, HIGH);
}
if (kryptis == 3) {
  // vaziuojam desinen
    digitalWrite(kryptis1PinA, HIGH);
    digitalWrite(kryptis2PinA, LOW);
    digitalWrite(kryptis1PinB, HIGH);
    digitalWrite(kryptis2PinB, LOW);
    }
if (kryptis == 4) {
  // vaziuojam kairen
    digitalWrite(kryptis1PinA, LOW);
    digitalWrite(kryptis2PinA, HIGH);
    digitalWrite(kryptis1PinB, LOW);
    digitalWrite(kryptis2PinB, HIGH);
    }
// Pagrindinio ciklo pabaiga
}
// Apsirasom pertraukimo funkcija greiciui matuoti
 void kairiojoRatoPertraukimas(){
   if (digitalRead (fotoDaviklisKaire) == LOW){
     skaitliukasKaire = skaitliukasKaire + 1;
     }
   }

Žemiau parodyta kaip viskas sujungta.

Reikia tik nepamiršti, kad ant Arduino plokštės turi  būti uždėtas L298N variklių valdiklis. Prie kurio prijungiami varikliai, taip kaip pavaizdota žemiau.

L298N shieldo tumbleriukai turi būti nustatyti, kaip parodyta žemiau:

Na o štai čia matyti kaip atrodo surinktas robotas

Čia padėjau visus reikalingus failus tokio roboto konstravimi. Sėkmės.