Uživatel:Vlkjan2

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Semestrální práce - Regulátor PC ventilátoru se zpětnou vazbou ze signálu TACHO

S kolegy Daliborem Baručákem, Lubomírem Vaculou a Josefem Houštěkem máme za úkol vytvořit Regulátor PC ventilátoru se zpětnou vazbou ze signálu TACHO, rychlost otáček je zadávána ve stupních 0-9 z klávesnice.

Nedá se přesně spravedlivě rozčlenit, kterou část, kdo dělal, neboť každý člen našeho týmu do práce přispěl nějakou částí, myšlenkou. Kdybychom chtěli napsat přesně, co kdo dělal, tak bychom se museli snažit ke každému řádku napsat něčí jméno. Práce byla řešena v týmu.

Soubor:CPU-FAN.png

[editovat] Zdrojový kód

[editovat] Použité zdroje

  • Atmel ATmega88 datasheet
  • fragmenty programů z MAM wiki

[editovat] Poznámky

  • časové konstanty jsou určované pro takt 1 MHz
  • R16 slouží v celém programu jako dočasný (TMP) registr
  • R17 testování puštění tlačítka
  • R18 slouží pro potřeby časovače
  • R19 identifikuje čekací interval 5s nebo 2s
		.include "m88def.inc"

[editovat] Vektory přerušení pro ATmega88

		.org 0x0000 
		rjmp start              ; po resetu se zacina od navesti start
		.org 0x0004 
		rjmp stlacena_klavesa   ; obsluha preruseni pri zmene stavu pinu (PCINT)
		.org 0x0009
		rjmp casovac            ; obsluha pri preteceni casovace 2
                .org 0x0006
	        rjmp otacka             ; vektor preruseni pro citac otacek
                .org 0x001A 
	        rjmp TIM1_OVF           ; vektor preruseni pro sekundovy casovac

[editovat] Nastavení vrcholu zásobníku

Vrchol zásobníku je umístěný na konec paměti RAM, která je určena konstantou RAMEND, definovanou v souboru m88def.inc, konstanta je 16-bitová, a registry ukazatele zásobníku 8-bitové (SPL - stack pointer low, SPH - stack pointer high), proto se konstanta nahrává ve dvou cyklech

	
       start:        
		ldi R16,high(RAMEND) ; do registru R16 se ulozi vyssi bajt konstanty RAMEND
		out SPH,R16          ; nacitany bajt se prekopiruje do SPH  
		ldi r16,low(RAMEND)  ; do registru R16 se ulozi nizsi bajt konstanty RAMEND
		out SPL,R16          ; nacitany bajt z R16 se zkopiruje do SPL

Do registrů v I/O prostoru (kam patri i SPL, SPH) nejde zapisovat přímo přes instrukci LDI, ale jen přes instrukci OUT.

Poznámka: Out SPH, high(RAMEND) by nefungovalo, musí se použít nějaký pomocný registr, v našem případě R16

[editovat] Inicializace připojené klávesnice

Soubor:IC-matrix keyb.png

Na černém konektoru do kontaktního pole, od kterého vede barevný plochý kabel dolů, jsou sloupce a řádky klávesnice připojeny takto:

COL1 COL3 ROW1 ROW3
COL2 COL4 ROW2 ROW4

Vývody ATmega168, ke kterým by tato klávesnice šla připojit:

PC5 PC4 PC3 PC2 ... ... ...
)
RESET PD0 PD1 PD2 PD3 ... ... ...


Porty PC2, PC3, PC4 jsou vstupy na které jsou připojené vývody klávesnice COL1, COL2, COL3

	
		cbi DDRC,2 ; COL1
		cbi DDRC,3 ; COL2
		cbi DDRC,4 ; COL3


		; na portech PC2, PC3, PC4 jsou aktivni pull-up rezistory
		sbi PORTC,2 
		sbi PORTC,3
		sbi PORTC,4

		; porty PD0, PD1, PD2, PD3 jsou vystupy na ktere jsou pripojene
		; vyvody klavesnice ROW1 az ROW4
		sbi DDRD,0 ; ROW1
		sbi DDRD,1 ; ROW2
		sbi DDRD,2 ; ROW3
		sbi DDRD,3 ; ROW4
	
		; na portech PD0, PD1, PD2, PD3 se nastavi log.0
		cbi PORTD,0	; 
		cbi PORTD,1
		cbi PORTD,2
		cbi PORTD,3

