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

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
tessier
Inlägg: 7
Blev medlem: 30 mars 2009, 10:28:07

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

Inlägg av tessier »

Scott Dattalo kan man lita på :humm:

Mycket intressant lösning då man kan köra åtta knappar parallellt med bara tre minnesregister.

http://www.dattalo.com/technical/softwa ... rtcnt.html

// Stefan
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 »

Dattalo-länken innehöll lite för många sidor djuplodande läsning för min smak, om jag ska vara ärlig, och det ska man ju. :)
edit: Det var pdf-filen på förra sidan jag tänkte på egentligen, men raden ovan stämmer iofs ändå. Jobbigt att bara döpa variabler till två bokstäver..


Jag har testat bl.a Swech's och Icecap's metoder. Tydligen har jag en väldigt rosslig knapp,
för vilken av rutinerna jag än använder så blir det ändå studsar när jag ska "toggla" någon funktion eller lysdiod.
Knappen är helt ny, av den här modellen kopplad till PORTA,4 med pulldown-motstånd.
Jag har testat med lite olika kondingar (47pF - 100nF) över knappen, utan någon större skillnad.


Såhär ser den nuvarande rutinen ut som körs med 100Hz (interrupt från en timer, verifierad frekvens med oscilloskop.) :

Kod: Markera allt

knapp_test

;Knapp-koll
	bcf			knapp_pos, 0		;Nolla knappens avlästa läge.
	btfsc		PORTA, 4			;Knappen är intryckt? Om inte: Hoppa över nästa rad.
	bsf			knapp_pos, 0		;Knappen avläst som intryckt en gång..

;Spara current
	movf		knapp_pos, 0		;knapp_pos till W.
	movwf		knapp_current		;W till knapp_current.

;Resultat
	movf		knapp_previous, 0	;knapp_previous till W.
	andwf		knapp_current, 0	;knapp_current AND W (knapp_previous). Resultatet till W.
	movwf		knapp_resultat		;W (resultatet) till knapp_resultat.

;Spara nästa previous
	movf		knapp_current, 0	;knapp_current till W.
	movwf		knapp_previous		;W (current) till knapp_previous.



;Knapp_toggle
	btfsc		knapp_current, 0	;Är knapp_current = 1 ? Om inte: Hoppa över nästa rad.
	comf		knapp_onoff, 1		;Toggla knapp_onoff.

;LED_visning
	btfsc		knapp_onoff, 0		;Är knapp_onoff = 1 ? Om inte: Hoppa över nästa rad.
	movlw		h'00'				;Tänd lysdioderna. (Inverterat, därav 00.)
	btfss		knapp_onoff, 0 		;Är knapp_onoff = 0 ? Om inte: Hoppa över nästa rad.
	movlw		h'ff'				;Släck lysdioderna. (Inverterat.)
	movwf		PORTC				;Lysdioderna..

return
"knapp_koll" och de två sista 'delarna' kan kanske göras snyggare om man vill.

I MPLAB_SIM fungerar det fint, men där finns ju inte heller någon knappstuds. :)


Förslag på ändringar i mjukvara eller hårdvara?
(Har provat andra knappar av samma sort. Tyvärr har jag ingen annan modell som får plats där den ska sitta.)

edit: Glömde berätta att elektroniken sitter på ett kretskort. Knappen är ansluten med 8cm långa tvinnade flerkardeliga sladdar.
Användarvisningsbild
electronix
Inlägg: 353
Blev medlem: 29 mars 2009, 10:48:08
Ort: Norrköping

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

Inlägg av electronix »

Testa med att lägga ett 100 ohm motstånd i serie direkt vid portpinnen och kondingarna mot jord efter motståndet, men det kanske du redan har försökt med.
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 »

Jag har testat med 220 ohm och diverse kondingar utan skillnad, men jag kanske inte har hittat rätt konding.
Det är lite olika bud på storleken i de andra trådarna som handlar som kontaktavstuds..

I dessa trådar nämns även att det räcker med avstuds i mjukvaran.
Men jag verkar inte lyckas med både avstuds i mjukvara *och* hårdvara...


Vissa dagar går verkligen allt som smort... :roll:
Användarvisningsbild
tecno
Inlägg: 27256
Blev medlem: 6 september 2004, 17:34:45
Skype: tecnobs
Ort: Sparreholm, Södermanland N 59° 4.134', E 16° 49.743'
Kontakt:

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

Inlägg av tecno »

Dags att hiva in en Schmitt-trigger?
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 »

Jimmy: din rutin är lite konstig. Ena stunden använder du en bit till att hålla reda på huruvida knappen är aktiverat och sparar detta i en byte som en bit - varefter du använder hela byten som indikering av tryckt eller inte. Är du SÄKER på att hela byten är nollad?
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 »

