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 

Uporaba Arduino timer-jev
Pojdi na stran Prejšnja  1, 2, 3  Naslednja
 
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
VolkD
Član
Član



Pridružen-a: Pet 24 Sep 2004 21:58
Prispevkov: 14228
Aktiv.: 64.07
Kraj: Divača (Kačiče)

PrispevekObjavljeno: Tor Okt 28, 2014 6:22 pm    Naslov sporočila:   Odgovori s citatom

V naslednji številki revije bo govora ravno o tem. Vredno branja.
_________________
Dokler bodo ljudje mislili, da živali ne čutijo, bodo živali čutile, da ljudje ne mislijo.
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo Obišči avtorjevo spletno stran
KlemenD
Član
Član



Pridružen-a: Sre 18 Maj 2011 15:08
Prispevkov: 188
Aktiv.: 1.20
Kraj: Maribor

PrispevekObjavljeno: Tor Okt 28, 2014 7:14 pm    Naslov sporočila:   Odgovori s citatom

Vsem še enkrat hvala za odgovore! So mi zelo v pomoč, vprašanje je edino, ali jih prav razumem Smile Sedaj bi koda izgledala nekako takole:
Koda:

void setup(){

cli();//stop interrupts

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A = 399; //naj šteje 400 tikov, potem pa sproži interrupt in resetira timer

  TCCR1B |= (1 << WGM12);  // turn on CTC mode

  TCCR1B |= (1 << CS10); // brez prescalerja

  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt

sei();//allow interrupts

//400 tikov pri 16MHz prez prescala je točno dolžina ene periode mojega 40kHz signala. Torej sedaj bo vsakih 400 tikov prožil interrupt in resetiar timer.. ali je za to koda pravilno spisana ?
}

void loop(){
//nič
}

