PIC: Hur gör man en bra avstuds-rutin? *Fixat*

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

PIC: Hur gör man en bra avstuds-rutin? *Fixat*

Inlägg av JimmyAndersson »

(PIC16F688. Assembler.)

Jag har sökt på "debounce" och hittade bl.a den här och den här men jag ser inte koden för själva avstuds-hanteringen.
Flera har skrivit att de använder timers och liknande för att läsa av knapparna flera gånger.
Jag kan inte riktigt se koden för timer-lösningen framför mig.

Min senaste variant bygger inte på timers:

Kod: Markera allt

isr_rutin
	;Knapp-interrupt.
	banksel		INTCON
	btfsc		INTCON,	RAIF		;PORTA change interrupt? Om inte: Hoppa över nästa rad.

;--
debounce
	btfss		PORTA, 4			;Intryckt knapp? Isåfall: Hoppa över nästa rad.
	goto		knappslut
	incf		rakna_knapp, 1		;Öka rakna_knapp med 1.
	btfss		rakna_knapp, 7		;Bit 7 satt (dvs rakna_knapp >=128) Isåfall: Hoppa över nästa rad.
	goto		debounce
	comf		PORTC, 1			;Toggla PORTC
;--

knappslut
	clrf		rakna_knapp			;Rensa
	banksel		INTCON
	bcf			INTCON, RAIF		;Clerara PORTA change interrupt.
	bsf			INTCON, RAIE
(förbaskade tabbar som inte håller sig på plats....)


Jag är medveten om att det är dumt att ha en såndär loop i ISR-rutinen,
men så länge jag bara exprimenterar med avstudsningen så gör det ju inget. :)


Jag satte några lysdioder på PORTC och en knapp med pulldown till PORTA.4.
Koden fungerar, men som avstuds är den ganska dålig. Man får oftast trycka 2-3 gånger för att PORTC ska ändras.
Testade att sätta en rad NOP i avstuds-rutinen och det blev bättre, men jag är lite tveksam till att det är en bra metod...


Jag skulle behöva lite råd på vad jag ska göra annorlunda. Det vore trevligt att se en avstuds-rutin för PIC.
Språk kvittar, men gärna assembler eftersom jag har återupptagit det. :)


edit: Det slog mig just.. Det är inte så att det krävs en lite annan lösning just eftersom jag använder "interrupt on change" ?
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av Swech »

Ett bra sätt är följande.

Sätt upp en timer som ger interrupt med 100Hz
I varje interrupt läser du av porten med knapparna.
Sätt "knapp status" = 0

100HZ
Läs av port
Är biten 1 = knapp intryckt så öka "Knapp intryckt" räknare med 1 Räkna till max 20
Är biten 0 = knapp ej intryckt så minska "Knapp intryckt" räknare med 1 Räkna till min 0

Är knapp status = 0 och "Knapp intryckt" > 15 så sätt knapp status = 1 (end)
Är knapp status = 1 och "Knapp intryckt" < 5 så sätt knapp status = 0 (end)
end


Får ju modifieras om knappen sluter mot + eller gnd samt utökas om fler knappar ansluts.

Swech
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av JimmyAndersson »

Aha! :idea:

Jag hade inte haft en tanke på att man skulle räkna ner också. Nu ser jag varför.

Stort tack! :tumupp:
Du är bra till mycket du.. :D
BJ
Inlägg: 8864
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av BJ »

Jag brukar nollställa räknaren varje gång som
det kommer en nolla.
Om man gör så här...

100 Hz
Läs av porten.
Är biten 1 = knapp intryckt, så öka "Knapp intryckt"-räknare
med 1. Räkna till högst 20.
Är biten 0 = knapp inte intryckt, så nollställ "Knapp intryckt".

Är "Knapp intryckt" 20 så sätt knapp status = 1. (end)
end

Då får huvudprogrammet nollställa varje ny
knapptryckning.

Blir det nån annan skillnad? Den kommer att bli
lite långsammare kanske?

Tillägg:
Nu tänkte jag på återfjädrande knappar.
Det kanske inte var det som Jimmy och Swech
tänkte på.
sneaky
Inlägg: 1621
Blev medlem: 22 juni 2009, 18:38:42

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av sneaky »

Jag brukar göra som du BJ, nollar räknaren varje gång statusen för pinnen inte är det jag söker.

Har även använt en variant av metoden som beskrivs på sidan 21 i följande PDF. Ett smart sätt att läsa av många olika inputs samtidigt. Hela PDFen är för övrigt ganska intressant läsning:
Användarvisningsbild
Oskar
Inlägg: 1939
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av Oskar »

Smarta tips! Wiki kanske?

Har för mig att jag gjorde så att pinnen måste ha samma tillstånd x antal pollningar i rad innan det räknas som en giltig nivå. Var länge sedan jag behövde göra någon avstuds.

/Oskar
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av Icecap »

Jag använder också en timer på 100Hz men har sedan länge skippat att räkna upp/ner osv.