Jag har kört runt några gånger med simulatorn och hela byten blir nollad som den ska innan loopen där koden bara kör runt och väntar på timer-interrupt.

Att jag först använder en bit och sedan går över till bytes är för att jag (än så läge)
inte har hittat något smidigt sätt att flytta en bit från ett register till ett annat (via W).
I början av rutinen nollar jag biten och ändrar den (till 1) ifall PORTA,4 är hög,
men det kändes omständigt att använda den principen i hela rutinen.

Egentligen skulle jag iochförsig kunna använda bytes hela vägen (h'00' och h'FF').
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 »

> att jag (än så läge)
> inte har hittat något smidigt sätt att flytta en bit från ett register till ett annat (via W)

Om det är samma position, ett par AND/OR borde fixa det.
Om det är olika position, en BTFSS/BTFSC och lite mer logik fixar det.
I fall två (som i och för sig funegrar i båda fallen) behövs inte W.
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 »

Jag har testat med AND för att "filtrera bort" allt utom första biten i varje byte, men ändå ingen framgång tyvärr.

Hur pass bra ska en avstuds-rutin av den här typen fungera egentligen?
"Bra" är ju relativt, men som exempel:
1) Hänger det på att man har en guldpläterad brytare i toppskick?
2) Eller ska det fungera med en sådan som jag länkade till tidigare?
3) Ska det rent av fungera om man är lite darrig och sätter två sladdar mot varandra?

Jag vet faktiskt inte riktigt hur/var jag ska gå vidare nu.
RC-filter, mjukvaru-avstuds.. ska jag verkligen behöva slänga in en schmitt-trigger också?
I andra mjukvaruavstuds-trådar har jag fått intrycket av att det ska räcka med avstudshantering i mjukvaran.



Hela min kod som den ser ut nu, ifall någon vill testa:

Kod: Markera allt

;****************************************************
	list		p=PIC16F688
	include		"p16f688.inc"
;****************************************************
;
;	PIC16F688. Intern oscillator på 8MHz.
;
;
;	Lysdioder 1 - 6 : RC0 - RC5.
;	Knapp (JP1) : RA4. (pin 3).
;
;
;****************************************************

	__CONFIG _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF

	errorlevel	-302

;****************************************************
;	Definiera diverse namn...

;	#define		KNAPP		PORTA, 4

;****************************************************
;knapp_vars		UDATA_SHR
;variabel		RES 1

; det blir mer här senare..

;****************************************************

Boot		CODE	h'0000'
	goto	start

;****************************************************

Int_vect	CODE	h'0004'

	goto	isr_rutin

;****************************************************
; MACRO

; kommer senare...

;****************************************************

Main	CODE

Start

;Generell setup
	banksel	OPTION_REG
	bsf		OPTION_REG,	NOT_RAPU	;PORT A pull-ups disabled
	bsf		OPTION_REG,	INTEDG	;Interrupt on rising edge of RA2/INT --
	bcf		OPTION_REG,	T0CS	;TMR0 internal clock  --
	bcf		OPTION_REG, PSA		;Prescaler är tilldelad Timer0-modulen --
	bsf		OPTION_REG, PS2		;Prescaler 1:128
	bsf		OPTION_REG, PS1		;Prescaler 1:128
	bcf		OPTION_REG, PS0		;Prescaler 1:128

	banksel	WDTCON
    bcf		WDTCON, SWDTEN		;WDT turned off

;	Interrupt
	banksel	INTCON
    bsf		INTCON, GIE		;Global interrupt enable bit  <--
    bsf		INTCON, PEIE	;Enable unmasked peripheral interrupts <--
    bsf		INTCON, T0IE	;Enable the Timer0 interrupt <--
    bcf		INTCON, INTE	;Disable the RA2/INT external interrupt
    bcf		INTCON, RAIE	;Disable the PORTA change interrupt <--
    bcf		INTCON, T0IF	;Timer0 did not overflow <--
    bcf		INTCON, INTF	;RA2/INT external interrupt did not occur
    bcf		INTCON, RAIF	;None of the PORTA-pins have changed state <--
    
	banksel	IOCA
	movlw	b'00000000'		;Inga interrupt on change på PORTA. <--
    movwf	IOCA
    
	banksel	PIE1
    bcf		PIE1, EEIE		;Disable the EE write complete interrupt
    bcf		PIE1, ADIE		;Disable the ADC-interrupt <--  DISABLED NU
    bcf		PIE1, RCIE		;Disable the EUSART receive interrupt
    bcf		PIE1, C2IE		;Disable the comparator C2 interrupt
    bcf		PIE1, C1IE		;Disable the comparator C1 interrupt
    bcf		PIE1, OSFIE		;Disable the oscillator fail interrupt
    bcf		PIE1, TXIE		;Disable the EUSART transmit interrupt
    bcf		PIE1, TMR1IE	;Disable the Timer1 overflow interrupt <<<<

	banksel	PIR1
    clrf	PIR1			;Cleara alla interrupt
    bcf		PIR1, ADIF		;AD interrupt clear <--


;	Klocka
	banksel	OSCCON
	bsf		OSCCON, IRCF2	;8MHz
	bsf		OSCCON, IRCF1	;8MHz
	bsf		OSCCON, IRCF0	;8MHz
	bcf		OSCCON, SCS		;Fosc = systemklockan


;	I/O
	banksel	TRISA
;	movlw	b'00010100'		;Allt till utgångar, bortsett från knappen (R4) och poten (R2).
	movlw	b'00010000'		;Allt till utgångar, bortsett från knappen (R4).
	movwf	TRISA
	banksel	TRISC
	clrf	TRISC			;Alla till utgångar, för lysdioderna.

	banksel	PORTA
	clrf	PORTA			;Tomt
	banksel	PORTC
	movlw	h'FF'			;Tomt (OBS: Inverterat för lysdioderna).	<<<<<<<<<
	movwf	PORTC
    
	banksel	WPUA
    clrf	WPUA			;Inga pull-ups
    

;	Timers
	banksel	TMR0
	movlw	d'100'			;TMR0 start. <<<<<<<<<<<<<<<<
	movwf	TMR0

	banksel	T1CON
	bcf		T1CON, TMR1ON	;Timer1 avstängd

;	Comparator
	banksel	CMCON0
    bsf		CMCON0, CM2		;Comparators avstängda
    bsf		CMCON0, CM1		;Comparators avstängda
    bsf		CMCON0, CM0		;Comparators avstängda
	banksel	VRCON
    bcf		VRCON, VREN		;CVref powered down

;	ADC
	banksel	ANSEL
;	movlw	b'00000100'		;AN2 (pin 11) analog. Resten digitala
	movlw	b'00000000'		;Digitala ingångar.
	movwf	ANSEL
    
	banksel	ADCON0
    bsf		ADCON0, ADFM	;Högerjusterad AD
    bcf		ADCON0, VCFG	;Vdd som referens
    bcf		ADCON0, CHS2	;Channel: AN2 (pin 11)
    bsf		ADCON0, CHS1	;Channel: AN2 (pin 11)
    bcf		ADCON0, CHS0	;Channel: AN2 (pin 11)
    bcf		ADCON0, ADON	;ADC disabled <--  DISABLED!!
    bcf		ADCON0, GO_DONE	;AD-conversion NOT in progress <--

	banksel	ADCON1
    bcf		ADCON1, ADCS2	;AD Conversion clock: Fosc/32 = 250kHz
    bsf		ADCON1, ADCS1	;AD Conversion clock: Fosc/32 = 250kHz
    bcf		ADCON1, ADCS0	;AD Conversion clock: Fosc/32 = 250kHz


;	USART
	banksel	TXSTA
    bcf		TXSTA, TXEN		;EUSART transmit disabled
    clrf	RCSTA			;EUSART port disabled
    bcf		BAUDCTL,ABDEN	;Auto-baud detect disabled


	;Rensa. (För att lättare se i MPLAB SIM.)
	clrf		rakna_knapp    
	clrf		knapp_onoff

;****************************************************
;****************************************************
;****************************************************

;Main-loopen

loop

	goto 	loop			;Om och om igen...

;****************************************************
;****************************************************
;****************************************************

;				Sub-rutiner här under
;****************************************************

knapp_vars		UDATA_SHR
knapp_pos		RES 1	
knapp_onoff		RES 1				;Knappen. (Togglas vid nedtryck.)

knapp_current	RES 1
knapp_resultat	RES 1
knapp_previous	RES 1


sub_rutiner		CODE




;****************************************************

knapp_test

;Knapp-koll
	bcf			knapp_pos, 0		;Nolla knappens avlästa läge.
	btfsc		PORTA, 4			;Knappen är intryckt? Om inte: Hoppa över nästa rad.
	bsf			knapp_pos, 0		;Knappen avläst som intryckt en gång..

;Spara current
	movf		knapp_pos, 0		;knapp_pos till W.
	andlw		b'00000001'			;TEST för att försäkra mig om att bara första biten används. <<
	movwf		knapp_current		;W till knapp_current.

;Resultat
	movf		knapp_previous, 0	;knapp_previous till W.
	andlw		b'00000001'			;TEST för att försäkra mig om att bara första biten används. <<
	andwf		knapp_current, 0	;knapp_current AND W (knapp_previous). Resultatet till W.
	andlw		b'00000001'			;TEST för att försäkra mig om att bara första biten används. <<
	movwf		knapp_resultat		;W (resultatet) till knapp_resultat.

;Spara nästa previous
	movf		knapp_current, 0	;knapp_current till W.
	andlw		b'00000001'			;TEST för att försäkra mig om att bara första biten används. <<
	movwf		knapp_previous		;W (current) till knapp_previous.



