PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AD-Wandlung Freilaufend mit ATMega16 - seltsame ergebnisse



DuRo
02.06.2007, 22:16
Hallo Zusammen,

ich habe folgendes Problem mit dem ATMega16 und der AD-Wandlung.
Als Referenzspannung liegen AREF und AVCC mit 5 Volt und einer LOW-Pass
enstörung an. Es soll ein (über ein Poti erzeugter Wert) von 0-5V
ausgewertet werden und je nach Wert z.B. ein Lüfter oder eine Heizung
an/abschalten.


int main ()

{



volatile int x,y,grad, resultat; // Merker für ADC



MCUCSR = (1<<JTD); //JTAG disabel

ADCSRA = ((1<<ADPS1)|(1<<ADPS2)|(1<<ADEN)|(1<<ADSC)|(1<<ADATE));
//Teilfaktor auf 64, Freilaufender Modus, AD-Wandler enablen


ADMUX = ((1<<REFS0)|(0<<REFS1)|(0<<MUX0));
//Referenzspannung definieren (liegt bei uns mit 5V an), PortA Pin0 als Eingang ausgewählt


SFIOR= (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);
//Einstellung für den Freilauf-Modus




//Ausgänge

DDRA = (1<<DDA3)|(1<<DDA4)|(1<<DDA5)|(1<<DDA6)|;
//PortA Pin 3,4,5,6 als Ausgang



do

{



x = ADCL; // ADCL-Register in Variable x speichern

y= ADCH; // ADCL-Register in Variable x speichern

y= (y<<5); //linksshift 5 Stellen



resultat=x+y; //beide Register addieren um 10bit Auflösung zu nutzen
resultat=resultat*10;
//dieser Schritt wird gemacht um eine bessere Gradeinteilung zum REalwert zuerreichen


switch (resultat)

{

case 0: grad=1 ; break;

case 205: grad=2 ; break;

case 410: grad=3 ; break;

case 615: grad=4 ; break;

case 820: grad=5 ; break;

case 1025: grad=6 ; break;

case 1230: grad=7 ; break;

case 1435: grad=8 ; break;

case 1640: grad=9 ; break;

case 1845: grad=10 ; break;

case 2050: grad=11 ; break;

case 2255: grad=12 ; break;

case 2460: grad=13 ; break;

case 2665: grad=14 ; break;

case 2870: grad=15 ; break;

case 3075: grad=16 ; break;

case 3280: grad=17 ; break;

case 3485: grad=18 ; break;

case 3690: grad=19 ; break;

case 3895: grad=20 ; break;

case 4100: grad=21 ; break;

case 4305: grad=22 ; break;

case 4510: grad=23 ; break;

case 4715: grad=24 ; break;

case 4920: grad=25 ; break;

case 5125: grad=26 ; break;

case 5330: grad=27 ; break;

case 5535: grad=28 ; break;

case 5740: grad=29 ; break;

case 5945: grad=30 ; break;

case 6150: grad=31 ; break;

case 6355: grad=32 ; break;

case 6560: grad=33 ; break;

case 6765: grad=34 ; break;

case 6970: grad=35 ; break;

case 7175: grad=36 ; break;

case 7380: grad=37 ; break;

case 7585: grad=38 ; break;

case 7790: grad=39 ; break;

case 7995: grad=40 ; break;

case 8200: grad=41 ; break;

case 8405: grad=42 ; break;

case 8610: grad=43 ; break;

case 8815: grad=44 ; break;

case 9020: grad=45 ; break;

case 9225: grad=46 ; break;

case 9430: grad=47 ; break;

case 9635: grad=48 ; break;

case 9840: grad=49 ; break;

case 10045: grad=50 ; break;

case 10250: grad=50 ; break;

}
//genaue Definition der Gradwerte (geht mit Sicherheit auch einfacher)

if (grad<=10) //Temperatur unter 10° Heizung an
{
PORTA=(1<<PA3);
}
if (grad<=12) //Temperatur über 12° Heizung aus
{
PORTA=(0<<PA3);
}
if (grad>=40) //Temperatur über 40° Lüfter an
{
PORTA=(1<<PA4);
}
if (grad<=30) //Temperatur unter 30° Lüfter an
{
PORTA=(0<<PA4);
}



} while (1);

return(0);



}


Bei Nutzung des Programms erhalte ich am Ausgang PortA Pin 3/4 komische
Werte. Der Ausgang liegt bei 3,x Volt und die LEDs flackern. Wenn man
Testweise den Wert der AD-Wandlung auf LEDs gibt, die am PortC testweise
angeschlossen waren, flackern diese auch. Allerdings sieht es für mich
dann aus, als ob eine AD-Wandlung stattfindet (Überprüfung durch drehen
am Poti - bei Maximalstellung alle Lampen an). So langsam bin ich
ratlos. Kann mir hier jemand von Euch helfen?

Liegt es vielleicht an den restlichen Eingängen von Port A, die nicht
genutzt werden und quasi offen liegen?

Besten Dank und Gruß Roland

robocat
02.06.2007, 22:50
1. ADC kannst du direkt auslesen, wenn nicht left-adjusted. wenn du das nicht willst, musst du 8 bit nach links schieben, nicht nur 5.
2. das ergebnis *10 zu nehmen ist sinnlos, es gibt eh nur ganzzahlen. also wird aus 0,1,2-1023 dann 0,10,20,10230.
3. im grenzbereich zwischen 2 werten kommt es oft zu einem flattern, ergebnis zB 220,220,221,220,221...
4. anstelle der switch (die werte (mit 5 am ende) enthält, die nie vorkommen) würde ich umrechnen mit zB grad=ADC*50/1024.

wenn etwas falsch ist, bitte mich korrigieren.

gruesse

ogni42
02.06.2007, 22:58
Das kann so kaum gehen, da Dein switch nur reagiert, wenn exakt (!) ein Wert getroffen wird (was bei analogen Spannungen nicht sehr wahrscheinlich ist), und, wie robocat schon geschrieben hat, der Wert immer etwas schwankt. Besser (Werte nur als Beispiel):


while(1)
{
int result = ADC;
switch (result)
{
case result < 100: PORTA = (1<<0);
break;
case result < 500: PORTA = (1<<1);
break;
default: PORTA = (1<<2)
}
}