Räkna Frekvens med ATtiny15

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Räkna Frekvens med ATtiny15

Inlägg av Nisse »

Första gången jag försöker mig på att skriva maskinkod till denna processor. Faktum är att senast jag skrev maskinkod till en uC var 11 år sedan och till en Z80 :lol:

Vad jag försöker uppnå är att tända en lysdiod ansluten till PB0 när frekvensen in på PB2 överstiger ca 5000 Hz och släcka den om frekvensen går ned.

Jag har simulerat programmet i AVRStudio och det verkar fungera som tänkt, men kommentarer och hjälp är mycket välkommet.
Kanske är det onödigt komplicerat att använda interupt eller något annat som jag totalt missat.....

Kod: Markera allt

.include "tn15def.inc" 

.def Counter = r17
.def Temp = r16

 
.org 0x0000 
rjmp Reset

//--- Interrupt Vector ------------------------------------------------- 

.org 0x0002
rjmp ExtInt

.org 0x0005
rjmp TimerInt

Reset: 

//--- Init -------------------------------------------------------------- 

   ldi    Counter, 0x00			; Nollställ räknaren
   ldi 	Temp, 0b00111011		; Sätt PB2 som ingåmg
   out	DDRB, Temp
   sbi	PORTB, 0				; Sätt PB0 till 1
   ldi    Temp,    0b00000011    ; Sätt att trigga på Stigande flank
   out    MCUCR,    Temp
   ldi    Temp,    0b01000000    ; Aktiverar extern interupt INT0
   out    GIMSK,    Temp

//-- Sätter timer och overflow till att ge interupt ca 24,4 gånger/sec vid CK 1,6 MHz
//-- 1600000/256/256 = 24,4
   
   ldi Temp, 0b00000100			; Sätt Timer0 prescaler till CK/256
   out TCCR0, Temp
   ldi Temp, 0x00				; Nollställ timer
   out TCNT0, Temp
   ldi Temp, 0b00000010					; Aktivera interupt på timer0 overflow
   out TIMSK, Temp
   sei


Loop:
	rjmp Loop

ExtInt:
	inc Counter
	reti

TimerInt:
	ldi Temp, 0xCD  ; 5000 Hz delat på 24,4 ger ca 205
	cp Counter, Temp
	brsh Light
	sbi PORTB, 0    ; Släck lysdiod
	ldi Counter, 0x00 ; Nollställ räknare
	reti

Light:
	cbi PORTB, 0    ;Tänd lysdiod
	ldi Counter, 0x00 ; Nollställ räknare
	reti
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Jag tycker att det ser bra ut, och det funkar ju.. det är ju huvudsaken! =D En möjlig förbättring för att göra koden mer lättläst kan ju vara att använda bit-namn (PB0 | PB1 osv..) istället för att skriva "0b00111011".
Däremot kommer du att få problem om motorn kilar förbi 6240rpm, för då slår "Counter" runt och lampan slocknar igen...
Maximal svarstid är för din kod 40ms, vilket skulle kunna minskas kanske?! Kör timern dubbelt så fort, halvera 0xCD till 66 (skriv med basen tio där det ändå inte ger någonting att ha det i hex, kompilatorn fixar ju maskinkod av det!) så klarar du upp till 12500rpm (vilket är ok om du inte har en extrem bålgeting till hoj!) :D
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Utveckla gärna hur du menar med att använda bitnamn. Som sagt, det var 11 år sedan jag skrev maskinkod senast :?

Problemet med att "Counter" slår runt vid strax över 6000 varv är jag medveten om. Programmet är just nu bara i exprimentstadiet och förmodligen kommer jag få ändra lite åt det hållet du skrev. Det finns även tankar på att koppla till en LCD eller 7-segment för att visa varvtalet. Men det kommer senare (jösses då måste jag fixa bitbang).

Mvh
Nils
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Jag skriver sällan asm, håller mig mest till C, så jag ska inte svära att det funkar i din kompilator, men vad det handlar om är egentligen "defines".
Så istället för att skriva 0b00000101 så skriver man först
.def PB0 0b00000001
.def PB2 0b00000100
och sedan kan man använda den logiska operatorn "eller" för att lägga ihop värden, ex:
PORTB = (PB2 | PB0), vilket asm också borde funka:
ldi Temp, (PB2 | PB0)
out DDRB, Temp

Ok, bra att du tänkt på overflow... Ett annan sak att ha i åtanke... en 7-seg eller LCD är inte speciellt snabb.. då varvtalet förändras snabbt kommer den bara att se ut att flimra... Fundera istället på en lång stapet a'la VU-meter, forma den som en cirkel, numrera och du har en "vanlig" varvräknare! =)

EDIT: Det är möjligt att bitnamnen finns definierade in nån fil som du kan inkludera... så är det i allfall i de flesta C-kompilatorer... någon annan vet nog det bättre än mig när det gäller asm
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Upptäckte att trots att koden fungerar så får jag lite felmedelanden. Hjälp :?
AVR Simulator: HW stack overflow at 0x0005
AVR Simulator: Invalid opcode 0xffff at address 0x000001
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Idag får jag inte de meddelandena längre :?:

Någon som kan svara på vad det var för meddelanden :?:

Mvh
Nils
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Om du verkligen inte gjort någon skillnad i programmet så var det ju märkligt att det försvann?!
Trots att tiny15 inte har något SRAM så har den ändå en tre nivåers hårdvarustack... kanske är det avsaknaden av initieringen av den som gör att det krånglar?!
Prova att lägga in följande som de första två raderna i Init:

Kod: Markera allt

ldi temp, RAMEND ; Temp=r16
out SPL, temp ; set stack pointer
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

