PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ADC und ATmega 8



Sippo
09.06.2009, 19:19
folgendes Problem:
ich weiß, dass mein Problem eigentlich recht einfach sein sollte aber ich komm grad irgendwie kein schritt weiter und habe gehofft ihr könntet mir vll helfen. Und zwar habe ich mich nun am ADC probiert aber bin irgendwie an etwas gescheitert...
liegts vll an den registern?

Folgende Pinbelegung:
gesamter PORTD LED's
VREF 100n gegen masse
und ADC 0 - 5 hängen in der luft aund wahlweise an einem POti (mitte)
die anderen beiden Pins des Potis gehen auf masse und VCC

habe folgende Codes getestet:

#include <avr/io.h>

#include <util/delay.h>




int main()
{
int sample,i,value;
DDRD=0xFF; // PORTD als Ausgabeport
ADMUX=(0<<REFS1)|(1<<REFS0); // ADC Ref auf Avcc, PC0 gew?hlt
ADCSR=(1<<ADEN)|(0<<ADPS0)|(1<<ADPS1)|(1<<ADPS2); // ADC eingeschaltet, 64 Bit Prescale
while(1)
{
sample=0;
for(i=0;i<64;i++)
{
ADCSRA|=0b10000000; //single conversion mode ein
while(ADCSRA & (1<<ADSC)); //warten bis konvertierung abgeschlosen
sample+=ADCW; //aufsummierung der samplewerte
}
value=sample/64; //aritmethisches mittel der samplewerte
if (value<300)
PORTD=0b10000000; //schaltet LED ein
else if (value>=300 && value<600)
PORTD=0b11000000; //schaltet LED ein
else
PORTD=0b11100000; //schaltet LED ein
}
}


#include <avr/io.h> // Include Datei f?r den ATMega8
#include <util/delay.h> // Include Datei f?r die Verz?gerungsfunktion

void long_delay(uint16_t ms)
{
for(; ms>0; ms--) _delay_ms(1);
}

int main()
{
int sample,i,value; // Variablen definitionn
DDRD=0xFF; // PORTB als Ausgabeport
ADMUX=0x00; // ADC Ref auf Avcc, PC0 gew?hlt, normale Formatierung
ADCSRA=0x80; // ADC eingeschaltet, kein Prescale
// Endlosschleife zur kontinuierlichen Auswertung der Eingangsspannung (am ADC)
while(1)
{
sample=0; // setzt den Samplewert auf 0
// Schleife zum Sammeln von 32 Me?werten
for(i=0;i<32;i++)
{
ADCSRA.6=1; // single conversion mode ein
while(ADCSRA.6); // warten bis konvertierung abgeschlosen
sample+=ADCW; // aufsummierung der samplewerte
}
value=sample/32; // Aritmethisches Mittel der Samplewerte
// Auswertung der Me?daten
if (value<300) // erste Grenze
PORTD=0x04; // schaltet gr?ne LED ein
else if (value>=300 && value<600) // zweite Grenze
PORTD=0x02; // schaltet gelbe LED ein
else
{
PORTD=0x01; // schaltet rote LED ein
long_delay(250); // verz?gerung von 250ms
PORTD=0x00; // schaltet LED aus
long_delay(250); // verz?gerung von 250ms
}
}
return 1;
} :-s

linux_80
09.06.2009, 20:29
Hallo,

Was geht denn nicht ?

Evtl. liegts am int für sample, denn das ist mit vorzeichen, also mal unsigned int probieren !

yaro
09.06.2009, 21:32
Du hast vergessen, den ADC zu aktiviren: ADCSRA |= (1<<ADSC);
das hier: ADCSRA|=0b10000000; mach lediglich den ADC an, lässt ihn aber kine conversion starten.

p.s. seit wann geht denn 0b....? bei mir zeigt er das immer als Fehler an.

Gruß, Yaro

Sippo
10.06.2009, 15:32
habe den Code nun folgendermaßen abgeänfdert aber noch kein resultat???


#include <avr/io.h>

#include <util/delay.h>



int main()
{
unsigned int sample,i,value;
DDRD=0xFF; // PORTD als Ausgabeport
ADMUX=(0<<REFS1)|(1<<REFS0); // ADC Ref auf Avcc, PC0 gew?hlt
ADCSR=(1<<ADEN)|(0<<ADPS0)|(1<<ADPS1)|(1<<ADPS2); // ADC eingeschaltet, 64 Bit Prescale
while(1)
{
sample=0;
for(i=0;i<64;i++)
{
ADCSRA |= (1<<ADSC);
ADCSRA |=0b10000000; //single conversion mode ein
while(ADCSRA & (1<<ADSC)); //warten bis konvertierung abgeschlosen
sample+=ADCW; //aufsummierung der samplewerte
}
value=sample/64; //aritmethisches mittel der samplewerte
if (value<300)
PORTD=0b10000000; //schaltet LED ein
else if (value>=300 && value<600)
PORTD=0b11000000; //schaltet LED ein
else
PORTD=0b11100000; //schaltet LED ein
}
}

Ceos
10.06.2009, 15:50
wenn du uns jetzt sagst, dass das compilen nicht ging, hättest du schon längst hilfe bekommen ;)


kopieren alleine hilft da nichts, n bisschen mitdenken ist schon wichtig!

zum einen ist deine initialisierung nicht richtig!