;Knapp_toggle
	btfss		knapp_current, 0	;Är knapp_pos = 1 ? Isåfall: Hoppa över nästa rad.
	goto		LED_visning
	comf		knapp_onoff, 0		;Toggla knapp_onoff. TEST: Resultatet till W.
	andlw		b'00000001'			;TEST för att försäkra mig om att bara första biten används. <<
	movwf		knapp_onoff			;TEST tillbaka med resultatet till knapp_onoff.

LED_visning
	btfsc		knapp_onoff, 0		;Är knapp_onoff = 1 ? Om inte: Hoppa över nästa rad.
	movlw		h'00'				;Tänd lysdioderna. (Inverterat, därav 00.)
	btfss		knapp_onoff, 0 		;Är knapp_onoff = 0 ? Om inte: Hoppa över nästa rad.
	movlw		h'ff'				;Släck lysdioderna. (Inverterat.)
	movwf		PORTC				;Lysdioderna..

	return

;****************************************************
;****************************************************
;	Interrupt

isr_vars		UDATA_SHR
pot_lo			RES 1
pot_hi			RES 1
	

isr_rutin		CODE


isr_rutin


	;Timer0 Interrupt. (TMR0 start: 100. Frekvens: 100.16 Hz. Period: 0.009984 sek.)
	banksel		INTCON
	btfss		INTCON, T0IF		;TMR0 interrupt? Isåfall: Hoppa över nästa rad.
	goto		timer0_slut			;Hoppa till slutet.
	call		knapp_test			;Hoppa till rutinen som läser av knappen.

	bcf			INTCON, T0IF		;Cleara TMR0 interrupt-flaggan.
	bsf			INTCON, T0IE		;Redo för nytt interrupt.
	movlw		d'100'				;TMR0 start. <<<<<<<<<<<<<
	movwf		TMR0

timer0_slut

	retfie

;****************************************************

	end
(Dessa tabbar när man klistrar in kod här.... :doh: Varför blir det bra på vissa rader men åt skogen på andra?)
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 »

Bara en tanke. Du nämner att du verifierat frekvensen av interrupten med ett oscilloskop men har du kikat på hur knappen beter sig också? Där kan du ju lätt se hur länge det fladdrar osv.

Nu är inte jag den mest erfarne på forumet (dagens underdrift) men enligt allt jag läst och själv testat så ska det räcka fint med mjukvara.
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 »

Bra fråga, det hade jag glömt att skriva. :)

Nu har jag inget oscilloskop med minne i närheten, men vad jag kan se på det analoga så är det i genomsnitt 5ms "skräp"
precis när man trycker ner knappen. Nu brukar jag inte mäta knappar, men av vad jag sett från oscilloskop-skärmdumpar
(på sajter som handlar om detta) så är min knapps "skräp" ganska normalt.

Jag lyckades gräva fram en påse knappar som är guldpläterade både på insidan och utsidan. Kan jämföra med dem senare. :)
Tyvärr är de inte momentana (dvs de behåller läget även efter man släppt knappen), men de borde fungera för att mäta med.

Om någon gör jämförande mätningar: Ta mina 5ms med en nypa salt. Det är svårt att hinna se på ett analogt oscilloskop.
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

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

Inlägg av bos »

Jag har inte lusläst tråden, men finns det någon anledning till att du inte implementerar avstudsaren i hårdvara? En kondensator och ett motstånd är allt som behövs:

Kod: Markera allt

+V ----[SW]--+--+---- [µC]
             |  |
            [R][C]
             |  |
             +--+
             GND
10k och 1µF är lagom värden. Detta ger följande resultat (grön kurva, den blå är samma typ av avstudsare men aktiv låg istället):

Bild
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 »

Det finns lite nackdelar med hårdvaran.

Frånsett fler komponenter och därmed högre pris och fler felkällor är den koppling du anger en störning i sig.

Med en 1µF kondensator kommer ett tryck på knappen att ladda upp kondensatorn mycket snabbt, detta kräver en hel del ström och ge ett dyk i VDD = störning. Ett motstånd (kanske 100 ohm) i serie med knappen kan sänka den ström men är ytterligare en kostnad och felkälla.

Så det finns goda anledningar att INTE ha avstutsning i hårdvara faktisk.
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

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

Inlägg av bos »

Visst finns det nackdelar, men det finns ju nackdelar med mjukvarulösning också. Ökad kodkomplexitet är en. Allt handlar ju om en avvägning mellan för- och nackdelar för en viss lösning. Min undran rörde sig om det fanns en anledning till att just en mjukvarulösning eftersträvades.
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 »

Kan du inte testa att köra med 10hz för att verifiera att din avstudsning funkar
i mjukvaran?

Swech
Skriv svar