[editovat] Nastavení přerušení

Stlačení klávesnice

To znamená při změně stavu pinu PC2, PC3, PC4


Při nastavování tohoto typu přerušení se zápis do konfiguračních registrů PCICR a PCMSK1 musí vykonat jako zápis do paměti PCICR - Pin Change Interrupt Control Regist. Je třeba nastavit první bit který zapíná kontrolu změny stavu pinu PCINT14 az PCINT8 PCIMSK1 - Pin Change Mask Register

  • nastavením příslušného bitu do 1 se vybere, na kterém z pinů PCINT14 az PCINT8 se ma detekovat změna
  • nás zajímá 2., 3. a 4. bit tohoto registru
  • nastavením těchto bitů se aktivuje přerušení při změně stavu na PCINT10 (PC2), PCINT11 (PC3), PCINT12 (PC4)

Zápis do paměti se vykonává přes instrukci ST (store) ukazatel X je 16-bitový, jeho dolní byte tvoří registr R26 a horní byte registr R27

		ldi R26,PCICR 		; PCICR tvori nizsi cast adresy X
		clr R27		  		; vyssi cast adresy X je nulova
		ldi R16,0b00000010 	; do R16 dame co se ma ulozit na adresu X, tj. aktivovani PCINT1
		st X, R16 			; ulozeni hodnoty R16 na adresu X

		; podobny princip jako v predeslem pripade, jen zapisujeme do registru PCMSK1
		ldi r26,PCMSK1 		; PCMSK1 tvori nizsi cast adresy
		clr r27 			; vyssi cast adresy je nulova
		ldi r16,0b00011100  ; povoleni preruseni pri zmene stavu pinu PC2,PC3,PC4
		st X, r16 			; zapisani hodnoty registru PCMSK1 (resp. na jeho adresu)

		sei 				; (Set Interrupt) - globalni povoleni preruseni
							; instrukce nastavi bit I v registru SREG
							; timto bitem se daji povolit/zakazat vsechny preruseni

[editovat] Nastavení generátoru PWM