ISR(TIMER1_COMPA_vect){ //sprožen interrupt

(pin x1 da na HIGH) // tako kot je predlagal [b]tilz0R[/b]

(pin x1 pusti high točno 200 tikov in ga potem da na LOW)

(takoj za tem ko vklopi pin x1 naj počaka poljubno število tikov med 0 in 200 in da pin x2 na HIGH) // če bo čakal 0 tikov bo signal na pin x2 v fazi z signalom na pin x1, če bo pa čakal 200 tikov pa bo signal na pinu x2 točno za 90 stopinj iz faze)

(za tem ko vklopi pin x2 naj počaka točno 200 tikov in ga da na LOW)



Sedaj pa ne vem kako naj programu povem, da čaka y tikov timerja preden izvede komando v ISR stavku.
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Tor Okt 28, 2014 7:26 pm    Naslov sporočila:   Odgovori s citatom

OCR1A = OCR1A + 199 //
negiraj pin neposredno v izhodnem registru // (glej HardwareWiring knjižnico za funkcijo DigitalWrite() in jo oklesti)
In takoj za tem letiš iz prekinitve. (TCNT1 pusti pri miru)

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
KlemenD
Član
Član



Pridružen-a: Sre 18 Maj 2011 15:08
Prispevkov: 188
Aktiv.: 1.20
Kraj: Maribor

PrispevekObjavljeno: Tor Okt 28, 2014 8:44 pm    Naslov sporočila:   Odgovori s citatom

igo Hvala za pomoč, vendar nisem prepričan če te pravilno razumem. Ne mi zamerit, v programiranju nisem ravno vešč.
A ne bom z tem stavkom
OCR1A = OCR1A + 199
rekel, da naj proži funkcijo samo vsakih 200 tikov timerja ?
To bi mi ustrezalo za generacijo signala na enem pinu.. ON 200 tikov, OFF 200 tikov..

Tukaj bi potreboval še eno ISR rutino, npr takole:
OCR1A = OCR1A + 199
OCR1B = OCR1A + 9

tukaj bi se pin pri OCR1B vklopil in izklopil z zamikom 10 tikov relativno na pin, ki bi ga nadziral OCR1A... ta zamik bi potem predstavljal fazni zamik.. ali je to izvedljivo ?

Upam, da nisem udaril čisto mimo..

Lep pozdrav,
Klemen
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
Sigi
Član
Član



Pridružen-a: Čet 31 Jul 2014 11:42
Prispevkov: 199
Aktiv.: 1.69
Kraj: Kamnik

PrispevekObjavljeno: Tor Okt 28, 2014 9:45 pm    Naslov sporočila:   Odgovori s citatom

Nisi udaril mimo, to je prava pot.

Ampak morda bi ti tole še bolj ustrezalo:
Nisem čisto prepričan, ali timer 1 v CTC modu zna generirat toggle signal tudi za OCR1B (za OCR1A ga zna), ampak najbrž da ga zna. Ker če to gre, lahko tvoja dva 40KHz signala generiraš povsem hardversko, brez interruptov:
-timer 1 v CTC mode, reload z OCR1A. OCR1A izhod v toggle mode.
OCR1B nastavljaš od 0 pa do vrednosti, ki si jo dal v OCR1A (da si dobil 40KHz) in če je tudi OCR1B izhod v toggle mode, boš lahko s tem nastavljal fazni zamik (0 do 180stopinj, če rabiš še drugih 180 boš popravil začetne pogoje stanja portov).
Reload vrednost bo tu pol manjša, ker ti izhod v eni periodi timerja enkrat preklopi stanje. Za celo periodo signala tako rabiš dve periodi timerja.

Z Arduinom ne delam. Če te bo zelo zezalo, lahko jutri spišem test v C-ju.

lp
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Tor Okt 28, 2014 9:50 pm    Naslov sporočila:   Odgovori s citatom

Ja, tako je.
Vsakih 200 taktov moraš spremeniti stanje pina pri nosilni frekvenci, zato rabiš prekinitev.

No, tu pravzaprav ne rabiš popolne ISR (porabi preveč taktov), ampak jo povsem oklesti, da bo ob prekinitvenem vektorju samo pobrisala prekinitveno zastavico in spremenila izhod. Po vrnitvi pa preverila stanje izhoda in zapustila zanko Cakaj1 oziroma Cakaj2.

Takoj za tem nastavi OCR1B, nato OCR1A, nato v miru dela vse ostalo. Ko se bo sprožila OCR1B prekinitev, mora biti pa prava ISR, ker bo program takrat že sredi računanja.

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
tilz0R
Član
Član



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

PrispevekObjavljeno: Tor Okt 28, 2014 9:56 pm    Naslov sporočila:   Odgovori s citatom

Kaj pa opcija, da se timer 1 nastavi kot CTC mode z ICR top vrednostjo.

Oba izhoda se nastavi na Toggle on compare match.

In potem, če je OCR1A recimo 100, ORC1B pa 200, bo pač B zaostajal za A,
če pa je kontra bo pa kontra, če sta enaka je pa v fazi.

To bi nam načeloma dalo 360stopinj nastavljanje faze.

_________________
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
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Tor Okt 28, 2014 10:25 pm    Naslov sporočila:   Odgovori s citatom

Ah, ja, vsa telovadba s klestenjem prekinitev ni nujno potrebna. Vse skupaj super deluje tudi z navadnimi ISR prekinitvami ob OCR1A in OCR1B, če je le Zamik dovolj velik. Če pa bi rad imel zamik tudi od 1 (1/16 us) do 50 taktov (Zamik < 50), je najbolje uporabiti kar podaljšano OCR1A prekinitev (drugo blokiraš).

Seveda pa je hardverska rešitev še boljša.

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
dejko1
Član
Član



Pridružen-a: Ned 16 Mar 2008 0:21
Prispevkov: 265
Aktiv.: 1.36
Kraj: Ljubljana

PrispevekObjavljeno: Tor Okt 28, 2014 10:51 pm    Naslov sporočila:   Odgovori s citatom

Evo še hardwerska rešitev s toggle brez prekinitev.

Koda:

void setup() {
  PORTB=0x00;
  DDRB=0x06;
 
  ICR1=199;
  OCR1A=0;
  OCR1B=100;
  TCNT1=0;
  TCCR1A=0x50;
  TCCR1B=0x19;
  OCR1B=100;
}

void loop() {
  delay(10);
  OCR1B = OCR1B + 1;
  if(OCR1B > 198) OCR1B=0;
}


"Problem" te kode je pri dinamičnem spreminjanju OCR registrov kjer lahko pride do obrata signala. Če imaš dostop do osciloskopa lahko preizkusiš kodo.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Obišči avtorjevo spletno stran
Sigi
Član
Član



Pridružen-a: Čet 31 Jul 2014 11:42
Prispevkov: 199
Aktiv.: 1.69
Kraj: Kamnik

PrispevekObjavljeno: Tor Okt 28, 2014 11:19 pm    Naslov sporočila:   Odgovori s citatom

dejko1 je napisal/a:
Evo še hardwerska rešitev s toggle brez prekinitev.

Koda:

void setup() {
  PORTB=0x00;
  DDRB=0x06;
 
  ICR1=199;
  OCR1A=0;
  OCR1B=100;
  TCNT1=0;
  TCCR1A=0x50;
  TCCR1B=0x19;
  OCR1B=100;
}

void loop() {
  delay(10);
  OCR1B = OCR1B + 1;
  if(OCR1B > 198) OCR1B=0;
}


"Problem" te kode je pri dinamičnem spreminjanju OCR registrov kjer lahko pride do obrata signala. Če imaš dostop do osciloskopa lahko preizkusiš kodo.


Uh, ja v CTC modu OCRji niso "double buffered"... to sem spregledal. Bi bila potrebna dodatna previdnost pri spreminjanju vrednosti med delovanjem. Če bi aplikacija zahtevala konstantne signale, potem je lahko: ustaviš števec ponastaviš in zopet zaženeš (z naprimer novim faznim zamikom). Če pa je treba fazni zamik dinamično menjat, bi se raje odločil za kakega od PWM modov, kjer sta OCR registra "double buffered". Vendar ker tam ni "toggle" načina za OCR izhode, bi moral interrupt vsaj vsakič zamenjat režim OCR izhoda (izmenično "set on compare" in "clear on compare" ). Preklop izhoda pa bi bil še vedno hardverski.

lp
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
KlemenD
Član
Član



Pridružen-a: Sre 18 Maj 2011 15:08
Prispevkov: 188
Aktiv.: 1.20
Kraj: Maribor

PrispevekObjavljeno: Sre Okt 29, 2014 12:06 am    Naslov sporočila:   Odgovori s citatom

Koda deluje tako kot mora ! Signala sta zelo stabilna kar se frekvence in duty cycla tiče... prihaja pa do omenjenih obratov signala.

Gre se za eksperiment s stoječim ultrazvočnim valovanjem. Imamo dva ultrazvočna oddajnika (40kHz) obrnjena drug proti drugemu. Dosti lažje/natančneje pri njuni valovni dolžini spreminjam fazo delovanja, kot pa fizično razdalijo med njima, da dosežem stoječe valovanje. Tako, da bom gor povezal še kak potenciometer ali pa rotirni enkoder in z njima poskusil nastavljat zamik. Naredil bom, kot je predlagal Sigi, vrednostni bom resetiral nato pa začel od začetka z novim faznim zamikom, ko se bo obračal potenciometer oz. rotirni enkoder... Seveda moram najprej točno ugotovit, kako koda deluje Very Happy
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
KlemenD
Član
Član



Pridružen-a: Sre 18 Maj 2011 15:08
Prispevkov: 188
Aktiv.: 1.20
Kraj: Maribor

PrispevekObjavljeno: Pon Nov 24, 2014 12:47 pm    Naslov sporočila:   Odgovori s citatom

Pozdravljen,

zakaj pri sledeči kodi še vedno prihaja do obrata signala ? Sklepal bi, da sedaj vedno ko obrnem potenciometer resetiram vse vrednosti in timer poženem od začetka... pa temu ni tako Brick wall

Koda:

int a;
int b;
volatile int c;

void setup() {
  PORTB=0x00;
  DDRB=0x06;
 
  ICR1=199;
  OCR1A=0; 
  TCNT1=0;
  TCCR1A=0x50;
  TCCR1B=0x19;
  OCR1B= c;
}

void loop() {
 a = analogRead(0);
 if( a != b ){
  c = round(a*(199/1023.0));
  setup(); 
  b = a;
    }

}


Lep pozdrav,
Klemen


Nazadnje urejal/a KlemenD Pon Nov 24, 2014 9:15 pm; skupaj popravljeno 1 krat
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
dejko1
Član
Član



Pridružen-a: Ned 16 Mar 2008 0:21
Prispevkov: 265
Aktiv.: 1.36
Kraj: Ljubljana

PrispevekObjavljeno: Pon Nov 24, 2014 1:40 pm    Naslov sporočila:   Odgovori s citatom

Analog read malo zaokroži (ali povpreči) in naredi nek treshold za spremembo, ker sicer ti bo tako kot je koda napisana stalno skakalo gor in dol.

V kodi bi moral najprej ustavit timer (s TCCR registri - izklopiš clock), nato počistit porte, nastavit nove nastavitve timerja in ga spet zagnat...
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Obišči avtorjevo spletno stran
KlemenD
Član
Član



Pridružen-a: Sre 18 Maj 2011 15:08
Prispevkov: 188
Aktiv.: 1.20
Kraj: Maribor

PrispevekObjavljeno: Pon Nov 24, 2014 9:26 pm    Naslov sporočila:   Odgovori s citatom

Pozdravljen,

takole ?

Koda:


int a;
int b;
volatile int c;

void setup() {
  TCCR1A=0;
  TCCR1B=0;
  PORTB=0x00;
  DDRB=0x06;
 
  ICR1=199;
  OCR1A=0; 
  TCNT1=0;
  TCCR1A=0x50;
  TCCR1B=0x19;
  OCR1B= c;
}

void loop() {
 a = analogRead(0);
 if( a > (b+1) || a < (b-1) ){    //tole za silo popravi skakanje
  c = round(a*(199/1023.0));
  setup(); 
  b = a;
    }

}


Lep pozdrav,
Klemen
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
KlemenD
Član
Član



Pridružen-a: Sre 18 Maj 2011 15:08
Prispevkov: 188
Aktiv.: 1.20
Kraj: Maribor

PrispevekObjavljeno: Pon Nov 24, 2014 10:02 pm    Naslov sporočila:   Odgovori s citatom

Pozdravljeni,

prej objavljena koda preverjeno ne popravi obračanja signala.

Lep pozdrav,
Klemen
Nazaj na vrh
Skrit 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
Pojdi na stran Prejšnja  1, 2, 3  Naslednja
Stran 2 od 3

 
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: 48 dni


Powered by phpBB © 2001, 2005 phpBB Group