mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC: Zweiter Kanal misst nicht


Autor: Daniel B. (scheinleistung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich möchte am ADC Kanal 6 und Kanal 7 messen und das dann abspeichern in
variablen. Leider funktioniert es nicht mit Kanal 6, es sieht so aus als 
würde in der Variablen für Kanal 6 immer 0 drin stehen. Wo ist der 
Denkfehler?

Init:
//ADEN = Enable  ADIF = InterruptFlag  ADIE = InterruptEnable  ADPSx = ADC-Takt 
          //Teilerfaktor 128 
          ADCSRA |= (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

          //Auswahl des Messkanals (7) sowie Festlegung des Ref Signals (Hier 01 - AVCC)
          ADMUX  |= (1<<REFS0) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0);
  
          ADCSRA |= (1<<ADSC);     //Eine Dummy-Messung um den ADC zu initialisieren!

Messungen:
  // ADC Einzelmessungen
           if(convertNow == 1)
         {
        //Messe Kanal 7
        ADMUX  |= (1<<MUX0);          //Wechsel auf ADC Kanal 7 (111)
        ADCSRA |= (1<<ADSC);          //einzelne Messung

        //Messe Kanal 6
        ADMUX  &= ~(1<<MUX0);          //Wechsel auf ADC Kanal 6 (110)
        ADCSRA |= (1<<ADSC);          //einzelne Messung
  
        convertNow = 0;              //restart Counter
        }

Interrupt Routinen zum speichern:
ISR(ADC_vect)
{
  //Wenn Kanal 7 gemessen wird (111) also MUX0 = 1
  if(ADMUX &(1<<MUX0))
  {
    adcLevel7 = ADC;            //speichere ab
  }
  
  //Wenn Kanal 6 gemessen wird (110) also MUX0 = 0
  else if(!(ADMUX &(1<<MUX0)))
  {
    adcLevel6 = ADC;          //speichere ab
  }

}

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. Berg schrieb:
> Wo ist der Denkfehler?

Hier:

> Messungen:
>
>   // ADC Einzelmessungen
>            if(convertNow == 1)
>          {
>         //Messe Kanal 7
>         ADMUX  |= (1<<MUX0);          //Wechsel auf ADC Kanal 7 (111)
>         ADCSRA |= (1<<ADSC);          //einzelne Messung
> 
>         //Messe Kanal 6
>         ADMUX  &= ~(1<<MUX0);          //Wechsel auf ADC Kanal 6 (110)
>         ADCSRA |= (1<<ADSC);          //einzelne Messung
> 
>         convertNow = 0;              //restart Counter
>         }
> 

Du musst warten bis die erste Messung fertig ist, ehe du die zweite 
startest.

Autor: Daniel B. (scheinleistung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber ich arbeite doch mir Interrupt! Nach der ersten Messung wird der 
Interrupt gestartet und der Wert abgespeichert. Dann geht es zurück zur 
zweiten Messung und dann ebenfalls wieder nach der Messung Interrupt -> 
abspeichern.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. Berg schrieb:
> Nach der ersten Messung wird der
> Interrupt gestartet und der Wert abgespeichert.

Ja.

> Dann geht es zurück zur zweiten Messung

Da ist deine Software schon lange dran vorbei, denn nirgends steht, dass 
nach dem Start der ersten Messung gewartet werden soll, bis der 
Interrupt aktiv war.
Du könntest entweder im Interrupt die zweite Messung starten, oder du 
setzt im Interrupt eine Variable auf 1, die anzeigt dass der Interrupt 
die Ergebnisse gelesen hat.
Aber so macht der Interrupt keinen Sinn, wenn du sowieso auf das Ende 
der Messung wartest. Da kannst du auch den Interrupt weglassen, und 
stattdessen direkt auf das Ende der Messung warten und das Ergebnis 
auslesen ehe du die zweite Messung startest.

Autor: Daniel B. (scheinleistung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt habe ich es so probiert, ohne Interrupt mit Warteschleife:
  if(convertNow == 1)
         {
        //Messe Kanal7
        ADMUX  |= (1<<MUX0);          //Wechsel auf ADC Kanal 7 (111)
        ADCSRA |= (1<<ADSC);          //einzelne Messung
        while ( ADCSRA & (1<<ADSC) ) 
        { 
                                  // auf Abschluss der Konvertierung warten 
          }
        adcLevel7 = ADC;


        //Messe Kanal6
        ADMUX  &= ~(1<<MUX0);          //Wechsel auf ADC Kanal 6 (110)
        ADCSRA |= (1<<ADSC);          //einzelne Messung
        while ( ADCSRA & (1<<ADSC) ) 
        { 
                                  // auf Abschluss der Konvertierung warten 
          }
        adcLevel6 = ADC;
  
        convertNow = 0;              //restart Counter
        }

Funktioniert aber auch nicht, Kanal 7 misst, Kanal 6 nicht!

Autor: noips (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist der Pin des Kanals 6 hardwaretechnisch in Ordnung? Ich habe schon 
mal einen Eingangs-Pin eines ADC aus Versehen durch zu hohe Spannung 
kaputt gemacht und bei der Wandlung hat der auch sehr kleine Werte 
gemessen obwohl die gleiche Spannung wie an anderen Kanälen angelegen 
hat. Wenn der betroffene Pin auch eine I/O-Funktion hat, versuch mal 
eine LED mit dem blinken zu lassen. Wenn das nicht geht, dann ist der 
Pin wohl nicht mehr OK.

Autor: Diensthabender Troll (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht mal das Konzept überdenken?

Z.B.:

In ISR ADC-Wert auslesen und (in Array) sichern, dann Index (auf 
Ergebnis und Mess-Quelle) erhöhen, (aus zweitem Array) neuen MUX-Wert 
holen und in ADMUX schreiben. Das legt Dir im Hintergrund die ADC-Werte 
verschiedener Quellen ins Array, auf das Du im Hauptprogramm jederzeit 
zugreifen kannst. Und es spart Rechenzeit, weil Du (nach der ersten 
Mess-Runde) nirgends auf die nächste Wandlung warten musst.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Diensthabender Troll schrieb:
> Vielleicht mal das Konzept überdenken?
>
> Z.B.:
>
> In ISR ADC-Wert auslesen und (in Array) sichern, dann Index (auf
> Ergebnis und Mess-Quelle) erhöhen, (aus zweitem Array) neuen MUX-Wert
> holen und in ADMUX schreiben. Das legt Dir im Hintergrund die ADC-Werte
> verschiedener Quellen ins Array, auf das Du im Hauptprogramm jederzeit
> zugreifen kannst. Und es spart Rechenzeit, weil Du (nach der ersten
> Mess-Runde) nirgends auf die nächste Wandlung warten musst.

Bei 16 Bit Werten muss man aber auf Atomizität achten. Also Double 
Buffer verwenden und dann wirds wieder aufwendig.

Autor: Michael Steinbauer (Firma: Steinbauer Electronics GmbH) (captain-stone)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. Berg schrieb:

> Funktioniert aber auch nicht, Kanal 7 misst, Kanal 6 nicht!

Hast Du schon mal versucht zuerst Kanal 6 abzufragen. Damit kannst Du 
die Suche eingrenzen. ADC oder Software von einer zur nächsten Wandlung 
n.i.O.

Michael

Autor: Daniel B. (scheinleistung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gute Idee, sieht so aus als würde ich auch mit Kanal 6 alleine nichts 
hinbekommen, da stimmt irgendwas grunsätzliches nicht oder er hat 
wirklich einen Schaden...

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

Bewertung
0 lesenswert
nicht lesenswert
Du kannst auch mal die ADC Funktion aus dem Tutorial benutzen und die in 
einer Schleife mit abwechselnden Kanalnummern aufrufen.

Autor: Daniel B. (scheinleistung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OHHHH Leute ich hab glaub ich nen dummen Fehler gemacht... Ich messe die 
Spannung vor dem Optokoppler mit Kanal 6. Wegen der galvanischen 
Trennung haben die gar keine gemeinsame Masse! Gerade messe ich die 
Spannung un er misst 0V bezogen auf die uC Masse. Riesen Denkfehler! 
Wenn ich jetzt aber die Massen verbinde ist das ganze ja nicht mehr 
galvanisch getrennt, gibt es da einen Ausweg???

Autor: noips (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Differenzverstärker zwischenschalten.

Autor: Daniel B. (scheinleistung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn die beiden Schaltkreise gemeinsame Masse haben, ist das ganze dann 
noch einigermaßen gut galvanisch getrennt oder wars das dann sofort mit 
der Trennung. Ich möchte sicherstellen, dass der steuernde Kreis nicht 
rückwärts von meiner Elektronik gestört werden kann. Der steuernde Kreis 
berührt meine Elektronik aber nur am Input Capture Pin zum PWM einlesen. 
Was meint Ihr? Wie relevant ist hier die galvanische Trennung?

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.