|
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
VolkD Član
Pridružen-a: Pet 24 Sep 2004 21:58 Prispevkov: 14228 Aktiv.: 63.86 Kraj: Divača (Kačiče)
|
Objavljeno: Tor Okt 28, 2014 6:22 pm Naslov sporočila: |
|
|
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 |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.19 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 7:14 pm Naslov sporočila: |
|
|
Vsem še enkrat hvala za odgovore! So mi zelo v pomoč, vprašanje je edino, ali jih prav razumem 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 |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.05
|
Objavljeno: Tor Okt 28, 2014 7:26 pm Naslov sporočila: |
|
|
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 |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.19 Kraj: Maribor
|
Objavljeno: Tor Okt 28, 2014 8:44 pm Naslov sporočila: |
|
|
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 |
|
|
Sigi Član
Pridružen-a: Čet 31 Jul 2014 11:42 Prispevkov: 199 Aktiv.: 1.68 Kraj: Kamnik
|
Objavljeno: Tor Okt 28, 2014 9:45 pm Naslov sporočila: |
|
|
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 |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.05
|
Objavljeno: Tor Okt 28, 2014 9:50 pm Naslov sporočila: |
|
|
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 |
|
|
tilz0R Član
Pridružen-a: Čet 31 Maj 2012 15:39 Prispevkov: 898 Aktiv.: 6.21 Kraj: Črnomelj
|
Objavljeno: Tor Okt 28, 2014 9:56 pm Naslov sporočila: |
|
|
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 |
|
|
igo Član
Pridružen-a: Sre 11 Okt 2006 19:11 Prispevkov: 3638 Aktiv.: 17.05
|
Objavljeno: Tor Okt 28, 2014 10:25 pm Naslov sporočila: |
|
|
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 |
|
|
dejko1 Član
Pridružen-a: Ned 16 Mar 2008 0:21 Prispevkov: 265 Aktiv.: 1.35 Kraj: Ljubljana
|
Objavljeno: Tor Okt 28, 2014 10:51 pm Naslov sporočila: |
|
|
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 |
|
|
Sigi Član
Pridružen-a: Čet 31 Jul 2014 11:42 Prispevkov: 199 Aktiv.: 1.68 Kraj: Kamnik
|
Objavljeno: Tor Okt 28, 2014 11:19 pm Naslov sporočila: |
|
|
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 |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.19 Kraj: Maribor
|
Objavljeno: Sre Okt 29, 2014 12:06 am Naslov sporočila: |
|
|
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 |
|
Nazaj na vrh |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.19 Kraj: Maribor
|
Objavljeno: Pon Nov 24, 2014 12:47 pm Naslov sporočila: |
|
|
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
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 |
|
|
dejko1 Član
Pridružen-a: Ned 16 Mar 2008 0:21 Prispevkov: 265 Aktiv.: 1.35 Kraj: Ljubljana
|
Objavljeno: Pon Nov 24, 2014 1:40 pm Naslov sporočila: |
|
|
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 |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.19 Kraj: Maribor
|
Objavljeno: Pon Nov 24, 2014 9:26 pm Naslov sporočila: |
|
|
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 |
|
|
KlemenD Član
Pridružen-a: Sre 18 Maj 2011 15:08 Prispevkov: 188 Aktiv.: 1.19 Kraj: Maribor
|
Objavljeno: Pon Nov 24, 2014 10:02 pm Naslov sporočila: |
|
|
Pozdravljeni,
prej objavljena koda preverjeno ne popravi obračanja signala.
Lep pozdrav,
Klemen |
|
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: 70 dni
Powered by phpBB © 2001, 2005 phpBB Group
|