www.elektronik.si Seznam forumov www.elektronik.si
Forum o elektrotehniki in računalništvu
 
 PomočPomoč  IščiIšči  Seznam članovSeznam članov  SkupineSkupine  StatisticsStatistika  AlbumAlbum  DatotekeFilemanager DokumentacijaDocDB LinksPovezave   Registriraj seRegistriraj se 
  PravilaPravila  LinksBolha  PriponkePriponke  KoledarKoledar  ZapiskiZapiski Tvoj profilTvoj profil Prijava za pregled zasebnih sporočilPrijava za pregled zasebnih sporočil PrijavaPrijava 

Merjenje časa s pulsein() funkcijo?

 
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Arduino sekcija
Poglej prejšnjo temo :: Poglej naslednjo temo  
Avtor Sporočilo
grosleon1991
Neznanec
Neznanec



Pridružen-a: Čet 19 Maj 2011 21:58
Prispevkov: 9
Aktiv.: 0.06
Kraj: SLO

PrispevekObjavljeno: Ned Mar 22, 2015 3:41 pm    Naslov sporočila:  Merjenje časa s pulsein() funkcijo? Odgovori s citatom

Lep pozdrav!
Za svoj projekt potrebujem funkcijo, ki mi bo merila čas kako dolgo je vklopljen pin. Pa me zanima kako meri oz. kako deluje funkcija pulsein(). Nikjer ne najdem opisa delovanja in source kode. Zanima me če so še kakšni drugi načini za merjenje časa.
Hvala za pomoč in razlago.


Nazadnje urejal/a grosleon1991 Pon Maj 11, 2015 9:05 pm; skupaj popravljeno 1 krat
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
tilz0R
Član
Član



Pridružen-a: Čet 31 Maj 2012 15:39
Prispevkov: 898
Aktiv.: 6.20
Kraj: Črnomelj

PrispevekObjavljeno: Ned Mar 22, 2015 4:03 pm    Naslov sporočila:   Odgovori s citatom

Če nočeš zapravljati procesorja s tem ko imaš while( pin status) {count++;} kot ga ima pulsein, potem boš uporabljal sledeče:

1. Ko zaznaš na pinu neko stanje, ki ga želiš meriti, recimo logična 1, poženeš timer. To boš najlažje zaznal tako, da boš signal pripeljal na en pin, ki je sposoben ustvariti interrupt. V rutini poženeš nek števec.
2. Ko se signal konča, vstaviš timer, pogledaš njegovo vrednost in na podlagi hitrosti timerja in njegove vrednosti preračunaš čas pulza.

Na ta način bi moral določiti pinu interrupt na "any edge".


Za arduino AVR jedro najdeš funkcijo pulseIn v datoteki: "POT_DO_ARDINO_IDE/hardware/arduino/avr/cores/arduino/wiring_pulse.cpp, njena vsebina pa je spodaj.

Koda:

/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
 * or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
 * to 3 minutes in length, but must be called at least a few dozen microseconds
 * before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
   // cache the port and bit of the pin in order to speed up the
   // pulse width measuring loop and achieve finer resolution.  calling
   // digitalRead() instead yields much coarser resolution.
   uint8_t bit = digitalPinToBitMask(pin);
   uint8_t port = digitalPinToPort(pin);
   uint8_t stateMask = (state ? bit : 0);
   unsigned long width = 0; // keep initialization out of time critical area
   
   // convert the timeout from microseconds to a number of times through
   // the initial loop; it takes 16 clock cycles per iteration.
   unsigned long numloops = 0;
   unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
   
   // wait for any previous pulse to end
   while ((*portInputRegister(port) & bit) == stateMask)
      if (numloops++ == maxloops)
         return 0;
   
   // wait for the pulse to start
   while ((*portInputRegister(port) & bit) != stateMask)
      if (numloops++ == maxloops)
         return 0;
   
   // wait for the pulse to stop
   while ((*portInputRegister(port) & bit) == stateMask) {
      if (numloops++ == maxloops)
         return 0;
      width++;
   }

   // convert the reading to microseconds. There will be some error introduced by
   // the interrupt handlers.

   // Conversion constants are compiler-dependent, different compiler versions
   // have different levels of optimization.
#if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==2
   // avr-gcc 4.3.2
   return clockCyclesToMicroseconds(width * 21 + 16);
#elif __GNUC__==4 && __GNUC_MINOR__==8 && __GNUC_PATCHLEVEL__==1
   // avr-gcc 4.8.1
   return clockCyclesToMicroseconds(width * 24 + 16);
#elif __GNUC__<=4 && __GNUC_MINOR__<=3
   // avr-gcc <=4.3.x
   #warning "pulseIn() results may not be accurate"
   return clockCyclesToMicroseconds(width * 21 + 16);
#else
   // avr-gcc >4.3.x
   #warning "pulseIn() results may not be accurate"
   return clockCyclesToMicroseconds(width * 24 + 16);
#endif

}

_________________
Knowledge sharing is caring.
majerle.eu | stm32f4-discovery.net
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Obišči avtorjevo spletno stran
grosleon1991
Neznanec
Neznanec



Pridružen-a: Čet 19 Maj 2011 21:58
Prispevkov: 9
Aktiv.: 0.06
Kraj: SLO

PrispevekObjavljeno: Ned Mar 22, 2015 6:59 pm    Naslov sporočila:   Odgovori s citatom

u bistvu jaz rabim merjenje časa za ultrazvočni senzor

Nazadnje urejal/a grosleon1991 Pon Maj 11, 2015 9:05 pm; skupaj popravljeno 1 krat
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Fido
Član
Član



Pridružen-a: Sre 17 Feb 2010 19:42
Prispevkov: 78
Aktiv.: 0.45
Kraj: Črnomelj

PrispevekObjavljeno: Ned Mar 22, 2015 8:06 pm    Naslov sporočila:   Odgovori s citatom

Mogoče ti bo ta link kaj pomagal Smile http://www.mikrocontroller.net/articles/High-Speed_capture_mit_ATmega_Timer

Kot je že Tilen povedal je ideja ta, da z Input capture modulom ujameš "rissing edge" pulza, poženeš števec, nastaviš naslednje proženje ob "falling edge" in ob ponovnem klicu prekinitvene rutine vrednost TCNT registra pripišeš svoji spremenljivki. (v mojem primeru pulselen, ne pozabit na "volatile")
Spodaj je koda po kateri se lahko malo orientiraš, kopirana je iz enega mojega projekta in nisem siguren, če je potrebno še kaj dodati, torej zgolj orientacijo Smile

PS: Tukaj sem uporabil Timer 4 (pin za Input Capture je v tem primeru ICP4)
Koda:

void input_capture_init()
      {         
          TCCR4A = 0;                                                   // WGM43:0 set to zero for Normal mode operation , TOP= 0xFFFF, TOVn Flag set on MAX
          TCCR4B  = TCCR4B | (1 << ICES4) | (1 << CS40);                // ICES4 HIGH - rissing edge , LOW - Falling edge    CS40 - No prescaling
          TIMSK4  = TIMSK4 | (1 << ICIE4);                             // ICIE4  Input-capture interrupt ENABLED -- Calling TIMER4_CAPT_vect after ICFn flag is set in TIFRn   
          TCCR4C = 0;       
      }
       
         
      ISR( TIMER4_CAPT_vect )
           {                         
              if(TCCR4B & (1<<ICES4))                         // ICES1:  "1" = Rissing edge triggering, "0" = Falling edge triggering
                {
                TCNT4 = 0;
                TCCR4B &= ~(1 << ICES4);                   // Set trigger-edge to falling
                TIFR4 |=(1<<ICF4);                          // Clear flag , must do after edge-trigger change
            
                }               
              else
              {
                pulselen = ICR4;
                TCNT4 = 0;
                TCCR4B |= (1 << ICES4);                                       //  Set trigger-edge to rising
                TIFR4 |= (1<<ICF4);                                              // Clear flag , must do after edge-trigger change
              }
           }
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Pokaži sporočila:   
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Arduino sekcija Časovni pas GMT + 2 uri, srednjeevropski - poletni čas
Stran 1 od 1

 
Pojdi na:  
Ne, ne moreš dodajati novih tem v tem forumu
Ne, ne moreš odgovarjati na teme v tem forumu
Ne, ne moreš urejati svojih prispevkov v tem forumu
Ne, ne moreš brisati svojih prispevkov v tem forumu
Ne ne moreš glasovati v anketi v tem forumu
Ne, ne moreš pripeti datotek v tem forumu
Ne, ne moreš povleči datotek v tem forumu

Uptime: 74 dni


Powered by phpBB © 2001, 2005 phpBB Group