Forum: Mikrocontroller und Digitale Elektronik A/D Wandler am ATMega16 immer 0


von CarstenM (Gast)


Lesenswert?

Hallo,

ich versuche vergebens bei meinem ATMega 16  mit 8 Mhz den A/D in 
betrieb zu nehmen.
Dazu habe ich das Beispiel aus dem Tutorial genommen und nur den ADC0 
mit 1,86V beschaltet. Eigentlich hätte ich erwartet nun einen Wert um 
744 zu bekommen aber es steht immer 0 drin.

Am Beispielprogramm habe ich den Prescaler auf 128 gesetzt und ADCL und 
ADCH nacheinander ausgelesen. Ansonsten ist es identisch.



Hat jemand eine Idee wo mein Fehler liegt?
1
void main(void)  
2
3
  char test_1 ="TEST123";
4
  uint16_t adcvalue_1;
5
  double adcvalue_2 = 0;
6
  
7
  while(1){
8
  adcvalue_1 = ReadChannel(0);         //Zwischenspeichern des Int-Wertes
9
  adcvalue_2 = adcvalue_1*0,0025;      //Umwandlung in double-Wert
10
11
  ftoa(test_1,adcvalue_2,2,1,0);      //Umwandlun double in char
12
  
13
  if(adcvalue_1 != 0)      
14
  {
15
    lcd_set_cursor(5,LINE0+10);      //Ausgabe auf dem LCD
16
    lcd_puts(small_font, test_1);    //Ausgabe auf dem LCD
17
    _delay_ms(400);
18
    }
19
  }
20
21
22
23
}
24
25
uint16_t ReadChannel(uint8_t mux)
26
{
27
  uint8_t i;
28
  uint16_t result;
29
 
30
  ADMUX = mux;
31
  ADMUX |= (1<<REFS1) | (1<<REFS0);
32
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
33
  ADCSRA |= (1<<ADSC);
34
  while ( ADCSRA & (1<<ADSC) ) 
35
  {
36
     ;     
37
  }
38
  result = ADCL;
39
  result += (ADCH<<8);  
40
  result = 0;
41
 
42
  for( i=0; i<1; i++ )
43
  {
44
    ADCSRA |= (1<<ADSC); 
45
    while ( ADCSRA & (1<<ADSC) )
46
    {
47
      ;   
48
    }
49
    result = ADCL;
50
  result += (ADCH<<8);
51
  }
52
  ADCSRA &= ~(1<<ADEN);
53
 
54
  result /= 1; 
55
  return result;
56
}

Gruß
Carsten

von Naja (Gast)


Lesenswert?

Welches Tutorial soll denn das gewesen sein? Kann man gleich mal 
sperren.

Das hier fand ich extrem lehrreich.

result /= 1;

von CarstenM (Gast)


Lesenswert?

hehe,

dort stand mal:

result /= 4;

mit der for-schleife darüber sollte dann ein Mittelwert gebildet werden.
Aber die Schleife läuft zurzeit nur 1x. Ich wollte es nicht löschen, ich 
war da nur faul.

Naja und das Tutorial komm von hier ;)


http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Analoge_Ein-_und_Ausgabe

von Karl H. (kbuchegg)


Lesenswert?

Naja schrieb:
> Welches Tutorial soll denn das gewesen sein? Kann man gleich mal
> sperren.

Nö, wieso?
Es wäre besser erst mal C zu lernen, ehe man das Tutorial angreift :-)


Hier
1
  adcvalue_2 = adcvalue_1*0,0025;      //Umwandlung in double-Wert
multiplizierst du mit 0

Kommazahlen werden in Programmiersprachen immer in englischer 
Schreibweise, also mit Dezimalpunkt geschrieben.
1
  adcvalue_2 = adcvalue_1*0.0025;      //Umwandlung in double-Wert

dann klappts auch mit dem Auswerten.

von Karl H. (kbuchegg)


Lesenswert?

Das hier

  char test_1 ="TEST123";

gheht auch nicht.
Wie willst du eine komplette Zeichenkette in einer Variablen speichern, 
die gerade einmal 1 Zeichen aufnehmen kann?
Hat dein Compiler den dazu gar nichts gesagt?

von Karl H. (kbuchegg)


Lesenswert?

ftoa(test_1,adcvalue_2,2,1,0);      //Umwandlun double in char


was ist das für eine Funktion?

Die C-Standardfunktion dafür heisst zwar auch ftoa, die kann es aber 
nicht sein. Die hat andere Argumente.
Und schau dir die Argmuente dafür an. Die erste Zahl ist üblicherweise 
die komplette Anzahl an Stellen. Bei dir wären das 2. Das wird ein 
bischen eng wenn du Kommazahlen ausgibst. Bereits die Vorkommastelle und 
der Dezimalpunkt belegen die vorgesehenen 2 Zeichen.

von CarstenM (Gast)


Lesenswert?

Hallo,

danke für den Hinweis. Du hast recht es muss natürlich 0.0025 heißen.
Nur hast du leider folgendes übersehen:

