www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC misst immer 5V


Autor: Hans Wurst (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>


/* ADC initialisieren */
void ADC_Init(void) 
{
 
  uint16_t result;
 
   ADMUX = (0<<REFS1) | (1<<REFS0) | (1<<MUX1);    // AVCC als Referenzspannung nutzen
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
 
  /* Dummy-Readout */
 
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
  while (ADCSRA & (1<<ADSC) );          // auf Abschluss der Konvertierung warten
  /* ADC einmal lesen  */
  result = ADC;
}
 
/* ADC Einzelmessung */
uint16_t ADC_Read(uint8_t channel)
{
  // Kanal waehlen, ohne andere Bits zu beeinflußen
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
  while (ADCSRA & (1<<ADSC) ); 
                                 // auf Abschluss der Konvertierung warten
  return ADC;                    // ADC auslesen und zurückgeben
  main=ADC;
}
 
/* ADC Mehrfachmessung mit Mittelwertbbildung */
uint16_t ADC_Read_Avg(uint8_t channel, uint8_t average)
{
  uint32_t result;
 
  // Kanal waehlen, ohne andere Bits zu beeinflußen
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
  
 
  /* Eigentliche Messung - Mittelwert aus 'average' aufeinanderfolgenden Wandlungen */
  result = 0; 
 
  for (uint8_t i = average; i>0; i-- ) {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while (1);    // auf Abschluss der Konvertierung warten
    result += ADC;                 // Wandlungsergebnisse aufaddieren
  }
 
  result /= average;               // arithmethischer Mittelwert
  return (uint16_t)result;
}
 

 
/* Beispielaufrufe: */
 


void main(void)
{


DDRD=0xff;         /* PortD als ausgang defnieren*/

  uint16_t adcval;
  ADC_Init();
  adcval = ADC_Read_Avg(1, 4);  // Kanal 1, Mittelwert aus 4 Messungen 
 
PORTD &= ~(1<<PD0); /* PD0 auf 0 setzen */
PORTD &= ~(1<<PD1); /* PD1 auf 0 setzen */
 
if (adcval < 314)           /* 314 entspricht 1.5V*/
  
  {
  PORTD |= (1<<PD1);      /* PD1 high wenn adcval größer 314 rot  */
  }

  
if (adcval > 314)     
  
  {
  PORTD |= (1<<PD0);      /* PD1 high wenn adcval kleiner 314 grün  */
  }

}



Hallo zusammen,
hat jemand ne idee warum mein adc immer nur 5V misst und nicht die 
Spannung die über den Widerstand R5 abfällt?
Die Schaltung an sich soll so funktionieren dass die Rote Led leuchtet 
wenn der ADC eine Spannung unter einem bestimmten Wert misst und Grün 
wenn sie über einem bestimmten Spannung liegt Rot leuchtet. Für den 
Anfang würd es mir aber mal reichen das der ADC überhaupt mal was misst 
;).

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

Bewertung
0 lesenswert
nicht lesenswert
for (uint8_t i = average; i>0; i-- ) {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while (1);    // auf Abschluss der Konvertierung warten
    result += ADC;                 // Wandlungsergebnisse aufaddieren
  }

was macht die Endlosschleife da drinnen?


Du hast eine ADC_Read Funktion. Warum benutzt du sie nicht um damit auch 
die mittelnde Version aufzubauen, sondern programmierst dort wieder 
alles aus? Klassisches Beispiel dafür, wie man es nicht macht.

/* ADC Mehrfachmessung mit Mittelwertbbildung */
uint16_t ADC_Read_Avg(uint8_t channel, uint8_t average)
{
  uint32_t result = 0;
 
  for( uint8_t i = 0; i < average; ++i )
    result += ADC_Read( channel );

  return result / average;
}

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

for (uint8_t i = average; i>0; i-- ) {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while (ADCSRA & (1<<ADSC) );    // auf Abschluss der Konvertierung warten
    result += ADC;                 // Wandlungsergebnisse aufaddieren
  }
 


Besser? Hab da was versucht und hab wohl vergessen das wieder zu ändern. 
Mein Fehler misst aber immer noch 5 V.


Karl heinz Buchegger schrieb:
> Du hast eine ADC_Read Funktion. Warum benutzt du sie nicht um damit auch
> die mittelnde Version aufzubauen, sondern programmierst dort wieder
> alles aus?



Weil es in meinem Beispielcode auch so gemacht wurde und ich nicht 
soviel  ändern wollte. Aber eigentlich müsste das doch kein Problem 
sein?

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

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht deine Aussenbeschaltung aus?
Hast du am Optokoppler was angeschlossen?


Hast du mit einem Voltmeter kontrolliert, welche Spannung tatsächlich am 
ADC Eingang anliegt?


Beim schnellen Drüberschauen über den Code hab ich so jetzt erst mal 
nichts mehr gesehen. IMHO ist die Konfiguration des ADC vernünftig.

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An ADC 1 liegen 1,5V sprich Opto ist beschalten der Transistor schaltet 
es leuchtet.

hmm hab ich den Eingangskanal richtig eingestellt mir kommts sovor uC 
ihrgendwas anderes misst.

Stimmt es das dass register beim Atmega 32 ADC heißt und nicht ADCW?

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t ADC_Read(uint8_t channel)
{
  // Kanal waehlen, ohne andere Bits zu beeinflußen
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
  while (ADCSRA & (1<<ADSC) ); 
                                 // auf Abschluss der Konvertierung warten
  return ADC;                    // ADC auslesen und zurückgeben
  main=ADC;
}
change to

uint16_t ADC_Read(uint8_t channel)
{
  // Kanal waehlen, ohne andere Bits zu beeinflußen
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
  while (ADCSRA & (1<<ADSC) );    // auf Abschluss der Konvertierung 
warten
  return ADC;                    // ADC auslesen und zurückgeben
}

Ich mess aber immer noch 5 V

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Wurst schrieb:

> Stimmt es das dass register beim Atmega 32 ADC heißt und nicht ADCW?

Sollte genauso ADCW heissen.

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

Bewertung
0 lesenswert
nicht lesenswert
Ähm.
Ich vermisse in deiner main() die obligatorische while(1) Hauptschleife. 
Dein ADC misst einmal und das wars dann auch.

Autor: Malte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  ADMUX = (0<<REFS1) | (1<<REFS0) | (1<<MUX1);    // AVCC als Referenzspannung nutzen

Datenblatt Seite 214

Hast du nicht 2,56V Intern als Referenz?
  ADMUX = (1<<REFS0) | (1<<MUX1);    // AVCC als Referenzspannung nutzen

so sollte das doch aussehen wenn ich mich nicht irre?!

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

Bewertung
0 lesenswert
nicht lesenswert
void main(void)
{
  uint16_t adcval;

  DDRD = 0xff;         /* PortD als ausgang defnieren*/
  PORTD &= ~(1<<PD0);  /* PD0 auf 0 setzen */
  PORTD &= ~(1<<PD1);  /* PD1 auf 0 setzen */

  ADC_Init();

  while( 1 ) {
    adcval = ADC_Read_Avg(1, 4);  // Kanal 1, Mittelwert aus 4 Messungen 
  
    if (adcval < 314) {           /* 314 entspricht 1.5V*/
      PORTD &= ~(1<<PD0);
      PORTD |=  (1<<PD1);      /* PD1 high wenn adcval größer 314 rot  */
    }
 
    else if (adcval > 314) {
      PORTD |=  (1<<PD0);      /* PD1 high wenn adcval kleiner 314 grün  */
      PORTD &= ~(1<<PD1);
    }
  }
}

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

Bewertung
0 lesenswert
nicht lesenswert
Malte schrieb:
>
  ADMUX = (0<<REFS1) | (1<<REFS0) | (1<<MUX1);    // AVCC als
> Referenzspannung nutzen
> 
>
> Datenblatt Seite 214
>
> Hast du nicht 2,56V Intern als Referenz?
>
>
  ADMUX = (1<<REFS0) | (1<<MUX1);    // AVCC als Referenzspannung
> nutzen
> 
>
> so sollte das doch aussehen wenn ich mich nicht irre?!

Ist egal.
Kommt aufs selbe raus.  0<<REFS1  ist eine glatte 0 und stört somit 
nicht weiter beim verodern der Einzelterme.

Man kanns raus nehmen oder man kanns drinnen lassen um zu dokumentieren, 
dass man REFS1 absichtlich auf 0 haben will.

