www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC Kanäle in einer For - Schleife ATMega 32


Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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.
#define F_CPU 16000000UL

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

#define photo_u werte[1]

void init_adc(void)
{

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

}


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

    unsigned char n, c;

      
    for (n=0; n<7; n++)
    {
    
      ADMUX = n; 
      
      //Starten von ADC
      ADCSRA|=(1<<ADSC);
    
      //Warten bis Umwandlung startet
      while((ADCSRA & (1<<ADSC)) == 0){}
      
      z_adcl[n] = ADCL;
      z_adch[n] = ADCH;

      z_adc[n] = ADCW;

      ADCSRA&=~(1<<ADSC);

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

      for (c=4; b<7; c++) z_werte[c]= 0.04878 * z_adc[c] - 24.97536; 
      
        //3: Strom Photozelle
        //4: Strom Generator
        //5: strom Akku
      
    }

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

    

  
}






int main(void){

  float werte[7];

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

  unsigned int  adc[7];

  DDRB=0xff;
  init_adc();

  

  
  
  for(;;)
  {
  
    
    messung(adc, werte, adcl, adch);


      if (photo_u > 15.00) 
      {
        PORTB|=(1<<PB0);  
      }
      else
      {
         PORTB&=~(1<<PB0);
      }
      
  }


}


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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ganze scheint mir nicht sehr zeitkritisch zu sein.
Gibt es einen speziellen Grund, warum du nicht die ADC Routine aus dem 
Tutorial benutzt? Die würde nämlich funktionieren.

Autor: JojoS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe die angesprochene Variable "b" in "c" geändert, weil das Forum mir 
eine Spammeldung gebracht hat. Das mit dem Berechnen in der Schleife ist 
ein Fehler, das stimmt.
Das doppelte Auslesen dient, dazu das ADCL und ADCH über den SPI 
übertragen werden sollen.

Autor: JojoS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: JojoS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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-Tu...

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@JojoS

du hattest Recht mit dem "while ( ADCSRA & (1<<ADSC)){}"! jetzt 
fnktioniert das Auslesen.
Die Mittelwertbildung und Festkommaarithmetik werde ich jetzt einmal 
anschauen!

vielen Dank

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.