Jag läser porten 1(!) gg per interrupt. Ska detta värde användas fler gångar i interrupten sparas det i en variabel.

Har även en variabel med den förra avläsning i, dessa två värden AND'er jag och resultatet är aktiva knapptryckningar.

Fungerar klickfritt i en del olika applikationer.
Alltså:
1: Läs porten.
2: Spara värdet till "Current"
3: Result = Current & Previous;
4: Previous = Current;
5: Utföra en n-key-rollover
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av Swech »

Allt hänger på hur hårt man vill filtrera.

Har man ett system där man skall t.ex. utföra något så länge som knappen är nedtryckt så kan det hicka till om
man nollställer sin avstudsning direkt då en 0a uppträder.
Men i de flesta fall funkar det bra ändå, Likaså Icecaps princip funkar också bra.

Något som däremot inbjuder till problem är att använda capture interrupt. Alltså trig då nivå ändrar sig.
Dessa interrupt är avsedda för att detektera klockpulser och data, inte mekaniska brytare eftersom
dessa studsar. I värsta fall kan processorn bli tokig då den interruptas med såpass korta intervall som uppstår
vid just kontaktstuds.

Swech
Användarvisningsbild
anlamotte
Inlägg: 859
Blev medlem: 5 augusti 2003, 15:54:34
Ort: Stockholm
Kontakt:

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av anlamotte »

Kan väl bidra med min metod :)
Jag använder en timer intruppt på ca 100hz.
Till detta 3 variabler som håller koll på status

Kod: Markera allt

  Sw0 aktiveras när knappen trycks ner
  Sw1 aktiveras när knappen släpps 
  Sw2 aktiveras när knappen hålls in en stund (för att snabbt stega i menyer m.m)
  Varje knapp använder 1 bit i varje variabel så knapp1 använder Sw0.0, Sw1.0 och Sw2.0
Funktionen blir att knapparna aktiveras när de släpps istället för när de trycks in.

Kod: Markera allt

Timer_ISR:
  If Pinb.6 = 1 And Sw0.1 = 1 Then   ' knappen har släppts efter den var intryckt!
    If Sw2.1 = 0 Then Sw1.1 = 1       ' knapp aktiverad
    Sw0.1 = 0                                 ' nollställ
    Sw2.1 = 0                                 ' nollställ
    Sw_tmr1 = 0                              ' nollställ
  End If

  If Pinb.6 = 0 Then                         ' knapp intryckt
    Sw0.1 = 1                                  ' spara knappstatus
    Incr Sw_tmr1                              ' knapp timer
    If Sw_tmr1 > 120 Then Sw2.1 = 1  ' knappen har hålts intryckt
  End If
Return
I huvudprogrammet:

Kod: Markera allt

  If Sw1.0 = 1 Or Sw2.0 = 1 then   ' knapp1 automatisk repetition
    ....gör vad som ska göras
    ....
    Sw1.0 = 0
  End if
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av v-g »

Kör med ismannens metod och den fungerar super. Har aldrig fått studsproblem.

Det gäller också att man har pullup/down-motstånd så att inte knappen svävar i ena läget. Samt att man använder en hyffsad brytare då också såklart.

Man kan även sätta en kondensator för att hindra för snabba omslag.
Användarvisningsbild
JimmyAndersson
Inlägg: 26586
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av JimmyAndersson »

Här var många bra tips. Håller med om att de borde skrivas in i wikin. :)
Nu fick jag även grepp om Icecaps' metod. Ska testa den också, för den verkar väldigt enkel och smidig.


Tackar! :tumupp: :tumupp:
sugarman64
Inlägg: 349
Blev medlem: 24 oktober 2008, 19:40:50
Ort: Lomma

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av sugarman64 »

Fattade inte den (Icecap's metod alltså). Någon som skulle vilja ge sig på att försöka förklara den lite närmare?
Ska snart skapa lite menyer och koppla in lite knappar till ett projekt, så denna tråd kom väldigt lägligt :)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av sodjan »

> Fattade inte den (Icecap's metod alltså).

Om du får "knapp tryckt" två gånger i rad så *är* "knapp tryckt". Ungefär...
sugarman64
Inlägg: 349
Blev medlem: 24 oktober 2008, 19:40:50
Ort: Lomma

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av sugarman64 »

Var väl ungefär det jag trodde. Verkade lite för enkelt bara.
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1355
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: PIC: Hur gör man en bra avstuds-rutin?

Inlägg av baron3d »

Jaha.. Här har vi en annan.

Kod: Markera allt

char inkey;
---
---
// Anropas lämpligen i 100Hz interrupt.
// lägger värde i "inkey"
void ReadKeys(void) {
   static char a0  a1, a2;

   a0=a1;
   a1=a2;
   a2=(~PORTA)&15;          //Maska bort oanvända bitar
   if(a2==a1 && a2>a0) {
      inkey|=a2;
   }
}
Efter man läst "inkey" nollställer man variabeln.
Alltså:

Kod: Markera allt

   if (inkey&1) .....
   ...
   ...
   inkey = 0;
Skriv svar