Autor: pschober (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn die Schaltung so gebaut ist wie auf dem Schaltplan, kann das gar 
nicht funktionieren.
Gnd (Pin31) hängt in der Luft

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Datenblatt Seite 214
>
> Hast du nicht 2,56V Intern als Referenz?


REFS1 REFS0 Voltage Reference Selection
0       0         AREF, Internal Vref turned off
0       1         AVCC with external capacitor at AREF pin
1       0         Reserved
1       1        Internal 2.56V Voltage Reference with external 
capacitor at AREF  pin

ADMUX = (0<<REFS1) | (1<<REFS0) | (1<<MUX1);
ähm Ich wäle doch AVCC aus. Das 0 REFS1 ist zur doku


Laut Datenblatt muss es ADC heißen ADCW taucht nicht einmal auf.

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

Bewertung
0 lesenswert
nicht lesenswert
Hans Wurst schrieb:
>> Datenblatt Seite 214
>>
>> Hast du nicht 2,56V Intern als Referenz?
>
>
> REFS1 REFS0 Voltage Reference Selection
> 0       0         AREF, Internal Vref turned off
> 0       1         AVCC with external capacitor at AREF pin
> 1       0         Reserved
> 1       1        Internal 2.56V Voltage Reference with external
> capacitor at AREF  pin
>
> ADMUX = (0<<REFS1) | (1<<REFS0) | (1<<MUX1);
> ähm Ich wäle doch AVCC aus. Das 0 REFS1 ist zur doku
>
>
> Laut Datenblatt muss es ADC heißen ADCW taucht nicht einmal auf.

In dem Fall gilt ausnahmsweise nicht das Datenblatt, sondern die 
Compilerdoku. Hauptsächlich deshalb, weil der gcc eine Erweiterung für 
alle Pseudo-16 Bit Register enthält, auf die mit dem Registernamen in 
einem Rutsch (anstelle von HighByte/LowByte) zugegriffen werden kann.

ADCW wurde gewählt, weil sonst Verwechslungsgefahr mit der 
Assembler-Anweisung ADC (Add with Carry) besteht. Es ist aber beides 
definiert: ADC und ADCW. Und beide bezeichnen im gcc auch dasselbe: das 
Pseudo-16 Bit Register mit dem Ergebnis der Wandlung.


Wie ist der momentane Zustand
* GND durchverbunden
* neues Hauptprogramm

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Ich vermisse in deiner main() die obligatorische while(1) Hauptschleife.
> Dein ADC misst einmal und das wars dann auch.

hmmm das stimmt aber wenn ich Schleife einfüge (der Vorschlag von dir) 
leuchtet gar nix mehr. Sehr komisch

pschober schrieb:
> Wenn die Schaltung so gebaut ist wie auf dem Schaltplan, kann das gar
> nicht funktionieren.
> Gnd (Pin31) hängt in der Luft

Ja die Masse hängt in der Luft das stimmt und ist beabsichtigt die 
Schaltung wird mit 180V betrieben. Das geht nicht und anderst und 
funktioniert, ich bekomm eine saubere 1.5 V Spannung. Sei auch mal dahin 
gestellt es geht um den ADC

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich versteh die Beschaltung des 2. GND anschlusses nicht (was nicht 
heißen muss, dass sie falsch ist)

edit: was ist denn T2 für ein Bauteil?

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok das habe ich nicht gewusste danke für die Erklärung.

Aktueller Stand:
ADC in ADCW geändert
Hauptprogramm geändert.
An Pin 31 hab ich nichts geändert kann ich den einfach an GND des uC 
anschließen?

Misst 5V

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> ich versteh die Beschaltung des 2. GND anschlusses nicht (was nicht
> heißen muss, dass sie falsch ist)
>
> edit: was ist denn T2 für ein Bautei

Light Duty Radial Leaded Arrestor

oder einfach gesagt ein Überspannungschutz/ableiter

http://www.alldatasheet.com/datasheet-pdf/pdf/2741...

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Fehler die Schleife funktioniert.

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

Bewertung
0 lesenswert
nicht lesenswert
Da die beiden GND Anschlüsse Chipintern höchst wahrscheinlich irgendwo 
zusammengeführt sind, wird sich die fehlende Verbindung erst mal nicht 
grossartig auswirken. Nichtsdestotrotz muss sie gemacht werden.


Ich hatte in meinem Hauptprogramm weiter oben noch einen Fehler. Hast du 
den gesehen (Ich hatte die ~ bei den Verundungen vergessen)?

Denn das hier:
> aber wenn ich Schleife einfüge (der Vorschlag von dir)
> leuchtet gar nix mehr.
kann dann nur mehr sein, wenn der ADC von anfang an und ständig 317 
liefert. Ich hab diese Möglichkeit nicht ausgebaut, weil ich dachte dass 
eine kleine Hysterese nicht schaden kann. Aber seis drum
 while( 1 ) {
    adcval = ADC_Read_Avg(1, 4);  // Kanal 1, Mittelwert aus 4 Messungen 
  
    if (adcval < 314) {           /* 314 entspricht 1.5V*/
      PORTD &= ~(1<<PD0);
      PORTD |=  (1<<PD1);      /* PD1 high wenn adcval größer 314 rot  */
    }
 
    else {
      PORTD |=  (1<<PD0);      /* PD1 high wenn adcval kleiner 314 grün  */
      PORTD &= ~(1<<PD1);
    }
  }

eine der beiden LED MUSS leuchten!

Ich würde mir zum testen ehrlich gesagt auch die Auswerteschaltung 
abklemmen und durch ein stink normales Poti als Spannungsteiler 
ersetzen. Dann kann ich am Poti drehen und einfach sehen ob die 
Umschaltung klappt. Ausserdem bin ich dann nicht darauf angewiesen, dass 
diese Eingangsbeschaltung auch tatsächlich funktioniert.

Autor: Hans Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm ich glaup ich hab die Ursache gefunden egal was ich anschließ es wir 
mir aus 5 V hochgezoegn. Vorher hab ich das nicht gemessen weil der uC 
aus war und die Maße nicht verbunden. wenn ich an den ADC1 und GND 1 V 
anschließ zieht es die auf 5V hoch warum hab ich noch nicht gefunden.

Autor: Hand Wurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ich hab die Schaltung jetzt über nen Spannungsteiler Widerstand+ 
Poti gemacht. Aber der ADC misst immer noch ihrgend nen mist. An PIn 1 
liegt 1,5 V.
Au man . Jemand nen Vorschlag?

Autor: ic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwelche Pullups etc. noch aktiviert auf dem Eingang? Eingang 
explizit als Eingang Definieren und alles was interne Pullups/downs 
betrifft nochmal festnageln.

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.