Sida 2 av 3

Re: Läsa värde med ADC på AVR? (asm)

Postat: 15 december 2009, 23:25:29
av Glattnos
Okej, jag har testat det nu, men resultatet är att alla dioder lyser hela tiden, oavsett om jag har potentiometern inkopplad eller inte. När jag mäter spänningen på mittenpinnen på potentiometern och vrider så ändras den mellan 0 och 5 Volt, så då vet man ju att det i alla fall finns en reglerbar spänning in på ADC5-pinnen.
Måste någon mer hårdvara vara inkopplad, tex motstånd, drossel eller kondensator? Eller ska det fungera med enbart GND, VCC och reglerbar spänning på ADC5?

Det här förstår jag inte riktigt:
"Voltage Reference Selections for ADC" i ADMUX?
"AREF, Internal Vref turned off" eller "AVCC with external capacitor at AREF pin"

Ska jag koppla potentiometern på VCC och GND eller ska AREF och AVCC vara med någonstans?

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 09:31:32
av snigelen
Det ser ut som om du fortfarande bara gör en omvandling. Du måste starta om omvandlingen (t.ex. i slutet av avbrotts-rutinen) eller köra free-running-mode som hatten sade ovan.

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 10:06:08
av Glattnos
Jasså, räcker det inte att sätta ADEN-biten(AD-enable)? Eller gör jag nått galet där när jag lägger ADCSRA i temp, kör en sbr och sedan lägger tillbaka värdet i ADCSRA? Kanske finns bättre sätt att sätta ADEN-biten?

Avbrottsrutinen ser ju ut såhär:

Kod: Markera allt

Ultra: INTERRUPT               ;Börja avbrottsrutinen med MACRO INTERRUPT 
   lds      adc_data, ADCL         ;Lagra värdet från ADCL i adc_data
   lds      temp, ADCSRA         ;Ladda temp med ADCSRA...
   sbr      temp, (1<<ADEN)         ;..och sätt ADENable biten
   sts      ADCSRA, temp         ;Lägg tillbaka värdet i ADCSRA
INTERRUPT_END                  ;Avsluta avbrottsrutinen med MACRO INTERRUPT_END

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 10:13:10
av Glattnos
Aha! Nu ser jag en sak. Det är ju ADSC som jag ska sätta i avbrottsrutinen. Jag ska testa det efter jobbet.

Såhär:

Kod: Markera allt

Ultra: INTERRUPT               ;Börja avbrottsrutinen med MACRO INTERRUPT 
   lds      adc_data, ADCL         ;Lagra värdet från ADCL i adc_data
   lds      temp, ADCSRA         ;Ladda temp med ADCSRA...
   sbr      temp, (1<<ADSC)         ;..och sätt ADSC biten
   sts      ADCSRA, temp         ;Lägg tillbaka värdet i ADCSRA
INTERRUPT_END                  ;Avsluta avbrottsrutinen med MACRO INTERRUPT_END

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 10:22:54
av snigelen
Ok. Nu har jag testat ditt program. Jag gjorde några ändringar för att det skulle fungera.

Kod: Markera allt

   ;ADC - AREF(Internal Vref turned off), Left adjusted, ADC5
   ldi      temp, (0<<REFS1)+(0<<REFS0)+(0<<ADLAR)+0b101   
I kommentaren står Left adjusted men du sätter inte den biten. Sedan har du sagt att du skall ha AREF som referens. Har du referensspänning på den pinnen? Annars kan du använda AVCC i stället:

Kod: Markera allt

   ldi      temp, (0<<REFS1)+(1<<REFS0)+(1<<ADLAR)+0b101   
I huvudloopen behöver du inte ha med sei, det räcker att köra den en gång innan loopen.
Om du sedan vill ha vänsterjusterat resultat så är det nog ADCH du vill läsa i avbrottsrutinen samt, som du själv kom på när jag skrev detta, att du skall sätta ADSC i stället för ADEN:

Kod: Markera allt

   lds      adc_data, ADCH         ;Lagra värdet från ADCH i adc_data
   lds      temp, ADCSRA         ;Ladda temp med ADCSRA...
   sbr      temp, (1<<ADSC)         ;..och sätt ADSCable biten
   sts      ADCSRA, temp         ;Lägg tillbaka värdet i ADCSRA

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 11:20:54
av Glattnos
Tusen tack! Det låter rätt. Nu börjar jag förstå varför det inte har fungerat.

