ADC: Zweiter Kanal misst nicht

OP #1380258
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:
1
//ADEN = Enable  ADIF = InterruptFlag  ADIE = InterruptEnable  ADPSx = ADC-Takt 
2
          //Teilerfaktor 128 
3
          ADCSRA |= (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
4

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

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

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

Interrupt Routinen zum speichern:
1
ISR(ADC_vect)
2
{
3
  //Wenn Kanal 7 gemessen wird (111) also MUX0 = 1
4
  if(ADMUX &(1<<MUX0))
5
  {
6
    adcLevel7 = ADC;            //speichere ab
7
  }
8
  
9
  //Wenn Kanal 6 gemessen wird (110) also MUX0 = 0
10
  else if(!(ADMUX &(1<<MUX0)))
11
  {
12
    adcLevel6 = ADC;          //speichere ab
13
  }
14

15
}
D. Berg schrieb:
> Wo ist der Denkfehler?

Hier:

> Messungen:
>
1
>   // ADC Einzelmessungen
2
>            if(convertNow == 1)
3
>          {
4
>         //Messe Kanal 7
5
>         ADMUX  |= (1<<MUX0);          //Wechsel auf ADC Kanal 7 (111)
6
>         ADCSRA |= (1<<ADSC);          //einzelne Messung
7
> 
8
>         //Messe Kanal 6
9
>         ADMUX  &= ~(1<<MUX0);          //Wechsel auf ADC Kanal 6 (110)
10
>         ADCSRA |= (1<<ADSC);          //einzelne Messung
11
> 
12
>         convertNow = 0;              //restart Counter
13
>         }
14
>

Du musst warten bis die erste Messung fertig ist, ehe du die zweite 
startest.
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.
OP
Jetzt habe ich es so probiert, ohne Interrupt mit Warteschleife:
1
  if(convertNow == 1)
2
         {
3
        //Messe Kanal7
4
        ADMUX  |= (1<<MUX0);          //Wechsel auf ADC Kanal 7 (111)
5
        ADCSRA |= (1<<ADSC);          //einzelne Messung
6
        while ( ADCSRA & (1<<ADSC) ) 
7
        { 
8
                                  // auf Abschluss der Konvertierung warten 
9
          }
10
        adcLevel7 = ADC;
11

12

13
        //Messe Kanal6
14
        ADMUX  &= ~(1<<MUX0);          //Wechsel auf ADC Kanal 6 (110)
15
        ADCSRA |= (1<<ADSC);          //einzelne Messung
16
        while ( ADCSRA & (1<<ADSC) ) 
17
        { 
18
                                  // auf Abschluss der Konvertierung warten 
19
          }
20
        adcLevel6 = ADC;
21
  
22
        convertNow = 0;              //restart Counter
23
        }

Funktioniert aber auch nicht, Kanal 7 misst, Kanal 6 nicht!
Gast
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.
Gast
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.
Persönliche Seite
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.
OP
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???
OP
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

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.