Vizitator Ace29 Postat Iunie 15, 2011 Partajează Postat Iunie 15, 2011 Salut. Am si eu o intrebare. Am un intrerupator rotativ PS1010-20 care vreau il conectez la un ATmega32. L-am conectat la cele doua intreruperi externe ale uC, INT0 si INT1. Am initilizat o variabila globala care sa fie incrementata pe INT0 si decrementata pe INT1. Problema este ca la o singura rotatie de la intrerupator (un singur click) mie imi incrementeaza/decrementeaza cateodata de 2 ori sau 3 ori. Am cautat pe net si din cate am inteles trebuie sa fac un debounce care poate fi facut hardware sau software dar nu am inteles cum se face. Stie cineva cum se poate realiza un debounce software? Link spre comentariu
10vid Postat Iunie 15, 2011 Partajează Postat Iunie 15, 2011 Debouncing ignora activitatea pe portul respectiv (aici prin dezactivarea intreruperii) pentru o perioada scurta de timp (cateva zeci de ms) cat timp contactul nu e complet asezat.In rutina de servire a intreruperii, inainte de a iesi adauga un delay de vreo 0.2s, sau cat crezi ca sta contactul inchis. (Habar n-am cum functioneaza butonul ala, dar ma gandesc, logic ar fi ca in repaus ambele contacte sa fie deschise, si doar cand face click un contact sa fie inchis pentru un timp scurt, nu?) Link spre comentariu
mitescu Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 O metoda (asemanatoare cu cea dinainte) si care functioneaza f. bine, este urmatoarea:- se activeaza cele doua intreruperi externe- se programeaza o intrerupere de la un timer (ex. Timer0Ovf), dar nu se activeaza- la aparitia primei intreruperi de la un INTx - de zeactiveaza acea intrerupere -GICR.INTx=0- se activeaza intreruperea de le timer ptr un timp necesar "linistirii contactului"(ex. 100us)- dupa acest timp va apare intreruperea de la timer- in rutina de deservire a intreruperii de la timer se testeaza bitii corespunzatori din registru GICR- in cazul in care unul din cei doi este in 0, insemna ca a avut loc o intrerupere - (suplimentar se poate testa pinul respectiv)- in aceeasi rutina de la timer , in continuare se trateaza respectiva situatie ptr INTx- se dezactiveaza intreruperea de la Timer si se reactiveaza INTxAceasta metoda este valabila pentru orice tip de comutatorDaca este vorba de un comutator "bifazic"(cum presupun eu ca ar fi), din acelea de tip "fara sfarsit ", metoda este mult mai simpla si presupune urmatoarea logica: Amandoua contacte se fac in ordine functie de directia in care se roteste comutatorul. Se activeaza una din INT( ex. INT0), iar la aparitia acestuia, se dezactiveaza si se astepta celalta Intrerupere (ex. INT1), in care se trateaza situatia , si la sfarsit se dezactiveaza INT1 si se reactiveaza INT0 si procesul se reia.In cazul in care nu te descurci , imi spui si iti pot da ca exemplu rutinele de la un encoder unghiular ce functioneaza dupa a doua metoda. Link spre comentariu
nico_2010 Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Salut. Am si eu o intrebare. Am un intrerupator rotativ PS1010-20 care vreau il conectez la un ATmega32. L-am conectat la cele doua intreruperi externe ale uC, INT0 si INT1. Am initilizat o variabila globala care sa fie incrementata pe INT0 si decrementata pe INT1. Problema este ca la o singura rotatie de la intrerupator (un singur click) mie imi incrementeaza/decrementeaza cateodata de 2 ori sau 3 ori. Am cautat pe net si din cate am inteles trebuie sa fac un debounce care poate fi facut hardware sau software dar nu am inteles cum se face. Stie cineva cum se poate realiza un debounce software?Monteaza cate un condensator de 1-10nF intre cele doua iesiri ale encoderului si masa si daca continua sa se manifeste la fel apeleaza la una din subrutinele existente pe net (care nu folosesc neaparat intreruperile externe ale controller-ului) Link spre comentariu
bogdan_ Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Iti trebuie o singura intrerupere pe unul dintre pini. Cand intrii in intrerupere verifici starea celuilalt pin. Daca e 0 ai o rotatie intr-un sens, daca e 1 e in sensul celalalt. Experienta mi-a aratat ca e cel mai bine sa mergi pe varianta fu condensatoare asa cum ti s-a spus. PRobabil ca se poate face debounce in software. Eu am incercat ceva, dar mai sarea/baga in plus pasi, am renuntat in favoarea condensatorului. Ca produs de serie merita scaderea costului si a BOMuliu prin soft. Ca hobby poti face cum e mai simplu si cu rezultate mai bune. Link spre comentariu
Vizitator Ace29 Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Intrerupatorul rotativ este urmatorul : http://www.adelaida.ro/product_info.php ... s_id=10473 . Pinii 1 si 4 ii conectez la ground iar 2 si 3 la INT0 si INT1. Codul folosit este cel de jos : void initializare_intreruperi(void) { sei(); //activam intreruperile globale MCUCR = (1< GICR = (1< PORTD |= (1< } SIGNAL (INT0_vect) //vectorul de intrerupere - { uart_puti(counter); USARTWriteChar('t'); if(counter > 98 ) {counter=0;} else {counter++;} GICR=(0< _delay_ms(200); GICR=(1< } SIGNAL (INT1_vect) //vectorul de intrerupere { uart_puti(counter); USARTWriteChar('t'); if(counter < -98 ){counter=0;} else { counter--;} GICR=(0< _delay_ms(200); GICR=(1< } Am pus acel delay si l-am pus si mai mare si degeaba. Pe Hyperterminal tot imi afiseaza mai multe valori la un singur click. Ce condensatoare sa folosesc? De cat ? 10nF e ok? Link spre comentariu
nico_2010 Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Asa cum am mai spus:"Monteaza cate un condensator de 1-10nF intre cele doua iesiri ale encoderului si masa" Link spre comentariu
Liviu M Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Pai intarzierea ai pus-o cam degeaba, ca incrementarea respectiv transmisia le faci deja inainte de intarziere. Ideea soft-debouncingului e ca atunci cand o intrare isi schimba starea, sa astepti o perioada (50..200ms sa zicem) si mai testezi o data sa vezi daca starea respectiva se mentine. In cazul intreruperilor, presupunand ca declansezi intreruperea cand iti vine un 1 pe o intrare (tranzitie din 0 in 1), cand vine intreruperea dezactivezi intreruperile (asta in primul rand, ca daca uControllerul accepta mai multe intreruperi, sunt sanse sa trigerezi mai multe de-astea pana ajungi sa prelucrezi una), astepti un timp si mai testezi o data intrarea respectiva. Daca se mentine in 1, e OK, ai avut un semnal corect, daca nu, nu. Asta in teorie. La tine s-ar putea sa se imbunatateasca lucrurile daca muti dezactivare intreruperilor la inceputul rutinei de tratare: SIGNAL (INT0_vect) //vectorul de intrerupere -{GICR=(0<<INT0);uart_puti(counter);USARTWriteChar('t');if(counter > 98 ) {counter=0;}else {counter++;}_delay_ms(200);GICR=(1<<INT0);} PS Nu stiu cum functioneaza atmelurile, fac numai ceva teorie "la rece" si sper ca bucata de cod pe care ai scris-o in postul anterior e functionala. Link spre comentariu
10vid Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 La tine s-ar putea sa se imbunatateasca lucrurile daca muti dezactivare intreruperilor la inceputul rutinei de tratareCand se intra in ISR, uC dezactiveaza automat toate intreruperile prin stergerea flag-ului I din SREG. Nu mai are rost sa dezactivezi intreruperea la periferic.Totusi, trebuie acordata atentie flagilor de cerere de intrerupere INTF0 si INTF1, acestia putandu-se seta chiar si atunci cand toate intreruperile sunt dezactivate si se pare, chiar si atunci cand INT0 si INT1 (int. enable) sunt dezactivati.De buna seama astia se vor seta si in cursul ISR-ului din cauza bouncing-ului, chiar daca la intrarea in ISR sunt si ei automat stersi de catre uC impreuna cu I din SREG. Apoi dupa iesirea din ISR, vor cauza o intrerupere falsa. Asa ca trebuie stersi (prin scrierea unui 1 logic!!!) la iesirea din ISR, adica dupa acel delay:SIGNAL (INT1_vect) //vectorul de intrerupere{uart_puti(counter);USARTWriteChar('t');if(counter < -98 ){counter=0;}else { counter--;}_delay_ms(200);GIFR=(1<<INTF1);} Link spre comentariu
10vid Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Cat despre varianta cu condensatoare, mi se pare o prostie. Eu inca n-am vazut condensatoare lipite paralel cu push-butoane in nici un aparat pe care l-am deschis, si au fost ceva aparate, unele chiar cu 10-15 butoane. "Pai asta-i rotary switch" or sa sara unii. E acelasi lucru. Sau push- butoanele sunt perfecte si nu necesita condensator? Ma-ndoiesc.Scurt-circuitarea unui condensator de la 5v prin contactele butonului duce la aparitia scanteilor si implicit la uzura prematura a butonului. Apoi impulsurile de RF generate de aceasta descarcare (fapt patit!) si induse in alti conductori apropiati pot crea triggere false sau alte probleme greu de depistat.Binenteles ca introducerea in serie cu butonul a unei rezistente rezolva toata problema, totusi, cine a mai vazut asa ceva, o rezistenta si un condensator la fiecare buton sau tasta? Link spre comentariu
Liviu M Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Cand se intra in ISR... Bune observatiile. Eu inca n-am vazut condensatoare lipite paralel cu push-butoane in nici un aparat pe care l-am deschis, si au fost ceva aparate, unele chiar cu 10-15 butoane. E mai ieftin cu soft debouncing; efectul e cam acelasi (am testat). Scurt-circuitarea unui condensator de la 5v prin contactele butonului duce la aparitia scanteilor E vorba de nF, da? Binenteles ca introducerea in serie cu butonul a unei rezistente rezolva toata problema Nu ma prind din context, rezistenta asta rezolva problema condensatorului sau a butonului? Link spre comentariu
bogdan_ Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Nu iti apare nici o scanteie si nici nu se uzeaza prematur pentru ca ai un curent de descarcare de U/R, unde U e alimentarea circuitului si R e rezistenta de pull up/ down. Dupa cum am zis, preoblema o rezolvi cu condensator mai usor la nivel hobby. Nu e greu nici in soft. La nivel comercial este mai important sa fie costul mai mic. Repet si eu ce s-a mai spus: intarzierea aia face numai prosti in isr pentru simplu motiv ca 200ms e mult prea mult si vei sari garantat. Ce se intampla daca faci o rotatie completa(20 de pasi) in juma de secunda? Cat de des intra in intrerupere? Si repet, nu iti trebuie 2 itnreruperi. Una singura pe schimbarea lui INT0 sau 1 e suficient. Uite-te pe internet la niste forme de unda. De exemplu: http://www.hobbytronics.co.uk/rotary-encoder-tutorial Link spre comentariu
10vid Postat Iunie 16, 2011 Partajează Postat Iunie 16, 2011 Nu iti apare nici o scanteie si nici nu se uzeaza prematur pentru ca ai un curent de descarcare de U/R, unde U e alimentarea circuitului si R e rezistenta de pull up/ down.Descarcarea lui C nu se face prin rezistenta de pull-up.Repet si eu ce s-a mai spus: intarzierea aia face numai prosti in isr pentru simplu motiv ca 200ms e mult prea mult si vei sari garantat. Ce se intampla daca faci o rotatie completa(20 de pasi) in juma de secunda? Cat de des intra in intrerupere?Si repet, nu iti trebuie 2 itnreruperi. Una singura pe schimbarea lui INT0 sau 1 e suficient. Uite-te pe internet la niste forme de unda.De exemplu: http://www.hobbytronics.co.uk/rotary-encoder-tutorialDaca vroia sa faca 20 de pasi in juma de secunda isi lua rotary encoder, se-nvarte mult mai fin. Si aici cred ca faci confuzia intre ce are el (rotary switch) si rotary encoder.In cazul lui nu merge cu o singura intrerupere, pentru ca-i va citi doar o directie.Pana una-alta, problema lui era ca ii citea mai multe valori deodata. Sa-si rezolve asta si apoi mai vedem.200ms era doar o valoare orientativa. Bineinteles ca se poate reduce si de zece ori, poate chiar de o suta de ori. Link spre comentariu
bogdan_ Postat Iunie 17, 2011 Partajează Postat Iunie 17, 2011 Eu am folosit asa ceva: http://www.supertech-elec.com/electroni ... D1112S.pdf la un mood lamp. Si da, roteam cu peste 1 tura pe secunda. Softul ar trebui sa fie facut sareactioneze corect mereu. La lampa respectiva nu imi admintesc sa fi pus condensatoare, dar nici nu mai pot verifica. Uite si mai jos rutina de intrerupere. ISR(INT0_vect) { if(mod_sel) { if (PIND & (1<<PD3)) { if(mod<5) mod++; } else { if(mod>0) mod--; } } } if(cul_sel) { if (PIND & (1<<PD3)) { cul+=2; } else { cul-=2; } }_delay_ms(10);} Cu conensatorul ai dreptate, cand se descarca e in scurt prin buton. Link spre comentariu
nico_2010 Postat Iunie 17, 2011 Partajează Postat Iunie 17, 2011 Cat despre varianta cu condensatoare, mi se pare o prostie. Eu inca n-am vazut condensatoare lipite paralel cu push-butoane in nici un aparat pe care l-am deschis, si au fost ceva aparate, unele chiar cu 10-15 butoane. "Pai asta-i rotary switch" or sa sara unii. E acelasi lucru. Sau push- butoanele sunt perfecte si nu necesita condensator? Ma-ndoiesc. Faptul ca ai deschis destule aparate, chiar cu 10-15 butoane si nu ai vazut condensatori are o explicatie simpla: producatorul doreste sa reduca pretul produsului si apeleaza la minimizarea numarului de componente utilizate, solutia de reducere a vibratiilor lamelelor push-butoanelor fiind implementata cel mai probabil software. Scurt-circuitarea unui condensator de la 5v prin contactele butonului duce la aparitia scanteilor si implicit la uzura prematura a butonului. Apoi impulsurile de RF generate de aceasta descarcare (fapt patit!) si induse in alti conductori apropiati pot crea triggere false sau alte probleme greu de depistat. La concluzia de mai sus ai ajuns probabil dupa ce te-ai electrocutat serios atingand terminalele unui condensator de 10nF proaspat decuplat de la o baterie de 4,5V Explicatia este ca, in realitate, curentul de descarcare a condensatorului ar putea afecta - prin oxidare cel mai probabil - contactele encoderului si de aici restul observatiilor tale referitoare la perturbatii RF (nu am mai intrat in detalii de explicare a efectelor oxidarii). Binenteles ca introducerea in serie cu butonul a unei rezistente rezolva toata problema, totusi, cine a mai vazut asa ceva, o rezistenta si un condensator la fiecare buton sau tasta? Bineinteles ca ar putea rezolva... doar partial problema, deoarece aceleasi pardalnice de vibratii iti vor induce semnale de trigger flase, daca nu cumva alegand corect reteaua R-C ai obtine o usoara intarziere (in limita a 1-5 ms) care ar reduce considerabil acele semnale parazite. Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum