|
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.20 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 5:53 am Naslov sporočila: Uporaba Arduino timer-jev |
|
|
Pozdravljeni,
Lotil sem se učenja o AVR timer-jih.
Za začetno razumevanje mi je bila zelo v pomoč ta stran LINK, ki sem jo dobro preučil nato pa na Arduinu poskusil še sam z tole kodo (čisto začetni nivo, najprej bi rad osvojil osnove...):
Koda: |
void setup(){
pinMode(8, OUTPUT);
cli();//stop interrupts
TCCR0A = 0;// set entire TCCR0A register to 0
TCCR0B = 0;// same for TCCR0B
TCNT0 = 0;
TCCR0B |= (1 << CS00);
sei();//allow interrupts
}
void loop() {
if (TCNT0 >= 100){
digitalWrite(8, digitalRead(8)^1);
TCNT0 = 0;
}
}
|
No, ko kodo poženem se na pinu 8 res pojavijo neki kvadratki, vendar je njihova frekvenca nesmiselna in se ne ujema s kodo. Kaj bi lahko bilo narobe ?
Dodatna razlaga:
Če je moje razumevanje pravilno, bi pri tej kodi moral biti čas enega tika timer-ja 1/(16x10^6) = 0.0625 uS, kar pomeni, da bo čas 100 tikov 100x0.0625=6.25uS. Vsaj približno toliko bi moral biti tudi Ton in Toff generiranih kvadratkov, pa je daleč od tega (preverjeno z osciloskopom). Če spreminjam vrednost v if izjavi, torej koliko tikov naj šteje se frekvenca generiranih kvadratkov spreminja nesmiselno, ali pa se sploh ne spremeni.
Hvala za pomoč !
Lp,
Klemen |
|
Nazaj na vrh |
|
|
rudiP Član
Pridružen-a: Tor 07 Avg 2007 15:30 Prispevkov: 1234 Aktiv.: 6.09 Kraj: KOPER
|
Objavljeno: Tor Okt 28, 2014 7:35 am Naslov sporočila: |
|
|
Manjka ti ISR rutina. V ISR skoči mikro ko pride do interupta in tu menjaš stanje na izhodnem pinu. Tako kot si napisal se program vrti v neskončni zanki in spreminjanje
stanja pina je odvisno le od hitrosti na kateri dela mikro. Kar imaš sedaj v loopu moraš
dat v ISR in bo prekinitev delala.
http://www.instructables.com/id/Arduino-Timer-Interrupts/ _________________ Lep pozdrav iz Kopra Rudi |
|
Nazaj na vrh |
|
|
Peter123 Član
Pridružen-a: Tor 13 Jan 2009 15:34 Prispevkov: 1364 Aktiv.: 7.37 Kraj: Lj.
|
Objavljeno: Tor Okt 28, 2014 8:20 am Naslov sporočila: |
|
|
Načinov uporabe timerjev je več, ampak najbolj pogosta je kot že omenjeno z ISR "stavkom".
In sicer timer vedno šteje ne glede na to kaj počne mcu.
Ko pride timer na 0 ali naredi over flow potem mcu prekine delo in izvede ISR "stavek".
Zelo pomembno: ISR "stavek" mora biti čim krajši!
Ponavadi vsebuje vsaj seštevanje spremenljivke npr.: a++; ali podobno.
V glavni zanki pa imaš če je a enak temo potem izvedeš...
Seveda je lahko zelo mikavno podaljšati ISR za še nekaj ukazov vendar se lahko pojavijo napake v komunikaciji (uart ali kaki drugi), saj ko mcu izvaja ISR vse ostalo stoji. So tudi drugi problemi, ki lahko nastopijo z uporabo predolge isr zanke. |
|
Nazaj na vrh |
|
|
dejko1 Član
Pridružen-a: Ned 16 Mar 2008 0:21 Prispevkov: 265 Aktiv.: 1.36 Kraj: Ljubljana
|
Objavljeno: Tor Okt 28, 2014 10:30 am Naslov sporočila: |
|
|
Predlagam da najprej poskusiš zadevo izvesti malo počasneje
Če so mikrosekunde nekaj kar res rabiš v programu ki bi ga rad naredil boš pa kmalu ugotovil da so funkcije digitalWrite in digitalRead precej počasne... |
|
Nazaj na vrh |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.20 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 3:27 pm Naslov sporočila: |
|
|
Pozdravljeni,
kako bi pa z ISR stavki naredil tole:
-timer mora pri frekvenci 16MHz štet 400 tikov (uporabil bi timer 1).
-ko prešteje 400 tikov (399 če štejem 0) se resetira na nič.
-ob poljubnem številu tikov (npr. 50, 150, 300, 350) bi rad prožil različne ISR stavke.
Ali je kakšna hitrejša koda, ki naredi isto kot: (digitalWrite(x, digitaRead(x)^1) torej da vsakič, ko progrem stopi v ISR rutino samo pogleda stanje pina in ga spremeni na nasprotno od tega.
Opis delovanja, ki ga z to kodo želim doseči:
Želim, da mi Arduino generira dva 40 kHz signala, kjer bi lahko drugi signal relativno na prvega pomikal poljubno iz faze. 400 tikov bi potem predstavljalo celotno periodo mojega 40 kHz signala. 1/(40*10^3) = 25 uS; 400 tikov pa je 400 * 0.0625uS = 25uS. Torej en pin bi šel on ob 0 oz. ob overfolow-u potem pa off ob 199 tikov. Drugi pa bi šel on (nekje med 0-199 tiki) off pa po 200 tikih za tem ko bi šel on. Takole bi lahko poljubno nastavljal fazo signala dva relativno na signal ena... Ne znam pa tega zapisat v kodi
Lep pozdrav,
Klemen |
|
Nazaj na vrh |
|
|
gumby Član
Pridružen-a: Sob 28 Apr 2007 12:32 Prispevkov: 4066 Aktiv.: 19.74
|
Objavljeno: Tor Okt 28, 2014 3:37 pm Naslov sporočila: |
|
|
50 impulzov pri 16MHz pomeni prekinitev na vsake 3,13 mikrosekunde. Pri 20MHz clocku to pomeni 62 strojnih ukazov procesorja.
Samo za občutek, v kaj se podajaš _________________ Tule nisem več aktiven. |
|
Nazaj na vrh |
|
|
tilz0R Član
Pridružen-a: Čet 31 Maj 2012 15:39 Prispevkov: 898 Aktiv.: 6.24 Kraj: Črnomelj
|
Objavljeno: Tor Okt 28, 2014 3:42 pm Naslov sporočila: |
|
|
KlemenD, piši "AVR" style v register PIN.
Poglej na katerem portu je tvoj pin in naredi nekako tako:
Koda: |
//Toggle bit
PINx = 1 << bit_tvojega_pina;
|
PS: Predpostavljam da uporabljaš Arduino z AVR-jem. _________________ Knowledge sharing is caring.
majerle.eu | stm32f4-discovery.net
Nazadnje urejal/a tilz0R Tor Okt 28, 2014 3:48 pm; skupaj popravljeno 1 krat |
|
Nazaj na vrh |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.20 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 3:46 pm Naslov sporočila: |
|
|
Pozdravljen,
da, res je vse skupaj malo na tesno... No, ampak poskusim lahko bom že potem videl, če bodo kvadratki dovolj stabilni za mojo aplikacijo... če ne iščem drugo rešitev. Tako ali tako je 40kHz v elektronskem svetu zelo malo, pa ne bi smelo bit problema...upam |
|
Nazaj na vrh |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.20 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 3:52 pm Naslov sporočila: |
|
|
tilz0R pardon sploh nisem napisal. Da, sklepaš pravilno uporabljam arduino uno (ATmega328). Hvala za nasvet ! |
|
Nazaj na vrh |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.11
|
Objavljeno: Tor Okt 28, 2014 4:05 pm Naslov sporočila: |
|
|
Arduino je super za počasne stvari. Ko gre zares in ti nič ne deluje, se zakoplješ v knjižnice ter ugotoviš, da je potrebnih 12 ciklov za navadno spremembo stanja pina.
V glavnem začni preučevati AVR Zbirnik.
Tam v parih ukazih napolniš timer in primerjalne registre, vmes preveriš vhode in spremeniš izhode, na koncu pa še v goto zanki v miru počakaš na naslednjo prekinitev. Mimogrede ob prekinitvi na LCD pošlješ en E=1, naslednjič E=0, do naslednjega E=1 pa pripraviš nov nibble. _________________ Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor |
|
Nazaj na vrh |
|
|
dejko1 Član
Pridružen-a: Ned 16 Mar 2008 0:21 Prispevkov: 265 Aktiv.: 1.36 Kraj: Ljubljana
|
Objavljeno: Tor Okt 28, 2014 4:29 pm Naslov sporočila: |
|
|
Timer0 in timer2 omogočata na obeh PWM izhodih možnost toggle on match, mogoče bi to delovalo...
Če uporabiš timer v PWM generation načinu potem timer sam od sebe (brez intervencije procesorja) generira signal, ti pa iz programa samo vnašaš vrednosti.
Edit: Vsi timerji znajo toggle on match ne samo timer0 in timer2.
Nazadnje urejal/a dejko1 Tor Okt 28, 2014 6:57 pm; skupaj popravljeno 1 krat |
|
Nazaj na vrh |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.20 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 5:04 pm Naslov sporočila: |
|
|
dejko1 priznam, da se mi trenutno ne sanja, kako bi s tem dosegel dve enaki frekvenci z poljubno razliko v fazi.
Sedaj najprej nekoga prosim, da mi napiše, kako uporabljam ISR stavke.
Naprimer pustim timer1 (16-bit), da šteje vseh svojih 65536 tikov, nato pa se resetira. Jaz pa želim sprožit naprimer 4 različne ISR funkcije (kadar bo timer naštel 4000 tikov, 10000 tikov, 30000 tikov in 50000 tikov) . Iz literature, ki sem jo tem izbrskal na spletu se žal ne znajdem |
|
Nazaj na vrh |
|
|
tilz0R Član
Pridružen-a: Čet 31 Maj 2012 15:39 Prispevkov: 898 Aktiv.: 6.24 Kraj: Črnomelj
|
Objavljeno: Tor Okt 28, 2014 5:09 pm Naslov sporočila: |
|
|
Klemen, naredi interrupte, da bo vsakih 10000 ciklov interrupt.
Ustvari statično spremenljivko znotraj ISR funkcije in preverjaj njeno stanje.
Koda: |
ISR() {
static uint8_t i = 0;
if (i == 0) {
//interrupt prvič
//delaj svoje
i = 1;
} else if (i == 1) {
//interrupt drugič
//delaj svoje
i = 2;
} else if (i == 2) {
//interrupt drugič
//delaj svoje
i = 3;
} else if (i == 3) {
//interrupt drugič
//delaj svoje
i = 0;
}
}
|
_________________ Knowledge sharing is caring.
majerle.eu | stm32f4-discovery.net |
|
Nazaj na vrh |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.11
|
Objavljeno: Tor Okt 28, 2014 5:53 pm Naslov sporočila: |
|
|
V sinhronizacijski prekinitvi (Timer1, nosilni signal) samo pobrišeš prekinitvene zastavice, negiraš stanje izhoda in primerjalnemu registru prišteješ vrednost spremenljivke PolPerioda. Prenos zanemariš. Takoj za tem letiš ven in prebereš vhoda Frek_gor in Frek_dol. Po potrebi povečaš ali zmanjšaš debounce števec in preveriš, če se mora PolPerioda spremeniti. Potem se posvetiš zaporedju bytov (ukazi in podatki), ki ga moraš poslati na LCD. Vmes te lahko zmoti prekinitev drugega Timerja2 (sledilni signal - tukaj moraš poskrbeti za Sklad), a se orientiraj samo po Timerju1.
Glej, da boš ob maksimalni frekvenci v eni polperiodi opravil več kot pol potrebnih nalog in nato počakaj, da se sinhronizacijska prekinitev zgodi, ko ne bo nič pomembnega v delovnih registrih. S tem prihraniš čas rogoviljenja s Skladom, ki bi ti načenjal živce, ko bi bila signala zelo malo (par taktov) zamaknjena. Nato dokončaš naloge in počakaš na novo sinhronizacijsko prekinitev.
Ne boj se Zbirnika. Za vse našteto rabiš ene 20 različnih ukazov (in "malo" brskanja po AVR datasheetu).
Jaz sploh ne bi uporabil dveh prekinitev, ampak samo eno - za sledilni signal. Tista za nosilni signal bi pa poskrbela samo negiranje enega bita in s tem za izstop iz čakalne goto zanke.
Cakaj1
Je nek bit 1?
Ne, goto Cakaj1
uredi polovico stvari (vmes se zgodi sledilna prekinitev)
Cakaj2
Je nek bit 0?
Ne, goto Cakaj2
uredi drugo polovico stvari
goto Cakaj1
Seveda se še nisem poglobil v datasheet niti pol stavka dlje od tega, kar sem doslej potreboval. Zato je rešitev od @dejko1 še najelegantnejša. _________________ Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor |
|
Nazaj na vrh |
|
|
gregoral Član
Pridružen-a: Pet 24 Nov 2006 9:42 Prispevkov: 688 Aktiv.: 3.26 Kraj: Ljubljana
|
Objavljeno: Tor Okt 28, 2014 6:07 pm Naslov sporočila: |
|
|
1) za večje hitrosti/frekvence signala ki ga želiš generirati MORAŠ uporabiti timer tako, da sam spreminja stanje izhoda!
Primer take nastavitve: vsakih 10 us zamenjaj stanje izhoda.
Po korakih to izgleda takole:
- s kakšno frekvenco teče procesor?
- primerno nastavi prescaler oz. druge parametre timerja
- sproži timer
- od tu dalje timer sam spreminja stanje izhoda in v kodi ne pipaš
- koda v glavnem programu lahko nato ob nekem dogodku (recimo pritisk tipke) izklopi timer
2) pri nižjih hitostih se lahko igraš s tem da timer kliče tvojo kodo.
V tem primeru izbereš najmanjši mnogokratnik časov ob katerih bi rad nekaj naredil.
Recimo interval je 1 sekunda in ob 100, 300 in 650 ms bi rad nekaj izvedel:
Timer nastavi na 100 ms in v ISR povečuj spremenljivko (recimo ticks).
V glavnem programu potem preverjaš stanje ticks in če je vrednost 100 izvedeš kodo, če je vrednost 300 izvedeš drugo kodo, ...
Tak način ne bo zelo natančen, saj lahko preteče nekaj časa preden boš v glavnem programu preveril stanje ticks.
Če imaš v glavnem programu dolge sekvence potem tak način ni najbolj primeren.
3) če bi rad generiral dva signala s kotnim zamikom:
- ena možnost ( ni optimalna ) uporaba dveh timerjev, ki jih primerno nastaviš.
- druga možnost je da znotraj timer isr malo računaš
Žal z arduinom nisem naredil še ničesar, zato so napotki bolj splošni.
Upam da ti napisano kaj pomaga.
lp, Gregor |
|
Nazaj na vrh |
|
|
|
|
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: 47 dni
Powered by phpBB © 2001, 2005 phpBB Group
|