[c]
if(adcvalue_1 != 0)
{
   lcd_set_cursor(5,LINE0+10);
   lcd_puts(small_font, test_1);
   _delay_ms(400);
}

Egal was in adcvalue_2 steht, angezeigt wir nur etwas, wenn adcvalue_1 
!=0 ist. Und darin sollte der Wert vom Register stehen.
Nur wieso ist das nicht so?

Muss ich die externe Beschaltung noch ergänzen? Oder reicht es einfach 
eine Spannung an ADC0 anzulegen?

von Karl H. (kbuchegg)


Lesenswert?

CarstenM schrieb:

> Egal was in adcvalue_2 steht, angezeigt wir nur etwas, wenn adcvalue_1
> !=0 ist. Und darin sollte der Wert vom Register stehen.
> Nur wieso ist das nicht so?

Wieso ist was nicht so?

Das möchte ich ganz gerne sehen, wie du auf einem LCD ausgibst, welches 
nicht initialisiert ist.
Hör auf zu künsteln und fang von vorne an:
ADC Wert ausgeben ohne irgendwelchen Schnickschnack.
Und bevor du das tust, stell sicher, dass dein LCD funktioniert. Schreib 
von mir aus "ADC-Test" irgendwo hin. Und wenn du diesen Text nicht 
siehst, dann ist deine LCD Ansteuerung im A... und nicht der ADC.

von CarstenM (Gast)


Angehängte Dateien:

Lesenswert?

Hier der komplette Quellcode.

Ich wollte mich nur auf den A/D Wandler mit meiner Fragen beziehen.
Der Rest läuft ohne Probleme.

>ftoa(test_1,adcvalue_2,2,1,0);      //Umwandlun double in char
>was ist das für eine Funktion?

Siehe in meinem Quellcode(nunmtostr.c). So kann ich einen array 
erstellen, das beliebige Vor und Nachkommastellen hat. (Stammt auch von 
hier)

von Karl H. (kbuchegg)


Lesenswert?

Immer noch:
  char test_1 ="TEST123";


Das geht so nicht!
Du kannst nicht einen kompletten String in einem einzelnen char 
unterbringen!


   char test_l[] = "Test123";

und stell besser sicher, dass der String, der bei ftoa enstehen wird 
auch tatsächlich in das ARray passt. Also besser klotzen und nicht 
kleckern

   char test_l[15];


(Warum verwendest du eigentlich nicht die Standardfunktionen zur ASCII 
Umwandlung?)

von CarstenM (Gast)


Lesenswert?

Danke erstmal das du dir die Zeit nimmst, alles durchzuschauen.
Ich hab nochmal den Link zum Thread rausgesucht, aus dem ich ftoa habe.

Beitrag "C-Umwandlungsfunktionen für double/int/long nach String"
Ich kenne zwar atoi aber den passenden gegenpart.

Um das ganze einfacher zu machen gehe ich wohl besser auf Anfang und 
werde nur den ADC nutzen und dann alles auf einem PORt ausgeben. 
Vielleicht klappt es dann ja.

von Karl H. (kbuchegg)


Lesenswert?

CarstenM schrieb:
> Danke erstmal das du dir die Zeit nimmst, alles durchzuschauen.
> Ich hab nochmal den Link zum Thread rausgesucht, aus dem ich ftoa habe.
>
> Beitrag "C-Umwandlungsfunktionen für double/int/long nach String"
> Ich kenne zwar atoi aber den passenden gegenpart.

itoa :-)
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F

von Naja (Gast)


Lesenswert?

@ Karl heinz Buchegger

>Naja schrieb:
>> Welches Tutorial soll denn das gewesen sein? Kann man gleich mal
>> sperren.

>Nö, wieso?
>Es wäre besser erst mal C zu lernen, ehe man das Tutorial angreift :-)

CarstenM schrieb:
>Ansonsten ist es identisch.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

>dort stand mal:
>result /= 4;

>adcvalue_2 = adcvalue_1*0,0025;
>char test_1 ="TEST123";

Es wäre besser gewesen erst mal lesen zu lernen, ehe man anderer Leute 
Beiträge angreift :-)

von Karl H. (kbuchegg)


Lesenswert?

Naja schrieb:

> Es wäre besser gewesen erst mal lesen zu lernen, ehe man anderer Leute
> Beiträge angreift :-)

Ich vermisse deine konstuktiven Beiträge die mithelfen das Problem des 
TO zu lösen.

Und nein: das er die Mittelwertbildung aus 4 Werten lahmgelegt hat, ist 
nicht das Problem.
Und ja: Die Änderung, die er an der Funktion aus dem Tutorial gemacht 
hat, ist zulässig (wenn er sonst nichts an der Registereinstellung 
verändert hat - habs nicht kontrolliert).
Und ja: Die Funktion aus dem Tutorial funktioniert.

>>dort stand mal:
>>result /= 4;
>
>>adcvalue_2 = adcvalue_1*0,0025;
>>char test_1 ="TEST123";
>

Die erste Modifikation (4->1) ist also kein Problem. Die anderen beiden 
sind echte Fehler, haben allerdings nichts mit dem Tutorial zu tun. 
Warum soll man daher das Tutorial sperren?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.