ADC Kanäle in einer For - Schleife ATMega 32

#1142099
Lesenswert?

Hallo zusammen,

Ich habe eine ADC Funktion geschrieben, welche die ADC Kanäle 0 bis 5 
auslesen soll. Mein Problem ist nun, dass wenn ich den Laufindex der 
For- Schleife gleichzeitig als ADMUX Adressen verwenden möchte, kein ADC 
Wert gelesen wird. Beim Eintragen von z.B. ADMUX = 1 funktioniert 
folgendes Programm.
1
#define F_CPU 16000000UL
2

3
#include <util/delay.h>
4
#include <avr/io.h>
5

6
#define photo_u werte[1]
7

8
void init_adc(void)
9
{
10

11
  //Einschalten von ADC, Datenblatt S.216
12
  ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
13

14
}
15

16

17
void messung(unsigned int *z_adc, float *z_werte, unsigned char *z_adcl, unsigned char *z_adch){
18

19
    unsigned char n, c;
20

21
      
22
    for (n=0; n<7; n++)
23
    {
24
    
25
      ADMUX = n; 
26
      
27
      //Starten von ADC
28
      ADCSRA|=(1<<ADSC);
29
    
30
      //Warten bis Umwandlung startet
31
      while((ADCSRA & (1<<ADSC)) == 0){}
32
      
33
      z_adcl[n] = ADCL;
34
      z_adch[n] = ADCH;
35

36
      z_adc[n] = ADCW;
37

38
      ADCSRA&=~(1<<ADSC);
39

40
      z_werte[1]= 0.021505 * z_adc[1]; //Spannung Photozelle
41
      z_werte[2]= 0.014663 * z_adc[2]; //Spannung Akku
42
      z_werte[3]= 0.039100 * z_adc[3]; //Spannung Generator
43

44
      for (c=4; b<7; c++) z_werte[c]= 0.04878 * z_adc[c] - 24.97536; 
45
      
46
        //3: Strom Photozelle
47
        //4: Strom Generator
48
        //5: strom Akku
49
      
50
    }
51

52
    if (n==6) n=0; //Rücksetzen des For-Schleifen-Zählers 
53
    if (c==6) c=0; //siehen Oben
54

55
    
56

57
  
58
}
59

60

61

62

63

64

65
int main(void){
66

67
  float werte[7];
68

69
  unsigned char adcl[6], adch[6], n, b;
70

71
  unsigned int  adc[7];
72

73
  DDRB=0xff;
74
  init_adc();
75

76
  
77

78
  
79
  
80
  for(;;)
81
  {
82
  
83
    
84
    messung(adc, werte, adcl, adch);
85

86

87
      if (photo_u > 15.00) 
88
      {
89
        PORTB|=(1<<PB0);  
90
      }
91
      else
92
      {
93
         PORTB&=~(1<<PB0);
94
      }
95
      
96
  }
97

98

99
}

Ich habe auch schon versucht in Abhängigkeit von n den ADMUX die 
entsprechende Adresse über den case-Befehl zuzuweisen.
Kann mir vielleicht jemand einen Tipp geben, wo die Ursache sein könnte?

Stephan
#1142107
Lesenswert?

> for (c=4; b<7; c++)
Was hat es denn mit der Durchlaufbedingung der Schleife auf sich? Eine 
Variable b gibt es da nicht! Das müsste zumindest mal ne Fehlermeldung 
geben.

Und was soll das doppelte Auslesen der ADC-Datenregister? Und bist Du 
sicher, dass Du wirklich GLeitkommaberechnungen brauchst? Meist ist 
Festkommaarithmetik sinnvoller...

Und noch was:
> while((ADCSRA & (1<<ADSC)) == 0){}
Überlege mal, was in dieser Zeile passiert! Kleiner Tip: Solange die 
Wandlung läuft, ist ADSC gesetzt...
Gast #1142120
Lesenswert?

das 'b<7' soll sicher 'c<7' heissen. Und die Float Skalierungen mit den 
festen Indizes gehören nicht in die for Schleife, da wird 8mal das 
Gleiche berechnet.
Und wozu das merkwürdige Rücksetzen der Schleifenzähler?
#1142130
Lesenswert?

JojoS wrote:
> das 'b<7' soll sicher 'c<7' heissen. Und die Float Skalierungen mit den
> festen Indizes gehören nicht in die for Schleife, da wird 8mal das
> Gleiche berechnet.
> Und wozu das merkwürdige Rücksetzen der Schleifenzähler?
Na, so tief in die Details bin ich noch gar nicht gegangen. Solange er 
nicht auf das Ende der Wandlung wartet, bevor er das Ergebnis ausliest, 
kann da nix Sinnvolles rauskommen...
Gast #1142142
Lesenswert?

ein bischen wird ja gewartet:
      //Warten bis Umwandlung startet
      while((ADCSRA & (1<<ADSC)) == 0){}
man muss natürlich auf das Ende der Wandlung warten. Ob das mit dieser 
Abfrage gemacht wird, weiss ich nicht, bin zu faul nachzusehen. Aber den 
Teil würde ich auch dem Tutorial abschreiben.
Und die Schleife wird 7mal durchlaufen, nicht 8mal wie ich erst schrieb. 
+/- 1, altes Informatikerproblem :-)
#1142150
Lesenswert?

Der Grund, weshlab ich nicht die Routine aus dem Tutorial benutzte ist, 
dass ich zu jedem Aufruf der Funktion alle Kanäle benötige. Ich möchte 
also nicht jedesmal den zu lesenden Kanal übertragen.

Der Ablauf in der Main Routine dient nur zu Testzwecken. Im eigentlichen 
Programm wird die Funktion "Messung" mehrmals aufgerufen.
Gast #1142151
Lesenswert?

ein Fehler ist die mehrfache Berechnung nicht, nur eine lange 
Warteschleife weil float Mathe nicht die Stärke eines AVR ist :-)
Aber der Fehler dürfte doch in der Abfrage auf das Wandlungsende liegen, 
du fragst auf ==0 ab, aber lt. Tutorial wird das Bit bei Wandlungsende 
gelöscht.
Die Mittelwertbildung für die Wandlung ist auch zu empfehlen.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ADC_.28Analog_Digital_Converter.29

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren