Fórum témák

» Több friss téma
Cikkek » SRF-04 Ultrahangos távolságmérő szenzor használata Arduino-val és AVR-rel
SRF-04 Ultrahangos távolságmérő szenzor használata Arduino-val és AVR-rel
Szerző: Fizikus, idő: Dec 7, 2011, Olvasva: 28707, Oldal olvasási idő: kb. 3 perc
Lapozás: OK   6 / 7

Távolságmérés AVR-rel (megszakítás - Timer1 Input Capture működési mód)

Az Input Capture működési módot általában két külső esemény között eltelt idő mérésére szokták használni. A timert úgy is beállíthatjuk, hogy az Input Capture lábon (ICP-PB0) beérkező jel felfutó vagy lefutó élei között eltelt időt mérje. De ha a megszakítás kiszolgáló rutinon belül megváltoztatjuk az input capture-t kiváltó eseményt (átállítjuk az élkiválasztó bitet), akkor egy impulzus hosszát is megmérhetjük az alábbi módon:

  1. Az Input Capture élkiválasztó bit (ICES) értékét 1-re állítjuk (felfutó él érzékelése).
  2. Amikor a megszakítás bekövetkezik nullázzuk majd elindítjuk a Timer1 TCNT1 számláló regiszterét és az élkiválasztó bit (ICES) értékét 0-ra állítjuk (lefutó él érzékelése)
  3. Amikor a jel lefutó élénél a következő megszakítás bekövetkezik (a jel logikai 1-ről 0-ra váltott), akkor a Timer1 számlálóregiszter értéke az ICR1 regiszterbe íródik. Az ICR1 regiszter tartalma azon órajelciklusok számával egyezik meg amíg a bejövő jel magas állapotban volt.


A fenti lépéseketeket ismételve megmérhető az Echo lábon lévő jel hossza.

Az Echo láb külső jelét az Atmega8-as input capture lábára (ICP – PB0) kell kötni. A Trigger lábat bármelyik szabad I/O lábra ráköthetjük (a példában én a PD7-re kötöttem).

  1. /*
  2. Hardveres idomeres Input Capture-rel
  3. SRF04 + AVR + soros LCD
  4. Hardware: ATmega8 @ 7.372800MHz
  5. */
  6. #define F_CPU 7372800UL // rendszer orajel: 7.3728 MHz
  7. #define USART_BAUDRATE 9600  // soros kommunikacio sebessege: 9600 bps
  8. #define UBRR_ERTEK ((F_CPU / (USART_BAUDRATE * 16UL)) - 1) // UBRR
  9.  
  10. #include <avr/io.h>
  11. #include <inttypes.h>
  12. #include <util/delay.h>
  13. #include <avr/interrupt.h>
  14. #define Trigger_PORT PORTD
  15. #define Trigger_PIN PIND
  16. #define Trigger_DDR DDRD
  17. #define Trigger_Lab PD7    //SRF04 Trigger laba PORTD7-re kotve
  18. #define Echo_PORT PORTB
  19. #define Echo_PIN PINB
  20. #define Echo_DDR DDRB
  21. #define Echo_Lab PB0    //SRF04 Echo laba PORTB0-re kotve (Input Capture lab)
  22. volatile uint16_t Time = 0;
  23. void KonfigUART() // UART beallitasa
  24. {
  25.    // 9600 bps soros kommunikacio sebesseg beallitasa
  26.    UBRRL = UBRR_ERTEK;    // UBRR_ERTEK also 8 bitjenek betoltese az UBRRL regiszterbe
  27.    UBRRH = (UBRR_ERTEK>>8);   // UBRR_ERTEK felso 8 bitjenek betoltese az UBRRH regiszterbe
  28.    // Aszinkron mod, 8 Adat Bit, Nincs Paritas Bit, 1 Stop Bit
  29.    UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
  30.    //Ado es Vevo aramkorok bekapcsolasa
  31.    UCSRB |= (1 << RXEN) | (1 << TXEN);   //
  32. }
  33. char UARTAdatFogad() // Ez a fuggveny a beerkezo adatokat kiolvassa az UDR regiszter bejovo pufferebol
  34. {
  35.    while(!(UCSRA & (1<<RXC)))  // Varakozas amig nincs uj bejovo adat
  36.    {
  37.       //Varakozas
  38.    }
  39.    //Most mar van beerkezett adat, amit kiolvasunk a pufferbol
  40.    return UDR;
  41. }
  42.  
  43.  
  44. void UARTAdatKuld(char data) // Ez a fuggveny a kuldendo adatot beirja az UDR regiszter kimeno pufferjebe
  45. {
  46.    while(!(UCSRA & (1<<UDRE)))  // Varakozas amig az Ado kesz nem lesz az adatkuldesre
  47.    {
  48.       //Varakozas
  49.    }
  50.    // Az Ado mar kesz az adatkuldesre, a kuldendo adatot a kimeno pufferjebe irjuk
  51.    UDR=data;
  52. }
  53. void UARTSzovegKuld( char *p)
  54. {
  55.  while(*p)
  56.  {
  57.    UARTAdatKuld( *p++);
  58.  }
  59. }
  60.  
  61. void Trigger()
  62. {
  63.     //az SRF04 Trigger labara 15us-os, magas allapotu impulzus adasa
  64.     Trigger_PORT |= (1<<Trigger_Lab);   //magas allapot
  65.     _delay_us(15);   // varakozas 15 mikroszekundumig
  66.     Trigger_PORT &= (~(1<<Trigger_Lab)); //alacsony allapot
  67.   //input capture beallitasa a felfuto elre
  68.   TCCR1B|=(1<<ICES1);
  69.   //input capture megszakitas engedelyezese
  70.   TIMSK|=(1<<TICIE1);
  71. }
  72. int main(void)  // Foprogram
  73. {
  74.   uint16_t Tavolsag = 0;
  75.   KonfigUART();   // UART Konfiguralasa
  76.         //Trigger pin kimenet
  77.         Trigger_DDR |= (1<<Trigger_Lab);
  78.         //Echo pin bemenet
  79.         Echo_DDR &= (~(1<<Echo_Lab));
  80.   //globalis megszakitasok engedelyezese
  81.   sei();
  82.  while(1)
  83.     {
  84.    Trigger();  // Trigger impulzus adasa (tavolsagmeres elinditasa)
  85.   _delay_ms(50);         // varakozas
  86.   Tavolsag = Time*10/54;   // tavolsag kiszamitasa
  87.   UARTSzovegKuld("?f");  // ?f soros LCD parancs: LCD torlese
  88.   UARTAdatKuld('0'+(Tavolsag/10000) % 10);  //Tizezresek kiirasa
  89.   UARTAdatKuld('0'+(Tavolsag/1000) % 10);   // Ezresek ertekenek kiirasa
  90.   UARTAdatKuld('0'+(Tavolsag/100) % 10);  // Szazasok ertekenek kiirasa
  91.   UARTAdatKuld('0'+(Tavolsag/10) % 10);   // Tizesek ertekenek kiirasa
  92.   UARTAdatKuld('0'+Tavolsag % 10);    // Egyesek ertekenek kiirasa
  93.   UARTSzovegKuld(" mm");     //
  94.   UARTSzovegKuld("?m");     // ?m soros LCD parancs: ugras a sor elejere
  95.    }
  96. }
  97.  
  98. //input capture megszakitas kiszolgalo rutin (ISR)
  99. ISR(TIMER1_CAPT_vect)
  100. {
  101. if (Echo_PIN & (1<<Echo_Lab)) //ha az Echo lab magas (felfuto el tortent)
  102.     {
  103.      //Timer1 input capture mod beallitasa, nullazasa es elinditasa
  104.     TCCR1A=0X00;
  105.     TCNT1=0;       //szamlalo nullazasa
  106.     TCCR1B=(1<<CS11); // eloosztas 1/8
  107.      // input capture beallitasa lefuto elre
  108.     TCCR1B&=~(1<<ICES1);
  109.     }
  110. else // ha lefuto el tortent
  111.     {
  112.        Time=ICR1;  // a szamlalo ertekenek beirasa a Time valtozoba
  113.     //input capture megszakitas jelzobit torlese
  114.        TIFR=(1<<ICF1);
  115.     // input capture megszakitas kikapcsolasa
  116.        TIMSK &=~(1<<TICIE1);
  117.        // Timer leallitasa
  118.        TCCR1B=0x00;        
  119.     }
  120.  }

A főprogram elején az Echo lábat bemenetnek, a Trigger lábat pedig kimenetnek állítom be. Majd konfigurálom a soros portot és engedélyezem az általános megszakításokat.
Létrehozok egy Trigger() függvényt, ami előállítja a Trigger lábon a 15 mikroszekundumos Trigger jelet, bekapcsolja és nullázza a Timer1-et, majd beállítja felfutó élre és aktiválja az Input Capture módot.
A program 50 ms-ként meghívja a Trigger függvényt és kiírja az eredményt a soros LCD-re. A megfelelő Input Capture esemény bekövetkeztekor az Echo lábon lévő visszhangjel hosszának mérése a megszakítás kiszolgáló rutinon belül automatikusan megtörténik. A rutinon belül megvizsgálom hogy fel vagy lefutó él történt-e. Felfutó él esetén bekapcsolom, nullázom majd elindítom a Timert és beállítom lefutó élre az Input Capture-t kiváltó eseményt. Lefutó él esetén a Timer1 számláló regiszter értéke automatikusan beíródik az ICR1 regiszterbe, ezt átírom a Time változóba, majd törlöm az Input Capture megszakítás jelzőbitet, kikapcsolom az Input Capture megszakítást és leállítom a Timert.

A jel hosszának a mérése megszakítások használatával egy elegáns megoldás, de ennek is vannak kötöttségei, amit már a kapcsolás tervezésnél figyelembe kell venni. Például az Echo lábat csak az Input Capture lábra (PB0) lehet kötni, ami fix, nem változtatható.


A cikk még nem ért véget, lapozz!
Következő: »»   6 / 7
Értékeléshez bejelentkezés szükséges!
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem