Krmiljenje zapornice

Zahteve:

S tipko sprožimo dviganje zapornice. Zapornica je dvignjena 3 sekunde, nakar se začne spuščati. Pod zapornico je nameščen IR senzor, ki zaznava oviro. V primeru prisotnosti ovire zapornica ostane dvignjena, če pa ovira nastopi med spuščanjem, se spuščanje zapornice ustavi, zapornica se dvigne v zgornji položaj. Zapornica ostane dvignjena tako dolgo, dokler je prisotna ovira. Med gibanjem zapornice sveti LED dioda, v premeru prisotnosti ovire pa LED dioda utripa.

Zapornica je nameščena na servo motor RS-2, za senzor ovire pa je uporabljen IR (infrardeči) senzor KEYES tip KY-032.

Uporabljen je tudi LCD display 16x2 za izpis posameznih podatkov. Preko serijskega motorja lahko spremljamo vrednost na IR senzorju oziroma analognem vhodu, kamor je priključen.

Servo motor:

Servo motorji so samostojne električne naprave, ki premikajo in obračajo dele strojev s precizno natančnostjo. Najdemo jih skoraj povsod, od igrač do avtomobilov. Poleg vezic za napajanje je srce servo motorja majhen enosmerni motor, kateri se vrti pri visokih obratih. Ker ima zelo malo navora, ima zraven zobniški prenos, ki visoke obrate z malim navorom pretvori v počasne obrate z velikim navorom. Motor vsebuje še elektronsko vezje na tiskani ploščici, kjer se nahaja senzor. Ta prepozna za koliko se je zavrtela gred motorja. Gred motorja se lahko premika v obsegu 180°, od -90°do +90°. Pozicija gredi motorja je odvisna od dolžine impulza na priključku za signal, frekvenca teh impulzov pa je okoli 50 Hz. Položaj gredi torej določamo s PWM impulzi, ki trajajo od cca. 0,7 ms do 2 ms. Dolžina impulzov PWM signala od 0,7 ms do 1 ms zavrtijo gred servo motorja v smeri urinega kazalca, dolžine od 1,7 ms do 2 ms pa gred zavrtijo proti smeri urinega kazalca. Pri standardnem servo motorju dolžina impulzov PWM signala 1,5 ms zavrtijo gred v položaj sredine.

Slika 1: Zasuk servo motorja v odvisnosti od dolžine PWM inpulzov.

IR senzor KY-032:

Senzor vsebuje infrardeči oddajnik in sprejemnik. Oddajnik oddaja infrardečo svetlobo določene frekvence. V primeru ovire, se ta svetloba od ovire odbije nazaj do infrardečega sprejemnika, ki da na svojem izhodu signal. S potenciometrom, nameščenim na senzorju lahko spreminjamo občutljivost senzorja. Ta znaša od 2 cm do 40 cm. Za delovanje potrebuje napetost napajanja od 3,3 V do 5 V.

Slika 2: IR senzor KY-032.

Slika 3: Sestava elementov na eksperimentalno ploščico in priključitev na razvojno ploščo Arduino Uno

Uporabljeni elementi:

- Razvojna plošča Arduino Uno

- LCD display 16x2

- Servo motor RS-2

- IR senzor KY-032

- Tipka

- Trimer potenciometer 4,7 kohm

- LED dioda, 5 mm, modra

- Upor 470 ohm

- Upor 10 kohm

- Vezice

 //Program za krmiljenje zapornice:

 /*

 Krmiljenje zapornice.

 Avtor: Milan Ivič

 Januar 2014

 */ 

 #include <Servo.h>             //Vključitev knjižnice za servo motor.

 #include <LiquidCrystal.h>     //Vključitev knjižnice za LCD.

 Servo servo;

 int Zapornica_spodaj = 0;         //Inicializacija za servo motorček, zapornica je spodaj (0°).

 int Zapornica_zgoraj = 70;        //Inicializacija za servo motorček, zapornica je zgoraj (70°).

 int Tipka = 8;                    //Tipka za dvigovanje zapornice => pin 8.

 int LED = 10;                     //LED dioda sveti v času gibanja zapornice in utripa v primeru prisotnosti ovire.

 //Ovira:

 int Senzor_ovire = A4;               //Senzor (IR) za zaznavanje ovire pod zapornico => analogni vhod A4.

 int Vrednost_senzorja;               //V spremenljivko Vrednost_senzorja je shranjuje vrednost na A4.

 LiquidCrystal lcd(2,3,4,5,6,7);      //Priključki LCD na pine Arduino.

 void setup()

 {

   Serial.begin(9600);

   pinMode(Senzor_ovire, INPUT);        //Analogni vhod A4, kamor je priključen senzor ovire.

   pinMode(Tipka, INPUT);               //Pin 8 je vhod => Tipka.

   pinMode(LED, OUTPUT);                //Pin 10 je izhod => LED.

   servo.attach(9);                     //Servo motorček je priključen na pin 9.

   servo.write(Zapornica_spodaj);       //Zavrti servo v spodnji položaj.

   lcd.begin(16,2);                     //LCD 2x16 => dve vrstici, vsaka po 16 znakov.

   lcd.setCursor(3,0);            

   lcd.print("Krmiljenje");             

   lcd.setCursor(3,1);            

   lcd.print("zapornice");

   delay(2000);                         //Počakaj 2 sekundi (2000 ms), nato počisti LCD.

   lcd.clear();

 }

 void loop()          //Glavna zanka.

 {

   Dvigovanje_zapornice();      //Klicanje funkcije z imenom Dvigovanje_zapornice.

 }

 void Dvigovanje_zapornice()

 {

   lcd.setCursor(0,0);

   lcd.print("Za dvig pritisni");

   lcd.setCursor(2,1);

   lcd.print("na tipko");

   int Stanje_tipke;                      //Deklariranje lokalne spremenljivke, vanjo se shranjzje stanje tipke.

   Stanje_tipke = digitalRead(Tipka);     //Branje stanja tipke.  

   if(Stanje_tipke == HIGH)               //Ali je tipka sklenjena?                

   {                                      //Blok  med { } se izvrši, če je tipka sklenjena (če je pogoj resničen).

    lcd.clear();    

    lcd.setCursor(2,0);

    lcd.print("Dvigovanje");

    lcd.setCursor(2,1);

    lcd.print("zapornice");      

     for(int i = 0; i < 70; i++)          //Zanka for se izvede 70 krat od 0 do 70 po koraku 1.

     {

      digitalWrite(LED, HIGH);            //V času dvigovanja zapornice LED dioda sveti.

      servo.write(i);                     //Ob vsakem obhodu zanke for se zavrti servo motor za 1°.

      delay(10);                          //Za počasnejše dvigivanje zapornice.

      digitalWrite(LED, LOW);

     }

    lcd.clear();    

    delay(3000);                          //Zapornica je 3 sekunde dvignjena.

    Ovira();                              //Klicanje rutine (podprograma) z imenom ovira.

   }

   else                                   //Tipka ni sklenjena, ponovno preveri stanje tipke.

   {

     Dvigovanje_zapornice();

   }

 }

 void Ovira()        //Rutina (podprogram) Ovira().

 {   

  digitalWrite(LED, HIGH);            //Vklopi LED za utripanje če je ovira.

  delay(150);                                   //Čas med vklopom in izklopom LED za utripanje. 

  Vrednost_senzorja = analogRead(Senzor_ovire);     //Branje vrednosti na analognem vhodu A4 (IR senzor).

  Serial.println(Vrednost_senzorja);                //Izpis btine vrednosti na serijskem monitorju.

  if (Vrednost_senzorja > 250)                      //Blok se izvede, če ni ovire.

  {

    lcd.clear();

    lcd.setCursor(2,0);

    lcd.print("Spuscanje");

    lcd.setCursor(2,1);

    lcd.print("zapornice");    

    for(int j = 70; j>0; j--)             //Zanka for se izvaja po korakih 1 od 70do 0 (če ni ovire).

    {             

      Vrednost_senzorja = analogRead(Senzor_ovire);

       if (Vrednost_senzorja > 250)         //Ali je nastala ovira med spuščanjem zapornice? Ni ovire?

       {

        digitalWrite(LED, HIGH);            //V času spuščanja zapornice mora LED dioda svetiti.

        servo.write(j);                     //Ob vsakem obhodu zanke for se zavrti servo motor za 1°.

        delay(10);                          //Za počasnejše spuščanje zapornice.

        digitalWrite(LED, LOW);             //Zapornica je spodaj, izklopi LED diodo.

       }

       else

       {                    //Je ovira, ki je nastala med spuščanjem zapornice.

        j=0;                //Inicializiramo j, da servo začne spuščati zapornico iz izhodiščnega (zgornjrga) položaja.

        Ovira();            //Idi na rutino (podprogram) Ovira().

       }

     }

   lcd.clear();

  } 

  else          //Ovira je prisotna, preden se je zapornica začela spuščati.

  {

    digitalWrite(LED, LOW);       //Izklopi LED za utripanje, če je prisotna ovira.

    delay(150);                   //Čas med izklopom in vklopom LED za utripanje.

    lcd.clear();

    lcd.setCursor(2,0);

    lcd.print("P O Z O R");

    lcd.setCursor(2,1);

    lcd.print("O V I R A !!");    

    servo.write(Zapornica_zgoraj);            //Zapornica v zgornjrm položaju (70°).

    Vrednost_senzorja = analogRead(Senzor_ovire);

    Ovira();   

  }  

}

Programsko okolje:

Odprto-kodno okolje Arduino omogoča enostavno pisanje kode, ki jo naložimo v ustrezno razvojno ploščo, v našem primeru Arduino Uno. Programsko Arduinovo integrirano razvojno okolje IDE (Integrated development environment) lahko prenesete iz Arduinove spletne strani http://arduino.cc/en/main/software. Zadnja verzija je Arduino 1.6.1 (26. marec 2015), na njihovi domači spletni strani (Arduino home) pa najdemo koristne informacije o programskem jeziku, knjižnice, primere ...

Naj tukaj še omenim, da so vse kode, napisane v poglavju za Intel Galileo kompatibilne z Arduinom in jih lahko uporabite za razvojno ploščo Arduino Uno (seveda v Arduinovem okolju).

Dodatni opis programa:

V jeziku C++ je program običajno razdeljen na funkcije. Vsak program ima vsaj eno funkcijo, v tem primeru je to glavna funkcija (void loop()). Veliko število funkcij je v jeziku C++ že narejenih in so shranjene v knjižnicah. Če želimo katero uporabiti, moramo v program vključiti knjižnico, v kateri se nahaja. Znaka { } označujeta začetek in konec funkcije.

Glavna funkcija je void loop() in je namenjena koordiniranju dela ostalih funkcij. Programi so v jeziku C++ sestavljeni iz funkcij, kar povečuje preglednost programa, obenem pa omogoča, da ponavljajočih se delov programa ni potrebno pisati večkrat ampak ta del zapišemo kot funkcijo, ki jo pokličemo, ko jo potrebujemo.

Slika 4: Glavna zanka void loop(), klicanje funkcije Dvigovanje_zapornice() in rutina (podprogram) Ovira()

Iz glavne zanke void loop() v našem primeru kličemo le eno funkcijo, funkcijo Dvigovanje_zapornice(). V njej najprej izpišemo na LCD "Za dvig pritisni na tipko". Nato deklariramo lokalno spremenljivko (deluje le v tej funkciji) Stanje_tipke, kamor se ob vsakem obhodu funkcije shranjuje vrednost stanja tipke (0 če tipka ni sklenjena in 1, če je tipka sklenjena).

- Če je tipka sklenjena, se izvede blok if stavka: Na LCD se izpiše "Dvigovanje zapornice". Nato z uporabo zanke for dvignemo zapornico v gornji položaj (servo motor zavrtimo v položaj 70°). Zanko for smo uporabili zato, da se zapornica dviguje počasneje. Izvede se 70-krat, po koraku 1 in z zakasnitvijo 10 ms. Vsakih 10 ms se servo motorček zavrti za 1°, dokler ne doseže položaja 70°. Zapornica ostane dvignjena 3 sekunde, nakar kličemo rutino (podprogram) Ovira(), kjer preverjamo prisotnost ovire. Ob prisotnosti ovire se zapornica ne sme spuščati.

- Če tipka ni sklenjena, se blok if stavka ne izvede in program ponovno preverja stanje tipke.

V rutini (podprogramu) Ovira() uredimo potrebno za utripanje LED diode, deklariramo lokalno spremenljivko Vrednost_senzorja, kamor se shranjuje prebrana vrednost na analognem vhodu A4. Na ta analogni vhod je priključen IR senzor. Na analognem vhodu A4 je vrednost okoli 10 ko je prisotna ovira in vrednost okoli 1020, ko ni ovire. Podatek dobimo izpisan na serijskem monitorju:

Slika 5: Izpis na serijskem monitorju v odvisnosti od prisotnosti ovire

Vrednost je lahko le v območju od 0 do 1023 (10-bitni podatek). Mi smo določili mejo 250. Če je vrednost večja od 250 pomeni da ni prisotne ovire, če pa je manjša pomeni, da je IR senzor zaznal oviro. Stanje ovire preverjamo s stavkom if.

- V primeru ko ni prisotne ovire, se začne zapornica spuščati, za kar smo zopet uporabili zanko for, po korakih 1° vsakih 10 ms od položaja 70° do položaja servo motorčka 0°. Ker pa lahko nastopi ovira tudi med spuščanjem zapornice, po vsakem obhodu zanke for preverjamo stanje IR senzorja. Če med spuščanjem zapornice IR senzor ni zaznal ovire, se zapornica spusti do spodnjega položaja (servo motorček v stanju 0°). Če pa je IR senzor med spuščanjem zapornice zaznal oviro, postavimo vrednost spremenljivke (števca) j na 0 in ponovno kličemo rutino (podprogram) Ovira(). Števec j moramo postaviti na 0 zato, ker se mora zapornica ponovno dvigniti v položaj 70° in ostati dvignjena tako dolgo, dokler ovira ni odstranjena. Ko je odstranjena, se mora servo motorček vrteti iz izhodiščnega položaja 70° do položaja 0°.

- V primeru ko je ovira prisotna, uredimo potrebno za utripanje LED diode, na LCD zapišemo "POZOR OVIRA !!" in zapornico dvignemo s stavkom:

servo.write(Zapornica_zgoraj);

V parametru Zapornica_zgoraj je namreč vrednost 70. Servo motorček se bo sedaj hitro zavrtel v pozicijo 70°.

Zanka for:

Sintaksa zanke je:

for (vstopni_izraz; pogoj_delovanja; izraz_povečevanja) res_blok

Ima tri dele, ki so lahko definirani (lahko pa tudi ne). res_blok se izvaja, dokler je pogoj_delovanja resničen.

Pomen posameznih delov:

Slika 6: Delovanje zanke for