-
        
+ Antworten
Seite 1 von 4 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 40

Thema: Auswertung/Funktionsweise des A/D Wandlers

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.03.2004
    Ort
    Bremen
    Alter
    26
    Beiträge
    308

    Auswertung/Funktionsweise des A/D Wandlers

    Hi!
    ich möchte den A/D Wandler meines Mega16 benutzen.
    Kann mir jemand vielleicht die Auswertung des A/D Wandlers erklären
    Nach meinen Informationen unterteilt er die Referenzspannung in 256 Teile, stimmt das?
    Man fragt doch den Wandler mit ADc ab oder(unter Bascom)?
    Muss ich sonst noch etwas beachten?
    Wie schließe ich dann ein Poti/LDR an den A/D Wandler?
    MFG
    Rasmus

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.01.2004
    Alter
    32
    Beiträge
    255
    Hallo!
    Es dürfte sich bei dem AD Wandler um einen 10bit ADC handelt, dh. er unterteilt den Spannungsbereich zwischen ARef und AGND in 1024 Teile. Liegt dein ARef jetzt bei 5V hast du damit eine Auflösung 4,88 mV.
    Allerdings ist die Größe von ARef auch begrenzt (sie darf imho nicht mehr als 0,2 V über AVCC und nicht unter einem bestimmten Wert liegen -> also im Datasheet nachschauen).

    Wie man die ADC Werte in Bascom abfragt weiß ich nicht - da ich nicht mit Bascom arbeite. Der AD Wandler muss auf jeden Fall zuerst initialisiert werden. Anschließend kann man den Wert mit einer einfachen Funktion auslesen.

    Wenn du auf die Genauigkeit der Werte wert legst, solltest du die Tipps im Datenblatt berücksichtigen (beim Anschluss von AVCC z.B. die Induktivität mit rein).

    Um einen änderbaren Widerstand anzuschließen benötigst du einen Spannungsteiler. Dazu nimmst du einen Festwiderstand bekannter Größe und hängst diesen an VCC und mit der anderen Seite an den Pin des LDR. Der LDR dann noch gegen GND und zwischen LDR und Widerstand deinen AD Port. Evtl. kannst du da dann noch nen Schutzwiderstand in Reihe reinbauen (aber nicht unbedingt notwendig). Hier ist aber vorsicht geboten, da beim Spannungsteiler keine linearen Werte rauskommen. D.h. du musst das ganze Software mäßig linearisieren.
    Einfacher ist das beim Poti. Da schließt du das eine Ende an VCC, das andere an GND. Dann kommt der Schleifer an den AD Port.

    Bei beiden Fällen kannst du nun Aref auf AVCC legen. Wichítig ist, dass keine Spannungen an den AD Port kommen, die über Aref liegen.

    Viele Grüße
    Flite

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    01.11.2003
    Ort
    Freiburg im Breisgau
    Alter
    28
    Beiträge
    2.624
    Hi Flite!
    Das Thema interessiert mich auch!
    Ich bin bisher noch nicht dazu gekommen die AD-W. auszuprobieren!
    Programmierst Du in Assembler?
    Wenn ja, könntest Du mir dann vielleicht, wenn es möglich wäre, einen mit Kommentaren versehenen einfachen Code posten?
    Oder könntest Du mir einen Code basteln, wo der AD-W. abgefragt wird und die 10 Bit an Ausgängen ausgegeben werden?
    Wenn möglich auch Kommentiert?
    Wäre nett, aber wenn nicht, ist es auch in Ordnung!
    Ich weiß selber, wie viel man zu tun hat!

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.03.2004
    Ort
    Bremen
    Alter
    26
    Beiträge
    308
    Hi!
    Also wäre bei einer Referrenzspannung von 5V, eine Einheit 0.0048828(Ref : 1024)groß, oder?
    LDR:

    Vcc----R---LDR---GND
    ............|
    ..........Port
    weiß jemand wie man das ganze dann mit Bascom abfragt?(irgendwie mit "ADc", bin mir aber nicht ganz sicher)
    Danke schonmal
    MFG
    Rasmus

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.01.2004
    Alter
    32
    Beiträge
    255
    Hallo!
    Ja - eine Einheit des ADC wären dann 4,88mV (=0,00488 V).

    der Port muss zwischen R und LDR (aber ich denke, das hast du so gemacht - nur das Forum hat die Leerzeichen eingespart).

    ADC in Bascom:

    Config Adc = Single , Prescaler = Auto
    Start Adc
    Dim W As Word, Channel As Byte

    Channel = 0 ' Pin Nummer von 0 - 7
    W = Getadc(Channel)

    Übrigens: ich hab nur bei Google 'bascom adc einlesen' eingegeben und den zweiten Link genommen.

    Grüße
    Flite

    Grüße
    Flite

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.03.2004
    Ort
    Bremen
    Alter
    26
    Beiträge
    308
    Danke!
    Ich habe schon verschiedene Möglichkeiten gesehen(gefunden bei Google), aber ich war mir nicht sicher, welches die "Richtige" ist.
    MFG
    Rasmus

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    01.11.2003
    Ort
    Freiburg im Breisgau
    Alter
    28
    Beiträge
    2.624
    Hi!
    Hat jemand sowas auch für Assembler?

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.01.2004
    Alter
    32
    Beiträge
    255
    Hier gibts auch einen für Assembler. Ist für den Mega32, sollte sich jedoch problemlos umschreiben lassen:

    Code:
    ;**********************************************
    ;*
    ;* 10 bits A/D converter demo
    ;*
    ;**********************************************
    
    .include "C:\VMLAB\include\m32def.inc"
    
    ;  Registers definitions
    ;
    .def temp = r16
    ; my Def
    ;**********************************************
    ;.equ    ADTS2    =7
    ;.equ    ADTS1    =6
    ;.equ    ADTS0    =5
    ;**********************************************
    ;  Reset and interrupt vectors
    ;
    .cseg
    ;*********************************************************************
    .org $00               ; 1 $000 Reset Go to Reset handler
    	rjmp start
    .org $02
    	rjmp dummy
    .org $04
    	rjmp dummy
    .org $06
    	rjmp dummy
    .org $08
    	rjmp dummy
    .org $10
    	rjmp dummy
    .org $12
    	rjmp dummy
    .org $14
    	rjmp dummy
    .org $16
    	rjmp dummy
    .org $18
    	rjmp dummy
    .org $20
    	rjmp ad_vector	 ; ADC complete
    .org $22
    	rjmp dummy
    .org $24
    	rjmp dummy
    .org $26
    	rjmp dummy
    .org $28
    	rjmp dummy
    
    
    ;	rjmp ad_vector   	; ADC
    ;***********************************************
    dummy:
    	nop
    	nop
    	nop
    	nop
    	reti
    ;***********************************************
    ;***********************************************
    ; ADC complete interrupt service
    ;
    ad_vector:
    
       in temp, ADCH
      	sbi	ADCSR,ADSC	; StartConversion
    sei
      ret
    
    ;***********************************************
    ;  Reset handler
    ;
    start:
    	
    	clr	temp		; first clear all registers
       out 	ACSR,temp
    	out 	ADMUX,temp
    	out 	ADCSR,temp
    	out	SFIOR,temp
    	
    	ldi 	temp,high(RAMEND)
    	out   sph,temp
    	ldi	temp,low(RAMEND)
    	out	spl,temp
    	
       ; ldi temp, $AB    ; Power on ADC; select prescaler (/8); free running
       ; out ADCSR,temp   ; and enable end of conversion interrupt
    
    
    	sbi	ADCSR,ADEN	; ADC-Enable
    	sbi	ADCSR,ADIE	; ADC-EnableEnable Interrupt
    	sbi	ADCSR,ADPS2	; SET Prescale to //
    	cbi	ADCSR,ADPS1	; 		Divisions Factor //
    	cbi	ADCSR,ADPS0	; 		by 16
    
    	sbi	ACSR,ACIE	; ACIE: Analog Comparator Interrupt Enable
    	sbi	ACSR,ACIS1	; ACIS1, ACIS0: Analog Comparator //
    	sbi 	ACSR,ACIS0	;   Interrupt Mode Select //
    
    	sbi ADMUX, ADLAR ; Get 8 most significant bits in ADCL	
    	
    	nop
       nop
       nop              ; Leave some time to stabilize before starting
       nop
    
       sbi	ADCSR,ADSC	; StartConversion
    
       sei              ; A warning must be issued here!!. 8 is not enough
                        ; as prescaler factor to obtain a 50-200 KHz
                        ; recommended ADC clock
    
    forever:
       rjmp  forever  ; Infinite loop, interrupted by ADC conversions
    Ich hab den Code jedoch nicht ausprobiert - beim groben überfliegen sieht es jedoch recht gut aus ...

    Grüße
    Flite

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    01.11.2003
    Ort
    Freiburg im Breisgau
    Alter
    28
    Beiträge
    2.624
    Hi Flite!
    Danke für den Code!
    Ich habe ihn jetzt 3 mal durchgelesen!
    Leider habe ich nicht verstanden, was der Code überhaupt machen soll!
    Was gibt er aus, oder bearbeitet er?

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.01.2004
    Alter
    32
    Beiträge
    255
    Hallo Florian,

    ich versuch mal das meiste zu erklären ...

    Code:
    .include "C:\VMLAB\include\m32def.inc" 
    .def temp = r16 
    .org $00               ; 1 $000 Reset Go to Reset handler 
       rjmp start 
    .org $02 
       rjmp dummy 
    .org $04 
       rjmp dummy 
    .org $06 
       rjmp dummy 
    .org $08 
       rjmp dummy 
    .org $10 
       rjmp dummy 
    .org $12 
       rjmp dummy 
    .org $14 
       rjmp dummy 
    .org $16 
       rjmp dummy 
    .org $18 
       rjmp dummy 
    .org $20 
       rjmp ad_vector    ; ADC complete 
    .org $22 
       rjmp dummy 
    .org $24 
       rjmp dummy 
    .org $26 
       rjmp dummy 
    .org $28 
       rjmp dummy
    Die Interrupt Vektor Table. Je nach ausgeführtem Interrupt springt er hier zu den entsprechenden Unterfunktionen.

    Code:
    dummy: 
       nop 
       nop 
       nop 
       nop 
       reti
    Wenn ein nicht gewünschter Interrupt ausgeführt wird (also einer, der nichts mit dem ADC zu tun hat und nicht der Reset ist) springt er in diese Funktion. Die verplemtern nur Rechenzeit und sollte überflüssig sein.

    Code:
    ad_vector: 
    
       in temp, ADCH 
         sbi   ADCSR,ADSC   ; StartConversion 
    sei 
      ret
    Die Funktion wird über die Interrupt Table aufgerufen, sobal ein Wert gewandelt wurde.

    in temp, ADCH liest has High Byte der ADC Wertes ein. Eigentlich müsste man hier noch eine zweite Variable einlesen, in der der Wert ADCL (das Low Byte) eingelesen wird. Fehlt hier völlig (warum, siehe weiter unten).

    Anschließend werden hier die Interrupts allgemein angeschaltet (da sie niergends abgeschaltet werden, sollte das eigentlich überflüssig sein).

    Code:
      ldi    temp,high(RAMEND) 
       out   sph,temp 
       ldi   temp,low(RAMEND) 
       out   spl,temp
    Initialisierung des Stack
    Das löschen der Register sollte überflüssig sein.

    Code:
       sbi   ADCSR,ADEN   ; ADC-Enable 
       sbi   ADCSR,ADIE   ; ADC-EnableEnable Interrupt 
       sbi   ADCSR,ADPS2   ; SET Prescale to // 
       cbi   ADCSR,ADPS1   ;       Divisions Factor // 
       cbi   ADCSR,ADPS0   ;       by 16
    Hier wird der ADC angeschaltet, der Interrupt (sobald eine Wandlung fertig ist) angeschaltet, und der Prescaler auf 16 gesetzt.

    Beim ADMUX Register sind folgende Werte wichtig:
    Die beiden MSB (REFS0/1) sind auf 0 zu setzen um mit ARef als Referenz zu arbeiten.
    ADLAR (wird im Bsp. gesetzt) dient dazu, das Ergebnis nicht rechtsbündig (also 8 Bit im unteren Byte und 2 Bit im High byte), sondern linksbündig (also 8 bit im high byte und 2 bis im low byte) auszugeben.
    D.h. da oben nur das High Byte ausgelesen wurde, und linksbündig aktiviert ist, werden hier im Beispiel nur 8 bit genutzt (anstatt 10 möglichen).

    Die restlichen 5 bit im ADMUX Registen (MUX 4- 0) dienen dazu, einzustellen, welcher der ADC pins eingelesen werden soll. Da alle 5 Bits auf 0 sind wird der ADC0 eingelesen.

    Code:
       sbi ADMUX, ADLAR ; Get 8 most significant bits in ADCL
    linksbündig wird aktiviert.

    Code:
       sbi   ACSR,ACIE   ; ACIE: Analog Comparator Interrupt Enable 
       sbi   ACSR,ACIS1   ; ACIS1, ACIS0: Analog Comparator // 
       sbi    ACSR,ACIS0   ;   Interrupt Mode Select //
    Hier wird wohl etwas für den Analog Comparator eingestellt. Diese Passage verstehe ich auch nicht und würde sie einfach löschen.

    Dann kommen ein paar nop's - benötigt er wohl zur Stabilisierung (würde ich je nach verwendeter Taktfrequenz evtl. noch ein wenig länger machen).

    Code:
      sbi   ADCSR,ADSC   ; StartConversion
    Hier wird das erste Mal eine Wandlung gestartet. Zukünftige Wandlungen werden automatisch nach einer vollendeten Wandlung gestartet (im Interrupt).

    Mit sei werden die Interrupts alle aktiviert.

    Danach folgt nur noch eine Endlosschleife, die nach jeder vollendeten Wandlung per Interrupt unterbrochen wird.


    Das macht das Programm:
    Das Programm wandelt die am ADC0 liegende Spannung bezogen auf AREF in einen digitalen 8 bit Wert um, der in der Schleife immer aktuell in der Variable Temp steht. Dieser muss nur ausgelesen werden und beispielsweise über das UART oder ein LCD angezeigt werden.

    Falls du noch Fragen hast melde dich!

    Ich hoffe dir geholfen zu haben (allerdings gebe ich keine Garantie über die geschribenen Dinge, da ich nebenher Fußball schaue und ich noch nie etwas mit dem ATMega32 gemacht habe).

    Viele Grüße
    Flite

+ Antworten
Seite 1 von 4 123 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Ja
  • Themen beantworten: Ja
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •