PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit adc



Gleiti84
01.07.2008, 22:03
Hallo,
Ich bin neuling und versuche ein paar tests auf dem ATMega 16.
Ich benutzte das board von Pollin.
Nun zu meinem Problem:
Mein AVcc ist an Vcc, GND an GND und mein ARef an Vcc oder an Masse mit einem Kondensator 100nF. Egal wie ich es mache und auch die passenden Bits setzte ich bekomme kein ergebnis. kann mir jemande helfen.

PS. Als routine benuzte ich die vom Wiki.

gruss markus

linux_80
01.07.2008, 22:30
Hallo,

wir wissen ja nicht welche Kombination Du ausprobiert hast,
wenn man aussen Vcc anlegt bei AREF, sollte man das auch auf ext. Reference konfigurieren.
Wenn man nur den Kondensator dran hat, muss man eine interne, oder AVCC als Referenz wählen.
Den Kondensator sollte man allerdings immer dran haben, egal wo die Spannung zu AREF herkommt.

Das gemessene Signal sollte dann auch zum AREF passen, bzw. eig. andersrum. Wenn man bis 5V Messen will, braucht man AVCC, damit man den ganzen Bereich vom ADC ausnutzen kann.
Ist die gemessene Spannung max. 2,5V, reicht die interne Referenz.

Grandalf
02.07.2008, 08:45
hi


also ich benutze ein zweites Netzteil mit dem ich 0V-2,5V anlegen kann und das is wie folgt angeschlossen

erste Stromquelle nur an VCC und GND um das board zu versorgen
zweite stromquelle am +pol mit dem gewünschten ADCpin verbunden (in meinem fall PA1) und am -pol mit GND verbunden
dann noch einen Kondensator von AREF zu GND (wobei es auch ohne den kondensator geht)

alles andere ist konfigurationssache des programms

mein programm:

ADC.c


#include <avr/io.h>
#include <avr/iom16.h>
#include <inttypes.h>
#include "ADC.h"


uint16_t ReadChannel(uint8_t mux)
{
uint8_t i;
uint16_t result;
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); // Frequenzvorteiler
// setzen auf 8 (1) und ADC aktivieren (1)
ADMUX = mux; // Kanal waehlen
ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen

/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) )
{
; // auf Abschluss der Konvertierung warten
}
result = ADCW; // ADCW muss einmal gelesen werden,
// sonst wird Ergebnis der nächsten Wandlung
// nicht übernommen.

/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
result = 0;
for( i=0; i<4; i++ )
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) )
{
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
result /= 4; // Summe durch vier teilen = arithm. Mittelwert
return result;
}


main.c


#include <avr/io.h>
#include <avr/iom16.h>
#include <inttypes.h>
#include "ADC.h"
#define F_CPU 4000000UL
#include <util/delay.h>

int main (void)
{
DDRA = 0;
DDRD = 1;
_delay_ms(500);
PORTD = 0xff;
_delay_ms(500);
PORTD = 0x00;
_delay_ms(500);
uint16_t adcval = 0x00;
while(1)
{
adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0 */
PORTD = adcval;
_delay_ms(250);
}
return 0;
}


ADC.h


uint16_t ReadChannel(uint8_t mux);


ich benutze übrigens auch den ATmega 16 und das pollin board (allerdings zusammen mit dem addonboard)


mfg Grandalf

Gleiti84
02.07.2008, 18:14
Also bei dem beispiel habe ich den ARef Pin über einen 100nF Kondensator auf masse gelegt.
Da ich 8 MHz benutze habe ich einen Prescalrer von 64 genommen.

ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2); // Frequenzvorteiler

ADMUX |= (1<<REFS0); // AVCC als Referenzspannung nutzen

Dann mache ich einen dummy readout

anschliessend messe ich viermal eine und bilde einen mittelwert.

wenn ich dann adc0 auf masse bzw. vcc lege ändert sich der wert nicht.

mfg Markus

fhs
02.07.2008, 18:38
Hallo Markus,


....ARef Pin über einen 100nF Kondensator auf masse gelegt.
das ist i.O., da Du AVcc als Referenz nimmst.


Da ich 8 MHz benutze habe ich einen Prescalrer von 64 genommen.
A/D-Wandlerfrequenz also 125 kHz -- auch i.O.!


Dann mache ich einen dummy readout
anschliessend messe ich viermal eine und bilde einen mittelwert.
Zeige uns doch mal Deinen Code dazu (am besten nicht abschreiben, sondern direkt in Dein Posting kopieren -- ganz, mit Initialisierung, so dass alles kompilierbar ist!).

Gruß

Fred

Gleiti84
02.07.2008, 19:09
uint16_t ReadChannel(uint8_t mux)
{
uint8_t i;
uint16_t result;

ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2); // Frequenzvorteiler

// setzen auf 8 (1) und ADC aktivieren (1)
ADMUX = mux; // Kanal waehlen
ADMUX |= (1<<REFS0); // AVCC als Referenzspannung nutzen
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */

ADCSRA |= (1<<ADSC); // eine ADC-Wandlung

while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result = ADCW; // ADCW muss einmal gelesen werden,
// sonst wird Ergebnis der nächsten Wandlung
// nicht übernommen.

/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
result = 0;

for( i=0; i<4; i++ )
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)

result /= 4; // Summe durch vier teilen = arithm. Mittelwert

return result;
}


und aufrufen tue ich alles über x = ReadChannel(0);

fhs
02.07.2008, 20:56
Hallo,

in dem von Dir geposteten Code kann ich keinen Fehler entdecken. Bist Du sicher, dass ADC0/PA0 als Eingang programmiert ist?


..mein ARef an Vcc oder an Masse mit einem Kondensator 100nF
Du hast Aref nie direkt mit Massse verbunden, oder?


Gruß

Fred

Gleiti84
02.07.2008, 21:27
nein nur über einen kondensator

ich habe eigentlich den pin als eingang geschrieben

fhs
02.07.2008, 22:06
Jallo,

Dein Pollin Board kenne ich nicht -- da ist PA0 ansonsten unbeschaltet? Kannst Du uns auch noch Deine Port-Initialisierung zeigen?

Gruß

Fred

Grandalf
03.07.2008, 07:12
Zitat von Gleiti84


Also bei dem beispiel habe ich den ARef Pin über einen 100nF Kondensator auf masse gelegt.
Da ich 8 MHz benutze habe ich einen Prescalrer von 64 genommen.

ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2); // Frequenzvorteiler

ADMUX |= (1<<REFS0); // AVCC als Referenzspannung nutzen

Dann mache ich einen dummy readout

anschliessend messe ich viermal eine und bilde einen mittelwert.

wenn ich dann adc0 auf masse bzw. vcc lege ändert sich der wert nicht.

mfg Markus


meinst du mit "bei dem Beispiel" meinen geposteten code?
da ich es hier alles vor mir liegen habe muss das funktionieren es funktioniert ja auch bei mir.

um halt bei mir was zu sehen musst du an PORTD 8 LEDs anschließen um den gemessenen wert binär angezeigt zu bekommen (wobei nicht wundern wenn zwischen 0V und 2,55V der ADC mehr als 1x bis 255 zählt)
du kannst aber natürlich das ganze für ne LCD anzeige umbauen oder wie du möchtest aber die ADC funktion müsste funktionieren.

hast du das ausprobiert?

mfg Grandalf

Gleiti84
03.07.2008, 19:38
Also, es hat sich erledigt, fehler von mir. 8-[
ich hatte versucht den 10bit wert in 8bit umzurechnen und dann über uart zu senden. dabei ist mir der fehler passiert, die berechnung hatte nicht gepasst. nun funktioniert alles.

Nochmals danke für eure bemühungen.

CU Markus