Sari la conținut
ELFORUM - Forumul electronistilor

Iar probleme cu 877


nassus

Postări Recomandate

Reusesc sa rezolv probleme complicate de programare si algoritmica dar nu reusesc sa rezolv o problema banala...am un buton conectat la RD1 (de exemplu) si un led la RB1, cand apas odata pe buton se aprinde ledul iar cand mai apas odata sa se stinga ledul.. prblema s-ar rezolva simplu cu sintaxa RB1=!RB1 dar din pacate nu o pot folosi pt ca ledul este aprins de o functie si de alta functie este stins. Am incercat o gramada metode dar nu reusesc sa rezolv 2 probleme : 1 debounce-ul butonulul fara prea mare delay si 2: chestia asta trebuie sa fie intr-o functie care primeste ca parametru pinul de intrare si sa nu returneze nimic...So astept idei...

Link spre comentariu
  • Răspunsuri 15
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • nassus

    6

  • Abram Burel

    2

  • MihaiStoica

    1

In primul rand in ce scrii programele? Daca in C te pot ajutaGeneric vorbind daca butonul este pe RD1 (configurata ca intrare) trebuie sa baliezi intrarea pentru a vedea(simti) trecerea din 0 in 1 sau invers. Alta metoda ar fi sa pui butonul pe RB1 si LED-ul pe alt pin (iesire).RB1 trebuie configurat ca intrare care sa genereze o intrerupere la schimbarea starii. Mai departe e treaba de pura programare

Link spre comentariu
Vizitator zuzurelu

In assembler ai putea incerca ceva de genul :

 

#define		BUTON		PORTB,1		#define		LED		PORTB,2		; FLAGS este un registru de uz generalMAIN;; etc; etc;;------------------------------------------; Butonul BUTON ;------------------------------------------btfsc	BUTON	                                ; Butonul este apasat ? goto	NU_S_A_APASAT_BUT	                     ; nope...                                                ; Da, acum este apasat	btfsc	FLAGS,1			                        ; Este prima oara apasat ?goto	SE_MENTINE_APASAT_BUT	                 ; Nope, butonul se mentine apasat											       ; Da, acest buton este apasat prima oara				                   ; ( ne intereseaza doar frontul POZ al comutarii )bsf		FLAGS,1					                 ; Ne ajutam de acest flag...;-------------------------------------; Actiunea BUTON, se va executa o singura data; la fiecare apasare de buton. Daca LED aprins, stinge-l si vice-versacall     DEBOUNCE     ; un delay de 10-20 mSbtfsc   LED      ; LED-ul era aprins ?bcf     LED	     ; stinge LED-ulbtfss   LED     ; LED-ul era stins ?bsf     LED      ; aprinde LED-ul                                                               ;-------------------------------------SE_MENTINE_APASAT_BUTgoto	END_BUT			                  ; Daca butonul se mentine apasat				                 ; nu facem nimic...NU_S_A_APASAT_BUT	bcf		FLAGS,1					; Am terminat cu flagul...END_BUT; END Buton BUT;-------------------------------------------------------------------------------;; etc; etc;

 

 

Nota : E doar o sugestie, copiii si televizoarele se fac la fata locului....

 

 

YO3HCV

Link spre comentariu
Vizitator musaraf

Uite si o varianta in "pseudocod".

Daca nu se poate detecta nivelul pinului cu intreruperi, nu mai ramane decat polling. O mare parte din viata sa programul o sa si-o petreaca verificand starea lui RB1.

 

unsigned char Setat;  // variabila globala, nu stiu cu ce compilator mergevoid main(){   Setat = 0;   PORTD.PIN1 = LOW;   for (;;)                 // bucla principala   {      while(!PORTB.PIN1);   // asteapta sa apasam butonul       schimba_stare_portD();   }}   void schimba_stare_portD()   // efect colateral{   delay_ms(50);        // sau cat trebuie ptr debounce   if (Setat)           // Schimbam si starea lui Setat, si a lui PORTD      PORTD.PIN1 = LOW;   else      PORTD.PIN1 = HIGH;   Setat  = ~Setat;     // sau Setat = !Setat, Setat = Setat^Setat etc.}

Normal, se poate si fara variabila globala, dar atunci functia ar trebui sa intoarca o valoare:

 

void main(){   unsigned char Setat;   for(;;)   {   ...   Setat = schimba_stare_portD();   ...   }}
Link spre comentariu

Bun codul pana la functia care aprinde ledul... Functia asta trebuie sa primeasca, ca si parametru pinul de intrare (RD1).Am incercat sa ii pun ca si parametru pinul dar nu mai merge cum trebuie.. adica atunci cand se apasa butonul se aprinde ledul iar cand se elibereaza butonul se stinge ledul.. Plus ca daca tin butonul apasat ledul se stinge si se aprinde cu o perioada care depinde de delay.So.. alte idei?

Link spre comentariu
Vizitator zuzurelu