Časovač 0 nastavený jako generátor PWM signálu tento časovač má dva nezavislé PWM:

  • PWM A s výstupem na OC0A (PD6) - slouží na ovládání LED s dosvitem (po puštění tlačítka svítí 5s a potom postupně zhasíná 2s
  • PWM B s výstupem na OC0B (PD5) - slouží na ovládání LED, jejíž jas je regulovaný klavesnicí

PWM generátor ma vypnuté přerusení (v našem případě není potřeba)

Soubor:TCCR0A.jpg


Soubor:TCCR0B.jpg

		ldi R16,0b11110011  ; COM0A1:0 = 3 invertujuci rezim PWM0A, datasheet str.101
							; COM0B1:0 = 3 invertujuci rezim PWM0B, datasheet str.102
							; WGM01:0 = 3 rychly PWM mod. datasheet str.103
		out TCCR0A,R16      ; zapsaní hodnot do registru TCCR0A, datasheet str. 100
		
		ldi R16,0b00000001  ; CS22:0 = 1 zdroj hodin bez delicky. datasheet str. 104
		out TCCR0B,R16      ; popis registru, datasheet 103

		ldi R16,0x7F        ; hodnota v OCR0B reguluje jas LED-ky pripojene na PD5
		                    ; (OC0B). 0 = nulovy jas, 0xFF maximalni jas
				    ; hned po zapnuti se nastavi polovicni jas (0x7F)
		out OCR0B,R16
		
		ldi R16,0           ; LED s dosvitem je zhasnuta 
		out OCR0A,R16
		
		ldi R17,0           ; v R17 je info o tom zda je ovladaci tlacitko (*) stlacene 
				    ; 0 ne, 1 ano
		
		sbi DDRD,5          ; PD5 (OC0B) je vystupni pin
		sbi DDRD,6          ; PD6 (OC0A) je vystupni pin

[editovat] Měření otáček ventilátoru pomocí TACHO

Pro tyto účely využijeme časovače 1 z datasheetu. Ten způsobí přerušení vzniklé z přetečení za 1 sekundu. Během této doby budeme sledovat změny na pinu PB0. Je třeba podotknout, že ventilátor za jednu otáčku 2x sepne a rozepne tranzistor. Takže odtud máme 4 změny pinu za otáčku. Jestliže chceme počítat otáčky za sekundu, je potřeba daný počet změn pinu podělit 4.

 
        cbi DDRB, 0
        sbi PORTB,0           ; nastaveni PB0 jako vstup s pull-up rezitorem

        ldi R16,0x00 
        out TCCR1A,R16

        ldi R16,0b01000011    ; nastaveni delicky /64 a reagovani na vzestupnou hranu
        out TCCR1B,R16

        ;ldi R16,0b00000001   ; povoleni preruseni pretecenim TMR1--->TIMSK2 se neda adresovat primo přes IN/OUT 
        ;out TIMSK1,R16       ; instrukce, proto se to dela nasledovne.....

	
        push R16              ; zalohovani R16 na zasobnik
        ldi R16,0b00000001    ; zapnuti preruseni pri preteceni casovace. povoleni preruseni pretecenim TMR1 
        ldi R28,TIMSK1
        clr R29
        st Y,R16              ; 16 bitový registr X používámě ,,dole´´, takže zde jsme se rozhodli použít 16 bitový 
                              ; registr Y, který má registry 28 a 29 
        pop R16               ; obnoveni R16 ze zasobniku

	
        ldi R17, 0x00
        ldi R16,0xC2F6        ; pri delicce 1:64 pretece TMR1 za 1 sekundu
        out TCNT1H,R17
        out TCNT1L,R16        ; FFFF-C2F6=3D09 => 15625*0.000064=1
	
        ldi R16,0b00000001    ; preruseni pri zmene pinu PCINT 0-7
        out PCICR,R16

        ldi R16,0b00000001    ; my jsme si z pinu PCINT 0-7 vybrali konkretne PB0, touto maskou zvolime reakci
        out PCMSK0,R16        ; pouze na PB0

; navesti pro jednotlive odskoky z vektoru preruseni

otacka:                       ; preruseni od PCINT0
        cli                   ; zakazani vsech preruseni
        inc R10;              ; pri kazdem preruseni se nam zvysi hodnota v R10 o 1 (zmena na pinu PB0)
        sei                   ; povoleni vsech preruseni
        reti 	              ; navrat z preruseni

TIM1_OVF:                     ; preruseni od 1 sec TCNT1
        cli                   ; zakazani vsech preruseni
        ldi R11, R10          ; nacteni R10 do R11
        ldi R10, 0x00         ; vynulovani R10 pro dalsi citani zmen na pinu PB0
        LSR R11               ; protoze se behem jedne otacky dojde ke 4 zmenam na pinu, je nutne
        LSR R11               ; hodnotu v R11 podelit 4, toho docilime tak, ze provedeme posun o 2 bity doprava 
                              ; takto ziskame v R11 primo pocet otacek za sekundu        
        ldi R17, 0x00         ; opetovne nastaveni sekundoveho citace
        ldi R16,0xC2F6        
        out TCNT1H,R17
        out TCNT1L,R16

        ldi R14, 0b00000110   ; nastaveni R14 jako 1/8 maxima otacek
        ldi R12, 0b10000000   ; nastaveneni prvniho bitu pro rozsveceni diod

        rjmp DIODY

[editovat] Zobrazeni otáček pomocí diod

Reálné otáčky ventilátoru zobrazujeme pomocí 8 diod. Ty nám zobrazují jednotlivé osminy maximálních otáček větráku. Maximální hodnotu otáček jsme určili s pomocí osciloskopu, kde jsme odečetli periodu změn na pinu PB0. 1/8 maximálních otáček je tak pro nás registr R14. Při každém odečtení otáček se od naměřené hodnoty odečte R14. Jestliže je výsledek větší než 0, jsou reálné otáčky větší než R14, proto proces odečítání provádíme tak dlouho, dokud není výsledek menší než 0. V tom případě ze smyčky vyskočíme. Pro indikaci otáček na diodách použijeme 8 bitový registr R12. Načteme do něj hodnotu 0b10000000. Při každé operaci, jejíž výsledek je větší než 0, dojde k posunu 1 o jeden bit doprava. Přítomnost 1 na daném bitu způsobí rozsvícení patřičné diody a ta nám tedy bude signalizovat otáčky.


DIODY:

cp R11,R14          ; porovnani R11 a R14
brlo X              ; skoc na X, pokud je R11<R14
                    ; provede se pokud Rd11>R14, tedy pri nesplneni brlo
rjmp Y              ; skok na Y, aby se preskocila cast, ktera probehne pri splneni BRLO

X:   

;1/8

sbrc R15,7          ; preskoci se, pokud je na 7-mem bitu R15 0
sbi DDRC,5          ; PC5 se nastavi jako vystup
sbi PORTC,5         ; na PC5 privedem log. 1

;2/8

sbrc R15,6          ; preskoci se, pokud je na 6-mem bitu R15 0
sbi DDRC,1          ; PC1 se nastavi jako vystup
sbi PORTC,1         ; na PC1 privedem log. 1

;3/8

sbrc R15,5        
sbi DDRC,0         
sbi PORTC,0 

;4/8

sbrc R15,4        
sbi DDRB,5         
sbi PORTB,5      

;5/8

sbrc R15,3       
sbi DDRB,4         
sbi PORTB,4 

;6/8

sbrc R15,2       
sbi DDRB,3        
sbi PORTB,3  

;7/8

sbrc R15,1       
sbi DDRB,1        
sbi PORTB,1

;8/8

sbrc R15,0       
sbi DDRD,7       
sbi PORTD,7

sei                 ; globalni povoleni preruseni
reti                ; navrat z preruseni

Y:

sub R11,R14         ; odecteme od merenych otacek jednu 1/8 ( 1x podelime )
ldi R13,R12         ; nacteme R12 do R13
lsr R12             ; posuneme cely registr o jeden bit doprava
or R12,R13          ; do registru R12 nacitame zleva postupne jednotlive bity tak, jak budou svitit diody

rjmp DIODY          ; cyklus pro zjisteni namerenych otacek ku maximu

[editovat] Nastavení časovače 2

Tento časovač slouží na odpočítávání času 5s a 2s.

  • do registru tohto časovače se přistupuje jako do paměti
  • je použita předdělička /256
  • při TCNT2 = 0 je krok časovače 1^10-6*256*256 = 65,54 ms - s touto periodou se bude volat přerušení, jakmile bude aktivované
		clr R16               ; nastaveni registru TCCR2A, same nuly
		ldi R26,TCCR2A
		clr R27
		st X,R16

		ldi R16,0b00000110    ; nastaveni TCCR2B, zapojeni preddelicky /256
		ldi R26,TCCR2B
		st X,R16

		clr R16               ; nastaveni konstanty pro 65,54 ms							  
		ldi R26,TCNT2         
		clr R27
		st X,R16

[editovat] Nastavení úsporného režimu

V idle mode je uspaný jen procesor, periferie běží. Procesor se vzbudí z přerušení od časovače nebo po stisku tlačítka

		ldi r16,0b00000001 ; Idle mode
		out SMCR,r16  

[editovat] Zacyklení programu

Program bude reagovat jen na přerušení

loop:
		sleep 		    ; uspani procesoru
		rjmp loop           ; nekonecna smycka

[editovat] Obsluha přerušení

obsluha přerušení PCINT0 při změně stavu pinu PC2,PC3 nebo PC4. Na tyto piny jsou připojené sloupce 1 az 3 (COL1 az 3), postupně se bude zjišťovat, která klávesa byla stlačená. Při stlačení kláves 0 az 9 se postupně ukládá číslo do registru R16. Na konci obsluhy přerušení se R16 zapíše do registru OC2A (ovládání PWM 2). Velikost zapsaného čísla je úměrná svitu LEDky, která se ovládá klávesnicí. Regulace jasu je ovládána hodnotou 0..255. Možnosti regulace na klávesnici jsou 1 az 9 (0 - LED je vypnuta). Krok regulace je 255/9 (cca 28)

[editovat] Stlačená klávesa

stlacena_klavesa:
		push r16		; ulozeni hodnoty r16 do zasobniku

		; nacitani konstanty ktera ovlada PWM 2
		; pro pripad aby se neztratila aktualni hodnota kdyz se pusti
		; stlacena klavesa

		in R16,OCR0B  
		
		;-------------------------------------------------------
		; aktivovani (do log. 0) 4. radku klavesnice (* 0 # D)
		; detekce stlaceni klavesy 0
key0:
		sbi PORTD,0
		sbi PORTD,1
		sbi PORTD,2
		cbi PORTD,3		
		sbic PINC,3     ; jakmile je stlacena 0, preskoci se nasledujici instrukce a 
			        ; nepokracuje se dal ve zjistovani stlacene klavesy
		rjmp key_star   ; pokracuje se testovanim dalsi klavesy
		ldi R16,0	; byla stlacena 0, do R16 se ulozi hodnota 0 (LED nesviti)
		rjmp keyret     ; skoc na konec obsluhy preruseni

		; detekce stlaceni klavesy *
key_star:
		sbic PINC,2
		rjmp key1
	
		push R16	; zaloha R16 na zasobnik
		ldi R16,0xFF    ; rozsviceni LEDky s dosvitem
		out OCR0A,R16
		ldi R17,1       ; ovladaci tlacitko * je stlacene
		pop R16         ; obnoveni R16 ze zasobnika

		rjmp keyret
		
		;-------------------------------------------------------
		; aktivovani 1. radku klavesnice (1 2 3 A)
		; detekce stlaceni klavesy 1
key1:
		cbi PORTD,0	
		sbi PORTD,1	
		sbi PORTD,2
		sbi PORTD,3
		sbic PINC,2
		rjmp key2
		ldi R16,28
		rjmp keyret

		; detekce stlaceni klavesy 2
key2:	
                sbic PINC,3
		rjmp key3
		ldi R16,56
		rjmp keyret

		; detekce stlaceni klavesy 3
key3:
		sbic PINC,4
		rjmp key4
		ldi R16,84
		rjmp keyret

		;-------------------------------------------------------
		; aktivovani 2. radku klavesnice (4 5 6 B)
		; detekce stlaceni klavesy 4
key4:
		sbi PORTD,0
		cbi PORTD,1	
		sbi PORTD,2
		sbi PORTD,3	
		sbi PINC,2
		rjmp key5
		ldi R16,112	
		rjmp keyret

		; detekce stlaceni klavesy 5
key5:
		sbic PINC,3
		rjmp key6
		ldi R16,140
		rjmp keyret

		; detekce stlaceni klavesy 6
key6:
		sbic PINC,4
		rjmp key7
		ldi R16,168
		rjmp keyret

		;-------------------------------------------------------
		; aktivovani 3. radku klavesnice (7 8 9 C)
		; detekce stlaceni klavesy 7
key7:
		sbi PORTD,0
		sbi PORTD,1
		cbi PORTD,2	
		sbi PORTD,3	
		sbic PINC,2
		rjmp key8
		ldi R16,196
		rjmp keyret

		; detekce stlaceni klavesy 8
key8:
		sbic PINC,3
		rjmp key9
		ldi R16,224
		rjmp keyret

		; detekce stlaceni klavesy 9
key9:
		sbic PINC,4
		rjmp keyret
		ldi R16,255

keyret:
		; zjisteni zda bylo pustene tlacitko *

		cbi PORTD,0	
		cbi PORTD,1
		cbi PORTD,2
		sbi PORTD,3           ; aktivovani radku (* 0 # D)
		sbis PINC,2           ; jakmile je tlacitko * pustene, preskoci se nasledujici instrukce
                rjmp keyret1          ; tlacitko je stale stlacene
                cpi R17,1             ; tlacitko * je prave pustene, bylo nekdy stlacene?
		brne keyret1          ; jakmile neni pokracuje se na navesti s ukoncenim obsluhy preruseni
		
		; spusteni casovace na postupne zhasinani

		clr R17               ; tlacitko je uz pustene
		
		push R16              ; zalohovani R16 na zasobnik
		ldi R16,0b00000001    ; zapnuti preruseni pri preteceni casovace 2
		ldi R26,TIMSK2
		clr R27
		st X,R16
		pop R16               ; obnoveni R16 ze zasobnika

		ldi R18,76            ; konstanta pro cas 5s (76*65,54ms)
		ldi R19,0             ; R19 = 0 - pocita se cas 5s (LED sviti)
		                      ; R19 = 1 - pocita se cas 2s (LED zhasina)

keyret1:
		; vsechny radky do log.0

		cbi PORTD,0	
		cbi PORTD,1
		cbi PORTD,2
		cbi PORTD,3

		out OCR0B,R16         ; aktualizace jasu LEDky ovladani klavesnici	

		pop r16               ; obnoveni puvodni hodnoty r16 ze zasobnika 
		reti 		      ; navrat z preruseni

[editovat] Obsluha časovače 2

casovac:
		cpi R19,0       ; jakmile se pocita cas 5 sekund, LED sviti
		breq sviceni
		
		in R16,OCR0A    ; jakmile se pocita cas 2s, LED pomalu zhasina
		subi R16,8      ; vypocet konstanty: 255/31 je cca 8
		out OCR0A,R16   ; 31 je pocet nasobku 65.64 ms, aby byl cas 2 sekundy

sviceni:
		cpi R18,1       ; cekani - zadany pocet nasobku 65,54 ms
		brne casovac1
		
		; prenastaveni casovace na jemnejsi krok 
		cpi R19,1       ; zjisteni, zda uz ubehl interval 2s
		breq vypni_casovac  ; jakmile ano, casovac se vypne
		ldi R18,31      ; 31*65,54ms je cca 2 sekundy
		ldi R19,1       ; pocita se 2s interval, LED bude zhasinat
		reti
		
vypni_casovac:
		; vypnuti casovace (vyvolani preruseni od casovace)
		clr R16    
		ldi R26,TIMSK2
		clr R27
		st X,R16		

		; uplne zhasnuti LEDky
		clr R16
		out OCR0A,R16

casovac1:
		dec R18
		reti

[editovat] Fotodokumentace

Soubor:komplet2.jpg Soubor:Mensi.JPG

[editovat] Závěr

V této práci jsme si vyzkoušeli zapojení ventilátoru, jehož otáčky jsou řízeny klávesnicí. Dále jsme zjišťovali pomocí zpětnovazebního signálu TACHO skutečné otáčky ventilátoru, které jsme dále zobrazovali na 8 diodách. Diody reprezentují otáčky v procentech poměr aktuálních otáček ku maximálním otáčkám. Důležitým krokem bylo určení maximálních možných otáček větráku pomocí osciloskopu. Veškerý postup jsme detailně komentovali, konkrétní detaily, proč a co jsme jak řešili jsou k nalezení u příslušné kapitoly u konkrétního kódu. Veškeré naše teoretické předpoklady se nám podařilo úspěšně splnit a zařízení fungovalo dle očekávání. V této úloze je zahrnuto i dohasínání osvětlení auta z 1.domácího úkolu. Snažili jsme se o to, aby byly vidět souvislosti v řešení zadaných problémů nám a i jiným studentům. Studentovi může posloužit naše práce i jako užitečný nástroj pro pochopení zákonitostí práce v assembleru.

Dalším možným vylepšením by bylo možno zobrazovat otáčky ventilátoru na LCD displayi, ale k tomu bychom doporučovali zvolit programování v C, neboť v Assembleru by to bylo zbytečně složité a zdlouhavé při hledání případných chyb.

Osobní nástroje