das register heisst ADCSRA und nciht ADCSR (schau mal ins datenblatt), zum anderen hast du in der initialisierung ADEN schon gesetzt, mit deinem 0b10000000 bewirkst du eigentlich kaum mehr als einen verschwendeten rechentakt, das ADSC bit hast du an der stelle richtig gesetzt und das warten auf das beende der berechnung stimmt auch ... nur wird mich nicht klar was das ADCW register sein soll, ist das neu ? normal heisst das ADCH und ADCL und wenn du es als 16bit wert lesen willst einfach nur ADC (schau mal ins datenblatt)

Sippo
10.06.2009, 16:27
beim kompilieren kommt lediglich ein warning

aber mit den änderungen nu geht noch weniger und zwar haben vorher mehrere leds geleuchtet und immer wieder wenn ich den Draht berührt hab geblinkt oder auch mal eine abgeschalten oder so aber nu tut nur noch 1 dauerleuchten.

Thomas$
10.06.2009, 18:00
ähm adc ist doch analog digital wandler zum einlesen der eingänge nicht zur ausgabe und lieg ich grad völlig daneben und hab das hier grad falsch verstanden

Ceos
10.06.2009, 18:23
wahrschienlich, er gibt den messwert am port D aus über 3 LEDs und liesst am port c am pin 0 ein ... hast du das poti mal sauber von links nach rechts durchgedreht ? ohne veränderung ? .. ich bin fast verlock den code bei mir mal auszuproibieren, wenn ich mein steckbrett nur noich auf arbeit liegen hätte :p

EDIT: gepriesen sei der löschbutton, nie wieder peinliche doppelposts

hier mein nachtrag

okay ich hab grad NOCH was entdeckt, du darfst nur REFS0 setzen nicht refs0 und refs1, das wären 2.56V interne referenz!!!

dein prescaler steht auf 128 nich 64 (ich sag nur datenblatt oder eventuell die kommentare korrigieren ^^)

wenn cih mich nicht verrechnet habe, machst du 75 oder 9 messungen pro sekunde mit allem drum und dran je nachdem ob 8 oder 1 MHz prozessortakt

lass mal das mit dem mittelwert weg und gib die werte lieber direkt aus.

das warning hätt ich aber auch gern mal gesehen wenns geht

achso wie sieht der code denn JETZT überhaupt aus ? ^^ hat vorteile wenn man die änderungen immer mitpostet sonst muss man immer rästeln was vielleicht beim editieren falsch gelaufen iss

Sippo
10.06.2009, 21:04
also das Poti hab ich richtig gedreht aber wenn die ref 2,xx ist kann ich ja auch maximal das eingeben , oder?

den code habe ich außerdem kopiert und überarbeitet werde morgen noch mal den aktuellen posten (grad am falscvhen PC) vll findet ja jemand noch was oder vll is au jemand so langweolig den code so weit abzuändern^^

Sippo
11.06.2009, 15:27
also das ist der neue Code:


#include <avr/io.h>
#include <util/delay.h>

int main()
{
unsigned int sample,value;
DDRD=0xFF; // PORTD als Ausgabeport
ADMUX=(0<<REFS1)|(1<<REFS0); // ADC Ref auf Avcc, PC0 gew?hlt
ADCSR=(1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2); // ADC eingeschaltet, 128 Bit Prescale
while(1)
{
sample=0;
ADCSRA|=(1<<ADSC); //ADC aktivieren
while(ADCSRA & (1<<ADSC)); //warten bis konvertierung abgeschlosen
value = ADCW; //aufsummierung der samplewerte

if (value<300)
PORTD=0b10000000; //schaltet LED ein
else if (value>=300 && value<600)
PORTD=0b11000000; //schaltet LED ein
else
PORTD=0b11100000; //schaltet LED ein
}
}

folgende änderungen:

mache nun nur noch 1 messung
der prescaler steht nun bei 128 (habe 16MHz an XTAL1 + 2)


werde nun meine Platine mit display löten um die Messwerte mal ausgeben zu können.

Hubert.G
11.06.2009, 17:25
Die Simulation sagt das es OK ist.
Was meinst du mit (habe 16MHz an XTAL1 + 2)

Sippo
11.06.2009, 17:29
mit diesem code funktioniert es nun:


#include <avr/io.h>

int main(void)
{
DDRD = 0xFF;
while (1)
{
uint8_t i;
uint16_t result;
int i2 = 60;
ADMUX = (0<<REFS1)|(1<<REFS0); // Kanal waehlen
ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen


ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
// setzen auf 8 (1) und ADC aktivieren (1)

/* 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<i2; 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 /= i2; // Summe durch vier teilen = arithm. Mittelwert
if (result < 128)
{
PORTD = 0b10000000;
}
else if (result >= 128 && result < 256)
{
PORTD = 0b01000000;
}
else if (result >= 256 && result < 384)
{
PORTD = 0b00100000;
}
else if (result >= 384 && result < 512)
{
PORTD = 0b00010000;
}
else if (result >= 512 && result < 640)
{
PORTD = 0b00001000;
}
else if (result >= 640 && result < 768)
{
PORTD = 0b00000100;
}
else if (result >= 768 && result < 896)
{
PORTD = 0b00000010;
}
else
{
PORTD = 0b00000001;
}
}
return 1;
}

mit den 16 MHz hab ich meinen Quarz gemeint^^

Tytus
12.06.2009, 21:53
ich glaub du hast auch vergessen den PORTC als eingang zu definieren

Ceos
13.06.2009, 01:49
das brauch man nicht, der ist standardmäßig auf input so wie alles was nciht initialisiert wird