Bun codul pana la functia care aprinde ledul... Functia asta trebuie sa primeasca, ca si parametru pinul de intrare (RD1).Am incercat sa ii pun ca si parametru pinul dar nu mai merge cum trebuie.. adica atunci cand se apasa butonul se aprinde ledul iar cand se elibereaza butonul se stinge ledul.. Plus ca daca tin butonul apasat ledul se stinge si se aprinde cu o perioada care depinde de delay.So.. alte idei?

Normal, tu trebuie sa detectezi software FRONTUL butonului si nu PALIERUL. Adica dupa ce ai detectat PRIMA OARA schimbarea, executi ceva si nu mai treci pe acolo pana nu se ia labutza de pe buton. Altfel, vei detecta CU FRECVENTA DE EXECUTIE a buclei principale ( choppata de functia DEBOUNCE ), mereu, acelasi buton apasat si deci vei executa de o multime de ori ACTIUNEA care te intereseaza.Daca vrei un bistabil, poti face foarte simplu treaba asta incrementand cu 1 un byte (un char) oarecare si verificand bitul 0 al sau. O data va fi 0 iar urmatoarea va fi 1 intotdeauna.YO3HCV,
Link spre comentariu

O idee ar fi ca durata debouncing-ului depinde de tipul de buton folosit. Asta inseamna ca ar trebui sa poti astepta stabilizarea starii atata cat sa se potoleasca contactul electric. Avand in vedere ca tu lucrezi la nivel de maxim usec per instructiune, nu prea vad de ce sa nu reusesti sa-l faci mai rapid daca butonuliti permite (daca nu, n-ai de ce sate stresezi in program ca nu rezolvi nimic).O alta idee are fi ca chiar daca faci apelul cu 2 functii diferite, nu vad de ce nu poti "pasa argumentul" intr-o variabila globala. Daca n-ai loc nici de asta, poate gasesti vreun bit de status.... nefolosit :)

Link spre comentariu
Vizitator zuzurelu

O idee ar fi ca durata debouncing-ului depinde de tipul de buton folosit. Asta inseamna ca ar trebui sa poti astepta stabilizarea starii atata cat sa se potoleasca contactul electric. Avand in vedere ca tu lucrezi la nivel de maxim usec per instructiune, nu prea vad de ce sa nu reusesti sa-l faci mai rapid daca butonuliti permite (daca nu, n-ai de ce sate stresezi in program ca nu rezolvi nimic).O alta idee are fi ca chiar daca faci apelul cu 2 functii diferite, nu vad de ce nu poti "pasa argumentul" intr-o variabila globala. Daca n-ai loc nici de asta, poate gasesti vreun bit de status.... nefolosit :)

Nu este bine sa folosesti bitii STATUS ca indicatori tip flag. Este o sursa periculoasa de erori stupide, mai ales daca NU lucrezi in assembler. Ai suficienta memorie sa definesti un byte sau un char ca octet de flaguri.Ce idei iti mai trebuie pentru un simplu push-buton ? Ti-am pus o rutina asm ce detecteaza atat frontul crescator cat si palierul + frontul coborator, inclusiv debounce. Retine conceptul si aplica-l in C.YO3HCV,
Link spre comentariu
Vizitator musaraf

Pentru problema cu debounce nu mai scriu, ca am inteles ca totusi merge, numai timpul pentru debounce este prea mare.

Pentru functia care are ca argument un pin, depinde de compilatorul tau. Daca accepta o sintaxa de tipul

byte pin;byte val;val = PORTD.pin;
este mai simplu. Daca nu, tot va merge cu switch:

 

void schimba_stare_portB(int pin_din_D){   delay_ms(timp_debounce);   switch (pin_din_D)    {      case 0:          PORTB.PIN0 = ~Setat0;          .....         break;       case 1:         PORTB.PIN1 = ~Setat1;          .....      ...   }}

Eventual zi cu ce compilator lucrezi, si poate bucata de program care face

treaba. Si eu sint curios.

Link spre comentariu
Vizitator musaraf

Eroarea din post-ul de la inceput ( executa de mai multe ori functia schimba_stare_port(), cat timp se tine apasat butonul ) cred ca se rezolva cam asa:

 

 for (;;)                 // bucla principala    {       while(!PORTX.PIN1);   // asteapta sa apasam butonul       schimba_stare_portY();      while(PORTX.PIN1);   // asteapta sa lasam butonul      delay_ms(timp_debounce);   // ziceam ca si la deschidere trebuie debounce   } 
Link spre comentariu
  • 3 săptămâni mai târziu...

Revin cu probleme....Vreau sa determin pozitia unui mecanism aflat intr-un mediu mai putin ospitalier (portiera unei masini (dacia)). Mecanismul are o rotatie de vreo 70 grade maxim si din acest motiv ma gandeam sa folosesc un potentiometru dar fiind un mediu asa de nasol cred ca jumatate din timpul alocat pt proiect o sa il petrec realizand o cutie cu filtre de aer si umezeala pt potentiometru si nu prea e ok.M-am mai gandit la un sistem tip mouse dar in cazul in care mecanismul este miscat fara ajutorul motorului atunci se decaleaza totul si nu mai merge. Ce idei aveti pt chestia asta?MersiPS. Daca intereseaza pe cineva codul pt debouncing sa ma anunte sa il postez.

Link spre comentariu

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 cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări