drti

Prvi koraki v Arduino – vožnja po črti in izogibanje oviri

 

Milan Gaberšek in Slavko Kocijančič , članek v reviji TIM, številka 3, letnik 2020/21

 

V trinajstem zaporednem prispevku na temo Prvi koraki v Arduino bomo obstoječi avtomobilček s krmilnikom Arduino nadgradili tako, da se bo poleg vožnje po črti izogibal oviram na poti. Konstrukcijo avtomobilčka bi lahko pustili nespremenjeno, a da ne bomo samo programirali, bomo z majhnim dodatkom dosegli lažje gibanje.

 

Programsko kodo si preko kopiraj/prilepi prenesite v Arduino IDE, da vam ne bo treba pretipkavati.  

 

 

//
// Program Arduino -
// Vožnja po črti in izogibanje oviri

// Pini za tipki za zaznavanje ovire 
const int pinTipkaLeva = 2;
const int pinTipkaDesna = 4;

// Led bela lučka na D8
const int led = 8;
// Svetlobno spremenljivi upor na A0
const int senzorSvetlobe = A0;
// Vrednost jakosti odbite svetlobe
// bomo shranili v spremenljivko
int jakostSvetlobe = 0;
// S testnim programom smo izmerili jakost 
// na črni in beli podlagi, vnesemo ju
// v jakostCrna in jakostBela
int jakostCrna = 100; // Jakost na crni podlagi
int jakostBela = 400; // Jakost na beli podlagi  
// Povprečje obeh vrednosti shranimo v refSvetloba
float refSvetlobe = (jakostCrna + jakostBela) / 2; 

// Pini za oba motorčka (preko modula L9110)
const int pinMotorA1 = 9;
const int  pinMotorA2 = 10;
const int pinMotorB1 = 11;
const int  pinMotorB2 = 12;

// Nastavitev vhodov in izhodov krmilnika Arduina
void setup() {
  // Branje podatkov preko
  // serijskega vmesnika USB
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  // Nastavitev tipk
  pinMode(pinTipkaLeva, INPUT_PULLUP);
  pinMode(pinTipkaDesna, INPUT_PULLUP);  
  // svetleča dioda bo vklopljena ves čas
  digitalWrite(led, HIGH);
  // Nastavitev izhodov za motorčka
  pinMode(pinMotorA1, OUTPUT);
  pinMode(pinMotorA2, OUTPUT);
  pinMode(pinMotorB1, OUTPUT);
  pinMode(pinMotorB2, OUTPUT);
}

// Prva parametra povesta, katera pina poganjata motor
// tretji parameter pove smer:
// -1 kolo se vrti nazaj, 0 miruje, 1 kolo se vrti naprej
void motor(int pinMotor1, int pinMotor2, int nSmer) {
  if (nSmer == 1) { // Naprej
    digitalWrite(pinMotor1, HIGH);
    digitalWrite(pinMotor2, LOW); 
  } 
  else if (nSmer == -1) { // Nazaj
    digitalWrite(pinMotor1, LOW);
    digitalWrite(pinMotor2, HIGH); 
  }
  else  { // Se ne vrti
    digitalWrite(pinMotor1, LOW);
    digitalWrite(pinMotor2, LOW);
  }
}

void vrtiVDesno(){
  motor(pinMotorA1, pinMotorA2, 1);
  motor(pinMotorB1, pinMotorB2, -1);
}

void vrtiVLevo(){
  motor(pinMotorA1, pinMotorA2, -1);
  motor(pinMotorB1, pinMotorB2, 1);
}

void peljiNaprej(){
  motor(pinMotorA1, pinMotorA2, 1);
  motor(pinMotorB1, pinMotorB2, 1);
}

void peljiNazaj(){
  motor(pinMotorA1, pinMotorA2, -1);
  motor(pinMotorB1, pinMotorB2, -1);
}

void ustavi(){
  motor(pinMotorA1, pinMotorA2, 0);
  motor(pinMotorB1, pinMotorB2, 0);
}

// Spremenljivka za vklop(true)
// oziroma izklop(false) sledenja po črti
int voznjaPoCrti = true;
void loop() {
  // Z ukazom analogRead preberemo
  // digitalno jakost odbite svetlobe
  jakostSvetlobe = analogRead(senzorSvetlobe);
  // Dobljeni podatek izpišemo na zaslon
  Serial.println(jakostSvetlobe);
  delay(10); // Počakamo na podatke
  // Preverimo, ali je pritisnjena tipka tipalk
  if ( (digitalRead(pinTipkaLeva) == LOW)
    || (digitalRead(pinTipkaDesna) == LOW) ) {
    // Koda za izogibanje oviri
    peljiNazaj(); delay(100);
    vrtiVLevo(); delay(400);
    peljiNaprej(); delay(500);
    vrtiVDesno(); delay(280);
    peljiNaprej(); delay(820);
    vrtiVDesno(); delay(350);
    peljiNaprej(); delay(400);
    vrtiVLevo(); delay(350);
    // Za lažje nastavljanje časov 
    // avtomobilček še ustavimo
    ustavi();
  } else {
    // Vklop kode za vožnjo po črti
    if (voznjaPoCrti == true) {  
      // Iskanje črte: 
      // Če je jakost odbite svetlobe
      // manjša od referenčne, zavrtimo 
      // v levo, drugače v desno 
      if (jakostSvetlobe <= refSvetlobe) {
        vrtiVLevo(); delay(20);
      } else {
        vrtiVDesno(); delay(20);
      }    
      peljiNaprej(); delay(10);
      ustavi(); // Ustavi
    }
  } 
}