I koden har jag inte ändrat något, bara stökat om lite bland kommentarerna och formateringen för att göra det mer lättläst.

Provade trots att jag inte har några problem nu att lägga in de två raderna du föreslog.
Resultat: " error: Undefined symbol: SPL" :(

Mvh
Nils
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Hmm.. näe, du har så rätt så... den ska inte behöva initieras... jag råkade se ett exempel på nätet som också gjort fel! ;)
Någonstans läste jag dock att SPL är definierad för ICE?! Kan det vara något i simuleringen som kräver initiering av stackpekaen kanske?! nåja...
Hittade föresten ett bra appnote om bitnamn:
http://www.atmel.com/dyn/resources/prod ... OC0931.PDF
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Hittade en detalj som skulle kunna ställa till det.
Hade missat att sätta bit 7 Global Interupt enable i SREG.
Dessutom använde jag fel interuptadress, 0x0002 istället för 0x0001
Vet dock inte varför det funkade ändå?
Nåväl nu ser det ännu bättre ut och funkar lika bra :lol:

Finns det för övrigt någon metod att sätta eller nolla enskilda bitar i de olika statusregistren (typ GIMSK o SREG)? (ungefär som cbi/sbi och sbr/cbr)


Kod: Markera allt

.include "tn15def.inc" 

.def Counter = r17	;Räknaren i register 17
.def Temp = r16		;Register 16 används till lite av varje

 
.org 0x0000 
rjmp Reset

//--- Interrupt Vector ------------------------------------------------- 

.org INT0addr
rjmp ExtInt			;Extern Interupt INT0

.org OVF0addr
rjmp TimerInt		;Intern Interupt Timer 0 overflow

Reset: 

//--- Init -------------------------------------------------------------- 

	ldi    	Counter,	0x00		; Nollställ räknaren
   	ldi 	Temp,		0b00111011	; Sätt PB2 som ingåmg och övriga som utgångar
   	out		DDRB,		Temp
   	sbi		PORTB,		PORTB0			; Sätt PB0 till 1
   	ldi    	Temp,		0b00000011  ; Sätt att trigga på Stigande flank
   	out    	MCUCR,		Temp
   	ldi    	Temp,		0b01000000  ; Aktiverar extern interupt INT0
   	out    	GIMSK,		Temp
	ldi		Temp,		0b10000000	; Global interupt enable
	out		SREG,		Temp

//-- Sätter timer och overflow till att ge interupt ca 24,4 gånger/sec vid CK 1,6 MHz
//-- 1600000/256/256 = 24,4
   
   	ldi 	Temp, 		0b00000100	; Sätt Timer0 prescaler till CK/256
   	out 	TCCR0, 		Temp
	ldi 	Temp,		0			; Nollställ timer
	out 	TCNT0,		Temp
	ldi 	Temp,		0b00000010	; Aktivera interupt på timer0 overflow
	out 	TIMSK,		Temp
	sei


Loop:
	rjmp 	Loop

//-- Extern interupt PB2 -----------------------

ExtInt:
	inc 	Counter					; Öka räknaren
	reti

//-- Intern Interupt ---------------------------

TimerInt:
	ldi 	Temp, 		205  		; 5000 Hz delat på 24,4 ger ca 205
	cp 		Counter, 	Temp
	brsh 	Light					; Om räknaren över 205 hoppa
	sbi 	PORTB, 		0    		; Släck lysdiod
	ldi 	Counter, 	0 			; Nollställ räknare
	reti

Light:
	cbi 	PORTB, 		PORTB0		; Tänd lysdiod
	ldi 	Counter, 	0 			; Nollställ räknare
	reti
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

oJsan skrev:Däremot kommer du att få problem om motorn kilar förbi 6240rpm, för då slår "Counter" runt och lampan slocknar igen...
Hoppsan, eller kanske ojsan... Här har både du och jag gjort en tankevurpa. 6240 rpm är bara 104 hz. Och de 5000 Hz jag har svammlat om borde borde bara vara 83 Hz :lol:
Bara att räkna om och justera programmet lite med andra ord....

mvh
Nils
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Haha, ja just ja.. det är rpm och inte rps! =D
Felplacerat anrop i avbrottsvektorn var nog anledning till ditt tidigare fel..
(Att skriva en etta till MSB i SREG är precis samma sak som instruktionen sei, varav den senare är lättare att skriva och använda!)
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

Efter att ha läst på lite mer om instruktionen sei så kan jag bara konstatera att så är det ju faktiskt.... Dooh!

// Nils
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Hmm... våran Saab 900 S har ingen varvräknare (S betyder förövrigt SNIK!), så det skulle vara skoj att montera en, så jag tar gärna del av din pickup-kontruktion om du får den att funka?! Fast jag kan ju å andra sidan kanske koppla min mig "direkt" också? Borde kanske skaffa mig Haynes-boken med elschema.. nej ucsh vad jobbigt allt blev... :cry:
:D

Edit: Upptäckte att jag svamlat i fel tråd, men jag antar att denna frekvensräknare ska användas i Nisses MC-shiftlight (~varvräknare), vars tråd finns på annat ställe i forumet!
Användarvisningsbild
Nisse
Inlägg: 908
Blev medlem: 9 juli 2006, 23:25:46
Ort: Kumla

Inlägg av Nisse »

I Saaben är det enklaste du kan göra att koppla in dig på tändspolens minus-anslutning. Den är normalt jordad och två gånger per motorvarv (4 cyl) så släpps den fri.

De två ämnena kommer strax bli förenade i projektdelen. Hade ju igentligen inte tänk att dra igång såhär fort, men nu har jag köpt på mig prylarna...

Mvh
Tobbe
Skriv svar