Det är nog igentligen själva komentaren "Left adjusted" som är fel eftersom jag tänkte läsa de åtta lägsta bitarna i ADC-värdet och då ska ju ADLAR inte sättas och sedan läser man ADCL. Men man kan ju även sätta ADLAR och läsa ADCH istället, för då får man väll de åtta högsta bitarna i ADC-värdet.
Jag ska testa detta senare och återkommer med hur det gick.

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 11:45:09
av jesse
Men om du hade tänkt läsa bara de 8 lägsta bitarna så hade det blivit fel - då hade du fått ett värde från 0-255 som börjar om från noll 4 gånger när du ändrar inspänningen från 0 till 5 volt... Läser du de 8 högsta bitarna blir det rätt - dvs du får ett 8-bitars värde som motsvarar spänningen : Värde = 256*Uin/5

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 14:04:45
av Glattnos
jesse: Okej, jag tror jag förstår hur du menar. Jag kan inte använda de 8 lägsta bitarna till något vettigt när det gäller avståndsmätningen med sensorn.
Men kan man använda de 8 högsta bitarna eller måste man använda alla 10? Jag antar att det har med nogrannheten att göra och själva beräknadet för att få fram avståndet i meter.

Min tanke är att när jag fått detta att fungera så ska jag fortsätta med att skriva ut avståndet i meter på en LCD-display. I nuläget har jag ingen aning om hur man skriver ut 10-bits binärtal på LCD i decimalform men det blir en senare fråga.

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 14:18:08
av hatten
Du kan vänsterjustera och läsa ADCH för 8-bitarsprecision, precis som du var inne på i ett tidigare inlägg.

"If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion."

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 16:35:40
av sodjan
> Jag kan inte använda de 8 lägsta bitarna till något vettigt

Tja, det beror ju helt på vad du menar med "något vettigt"... :-)

Antag att du har ett 1 m måttband...

Att bara läsa de 8 *lägsta* bitarna motsvarar att bara läsa av cm-skalan
(i 0-9 cm) men inte veta om det är 5, 15, 25... cm totalt. D.v.s ditt
"mätvärde" kommer att räkna 0-9 och starta från 0 10 gånger under tiden.
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9... o.s.v

Mycket ovanligt att man faktiskt vill göra på det sättet...

Att bara läsa de *högsta* 8 bitarna motsvarar att bara läsa av i hela dm
men inte veta hur många cm det är därimellan. D.v.s du mäter bara
0,0,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,10,10,20,20... o.s.v...

Detta är mycket vanligt när man inte behöver full upplösning.

Att läsa alla 10 bitarna motsvarar att läsa av i cm över hela skalan (0-100) cm.
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24... o.s.v

Så gör man när man både behöver hela skalan och full upplösning...

Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 18:54:16
av Glattnos
Yes! Nu fungerar det! Tack för all hjälp!

Här är hela den fungerande koden:

Kod: Markera allt

.NOLIST
.INCLUDE	"m168def.inc"
.LIST
;===============================================================================================
;	Avståndsmätare - TEST av ADC
;
;	Programmet läser av en ultraljudssensor via ADC och visar värdet från ADCH på 
;	8 st lysdioder som sitter på PortD
;
;	CPU:		Atmel Atmega168 (Int. Oscilator 8 MHz)
;	Plattform:	AVR Dragon
;
;	Ver 1.0 [2009-12-16/glattnos@hotmail.com]
;===============================================================================================

.DEF	temp			= r16		;Temporärt register
.DEF	adc_data		= r17		;Data för digitalt ADC-värde

;-----------------------------------------------------------------------------------------------
;	Macron
;-----------------------------------------------------------------------------------------------
.MACRO INTERRUPT		;Macro i början av en avbrottsrutin 
 	push temp			;Lägg temp(1) på stacken
	in temp,SREG		;
	push temp			;Lägg SREG(2) på stacken
.ENDMACRO				;Slut macro

.MACRO INTERRUPT_END	;Macro i slutet av en avbrottsrutin
	pop temp			;Hämta SREG(2) från stacken
	out SREG,temp		;
	pop temp			;Hämta temp(1) från stacken
	reti				;Returnerar från avbrottet
.ENDMACRO				;Slut macro

;===============================================================================================
;	AVBROTTS-VEKTORER
;===============================================================================================
.CSEG							;Följande placeras i PM
.ORG 0000						;Avbrottsvektor för Reset
	rjmp Reset

.ORG ADCCaddr					;Avbrottsvecktor för ADC
	rjmp Ultra

;-----------------------------------------------------------------------------------------------
;	Reset	-	Initieringskod för att förbereda systemet
;-----------------------------------------------------------------------------------------------
.ORG 0x0100						;Startadress i PM för Reset
Reset:
	ldi		temp, LOW(RAMEND)	;Initiera stackpekare
	out		SPL, temp			;
	ldi		temp, HIGH(RAMEND)	;
	out		SPH, temp			;

	ldi		temp, 0xff			;Sätt PortD som utport
	out		DDRD, temp			;

;-----------------------------------------------------------------------------------------------
;	ADC		-	Initiering
;-----------------------------------------------------------------------------------------------

	;ADC - AREF(Internal Vref turned off), Left adjusted, ADC5
	ldi		temp, (0<<REFS1)+(1<<REFS0)+(1<<ADLAR)+(0<<MUX3)+(1<<MUX2)+(0<<MUX1)+(1<<MUX0)	
	sts		ADMUX, temp 

	;ADC - ADENable, ADStartConversation, ADInterruptEnable
	;ADPrescalerSelectBits 110 = System clock/64 to ADC
	ldi		temp, (1<<ADEN)+(1<<ADSC)+(1<<ADIE)+0b110	 
	sts		ADCSRA, temp

	sei		;Sätt I-biten i SREG för att tilllåta avbrott

;========================================================================
;	Main	-	Huvudloop
;========================================================================
Main:
	mov		temp, adc_data			;Sätt värdet från ADC:n...
	out		PORTD, temp				;...till PortD

	rjmp	Main					;Börja om på Main

;===============================================================================================
;	AVBROTTSRUTIN	-	Avbrottsrutinen Ultra läser av UL-sensorn och sparar värdet
;===============================================================================================
Ultra: INTERRUPT					;Börja avbrottsrutinen med MACRO INTERRUPT 
	lds		adc_data, ADCH			;Lagra värdet från ADCH i adc_data
	lds		temp, ADCSRA			;Ladda temp med ADCSRA...
	sbr		temp, (1<<ADSC)			;..och sätt ADStartConvertion-biten
	sts		ADCSRA, temp			;Lägg tillbaka värdet i ADCSRA
INTERRUPT_END						;Avsluta avbrottsrutinen med MACRO INTERRUPT_END


Re: Läsa värde med ADC på AVR? (asm)

Postat: 16 december 2009, 21:04:33
av jesse
Grattis!

Men om du ska fortsätta med det här så rekommenderar jag verkligen att du läser lite om binära talsystem, och hur man räknar med dessa. T.ex. en gymnasiebok i digitalteknik. Den går igenom det mesta du behöver veta för att sedan lära dig processorns funktioner, och att förstå hur den räknar. Biblioteket har t.ex "Digitalteknik från A till Ö" eller motsvarande...

Re: Läsa värde med ADC på AVR? (asm)

Postat: 17 december 2009, 08:21:09
av Glattnos
jesse: Okej, ja jag har väll tänkt att jag ska läsa någon bok om just digitalteknik, nu har jag bara böcker specifikt om AVR-prosessorer, "Microprosessorteknik" av Per Foyer och "Embedded C Programming and the Atmel processor".
Per Foyers bok har jag läst från pärm till pärm men den andra boken är på engelska vilket jag inte är så bra på så den har jag läst ungefär halva. Jag tycker att assembler är lättare att förstå än C så därför håller jag mig till assembler nu i början.

Men jag kan ju lika gärna fortsätta denna tråd.

Nu har jag ju fått ADC:n att fungera, och får ett 8-bitarsvärde. Nu vill jag skriva ut ett värde decimalt på min LCD. Till LCD:n kan man skicka ASCII-tecken på 8 bitar. Om jag till att börja med vill skriva ut talet från ADC:n decimalt, hur kan jag göra då?

Jag tänker såhär:
Talet från ADC:n är 1 byte som kan innehålla 0-255 binärt
Talet som ska visas på LCD:n är ju mellan 0-255 decimalt, så då behövs 3 st siffror.
Man använder 3 byte i SRAM för att lagra dessa 3 siffror i ASCII-format.
Så skickar man dessa tre byte i tur och ordning till LCD.

Frågor:
1. Är detta en bra metod eller finns det något enklare sätt?
2. Hur räknar man om det binära talet till tre ASCII-tecken(i assembler)?

Re: Läsa värde med ADC på AVR? (asm)

Postat: 17 december 2009, 10:48:16
av sodjan
Det finns så många beskrivningar över binär -> BCD omvandling så det
är fullständigt onödigt att försöka göra ytterligare en. Det finns flera
gamla tråder här i forumet. Sök eller Googla...

Re: Läsa värde med ADC på AVR? (asm)

Postat: 17 december 2009, 11:15:36
av Glattnos
sodjan: Okej, jag har sökt och inte hittat något bra men det var ju inte så konstigt. Ja har sökt på "binär decimal" men när jag söker på "binär BCD" så fanns det ju massor :)

Men jag ställde en fråga till: 1. Är detta en bra metod eller finns det något enklare sätt?
Eftersom jag kom på metoden själv(jag har alltså inte läst det någonstans)så känns det som att det kanske finns något bättre sätt som jag inte tänkt på.