Forum: Mikrocontroller und Digitale Elektronik AVR Atmega16 ADC falsche Messungen


von M. G. (elch)


Lesenswert?

Hallo nochmal ;)
Ich versuche zur Zeit eine Spannung von Phototransistoren an meinem 
Atmega16 mit dem ADC auszulesen.Dazu habe ich den folgenden code 
geschrieben.
Das Problem ist, das der ADC mir wenn die Phototransistoren nicht 
angeschlossen sind schon einen Wert von 1023 ausgibt.
Den Atmega habe ich nach dieser 
(http://www.kreatives-chaos.com/images/38.png) Schaltung aufgebaut, 
allerdings ohne den reset widerstand.
Hier der Code:
1
#define F_CPU 16000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
//Variablen :
7
unsigned int adc_links=0;  //Spannung des linken Infrarottransistors
8
unsigned int adc_rechts=0;  //Spannung des rechten Infrarottransistors  
9
unsigned int adc_oben=0;  //Spannung des oberen Infrarottransistors
10
unsigned int adc_unten=0;   //Spannung des unteren Infrarottransistors
11
unsigned int result=0;        //Ausgabe der ReadChannel funktion
12
13
int ReadChannel(unsigned int mux)
14
{  
15
  
16
  result=0;
17
  ADMUX=mux;    //kanal waehlen 
18
  _delay_us(40);  //40 mikrosekunden warten zum einstellen des Kanals
19
  result=ADCL;
20
  result+=(ADCH<<8);  
21
  return result;
22
}
23
24
int main()
25
{
26
////////////////////////////////////////////////////////////////////////////////////////////////////
27
    //ADC///////////////////////////////////////////////////////////////////////////////////////////////
28
29
  ADCSRA|=(1<<ADEN);//ADC Enable !
30
  SFIOR=0x00;        //freilaufender Modus
31
  ADCSRA|=(1<<ADATE);//freilaufender Modus
32
  ADCSRA|=(1<<ADSC);//Messung aktivieren
33
  ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);// Vorteiler 128 -> F=125Khz -> 9615 Messungen die Sekunde
34
  ADMUX|=(1<<REFS0); //AVCC als Referenzspannung
35
  _delay_us(120);    //120 microsekunden warten zum einstellen
36
  result=ADCW; //Testdurchlauf
37
38
 while(1)
39
   {
40
    //Auslesen der ADC Kanaele:
41
    adc_links=ReadChannel(1);
42
    adc_rechts=ReadChannel(2);
43
    adc_oben=ReadChannel(3);
44
    adc_unten=ReadChannel(4);
45
    
46
///////////////////////////////////////////////TEST
47
    if(adc_links>=1023)PORTB|=(1<<PIN0);
48
    if(adc_links>925)PORTB|=(1<<PIN1);
49
    if(adc_links<820)PORTB&=~(1<<PIN0);
50
    if(adc_links<925)PORTB&=~(1<<PIN1);
51
52
////////////////////////////////////////////////////
53
        }
54
return 0;
55
}

Die Werte bei denen bei PortB etwas ausgegeben wird sind nur zum Testen 
gedacht.
Ich beschaeftige mich zum ersten Mal mit dem ADC und vermute das es sich 
um einen einfachen Anfaengerfehler handelt.
Allerdings finde ich meinen Fehler nicht, und auch die Forensuche hat 
nichts ergeben.
Vielen Dank schonmal im Voraus!

von spess53 (Gast)


Lesenswert?

Hi

>Den Atmega habe ich nach dieser
>(http://www.kreatives-chaos.com/images/38.png) Schaltung aufgebaut,
>allerdings ohne den reset widerstand.

Da fehlt ein Kondensator (100n) von VCC nach GND).

>int ReadChannel(unsigned int mux)
>{
>  result=0;
>  ADMUX=mux;    //kanal waehlen
>  _delay_us(40);  //40 mikrosekunden warten zum einstellen des Kanals
>  result=ADCL;
>  result+=(ADCH<<8);
>  return result;
>}

An welcher Stelle startest du den ADC?

MfG Spess

von M. G. (elch)


Lesenswert?

Den Kondensator von Vcc nach Gnd gibt es bei mir natürlich auch.
Ich dachte die Messung wird hier aktiviert:
1
  ADCSRA|=(1<<ADEN);//ADC Enable !
2
  SFIOR=0x00;        //freilaufender Modus
3
  ADCSRA|=(1<<ADATE);//freilaufender Modus
4
  ADCSRA|=(1<<ADSC);//Messung aktivieren
Mit freundlichen Grüßen!

von Karl H. (kbuchegg)


Lesenswert?

Starte deinen ersten Ausflug mit dem ADC mit der Routine im Tutorial. 
Die übernimmst du erstmal so wie sie ist. Wenn dann alles läuft, kannst 
du die immer noch verändern.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_interne_ADC_im_AVR

von M. G. (elch)


Lesenswert?

Diesmal habe ich mich so weit wie moeglich am Tutorial orientiert, und 
dadurch zu single-conversion gewechselt.
1
  uint16_t ReadChannel(uint8_t mux)
2
  {
3
    uint8_t i;
4
    uint16_t result;
5
6
7
    ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);// Vorteiler 128 -> F=125Khz -> 9615 Messungen die Sekunde 
8
                      //ADC aktivieren
9
    ADMUX = mux; // Kanal waehlen
10
    _delay_us(40);  //40 mikrosekunden warten um Kanal einzustellen
11
    ADMUX|=(1<<REFS0); //AVCC als Referenzspannung
12
13
  ////////////////////Dummy Readout:
14
    ADCSRA |= (1<<ADSC);       // eine ADC-Wandlung
15
    while ( ADCSRA & (1<<ADSC)){}   // auf Abschluss der Konvertierung warten
16
    result = ADCW;           // ADCW auslesen
17
    result = 0;            //Dummy readout loeschen
18
  /////////////////
19
20
    ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
21
    while ( ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten
22
    result=ADCL;          //ADC auslesen
23
    result+=(ADCH<<8);
24
    ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
25
    return result;
26
  }

Den Prescaler musste ich aendern, da mein Mega16 mit 16 Mhz arbeitet.
Ausserdem habe ich Avcc als Referenz eingestellt, da ich fast 5 volt 
messen muss, wozu die interne Referenzspannung meines Achtens nicht 
ausreicht.
Ich habe auch schon einen andern Mega16 ausprobiert, aber es 
funktioniert nicht so wie es soll.
Das Programm gibt mit jetzt fuer Kanal 1 1023 aus, obwohl kaum eine 
Spannung anliegt.
Mit freundlichen Gruessen.

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:
> Diesmal habe ich mich so weit wie moeglich am Tutorial orientiert, und
> dadurch zu single-conversion gewechselt.

Gut.
Der _delay_us ist zwar sinnlos, aber was solls. Er tut auch nichts

> Den Prescaler musste ich aendern, da mein Mega16 mit 16 Mhz arbeitet.

ok

> Ausserdem habe ich Avcc als Referenz eingestellt,

OK. Und an Avcc ist bei dei deinem µC auch eine Spannung angeschlossen?

> Das Programm gibt mit jetzt fuer Kanal 1 1023 aus

1023 bedeutet:
Die Spannung am Messeingang ist gleich oder größer als die eingestellte 
Referenz.
Welche Spannung misst du den an ARef?

von M. G. (elch)


Lesenswert?

Sieht so aus als haette ich Avcc und Aref fuer das selbe gehalten ^^
Wie gesagt , das ist mein erstes ADC Programm.
Ich versuch dann wohl am besten mein Glueck gleich nochmal wenn Aref 
auch beschaltet ist.

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:
> Sieht so aus als haette ich Avcc und Aref fuer das selbe gehalten ^^
> Wie gesagt , das ist mein erstes ADC Programm.
> Ich versuch dann wohl am besten mein Glueck gleich nochmal wenn Aref
> auch beschaltet ist.

Nein!

Lies bitte das Tutorial. Dazu habe ich dir den Link gepostet.
An ARef keine Spannung anschliessen ist ok. Ganz im Gegeteil.
Aber dort kannst du nachmessen, welche Referenzspannung tatsächlich 
eingestellt und benutzt wird.

Du hast ja interne Referenzspannung benutzt, in deinem Fall AVcc. Das 
ist ja ok. Aber miss doch mal nach, ob das auch alles stimmt. Dazu hast 
du ja den ARef Ausgang, damit du dort
  * mit dem Kondensator die Spannung stabiliseren kannst
  * Die Spannung nachmessen kannst.

von M. G. (elch)


Lesenswert?

Gut, das hat mich schon ein Bisschen verwirrt, da ich ja Avcc als 
Referenz nutze.
Wo koennte dann der Fehler liegen ?

von M. G. (elch)


Lesenswert?

An Aref liegt eine konstante Spannung von etwa 4,6 Volt an.

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:
> An Aref liegt eine konstante Spannung von etwa 4,6 Volt an.

OK.
Hardwaremässig sieht es dann so aus, als ob erst mal alles in Ordnung 
wäre.

Deine Messspannung ist nicht größer als ARef (hast du kontrolliert?)

von Karl H. (kbuchegg)


Lesenswert?

Und nimm bitte die ADC_Routine aus dem Tut 1:1 so wie so dort drinnen 
ist. Einzig an den Vorteiler-Bits spielen um den höheren Vorteiler zu 
erhalten. Sonst alles so wie da drinn angegeben.

Hintergrund: Ich will mir jetzt ehrlich nicht aus dem Datenblatt 
zusammensuchen, in welcher Reihenfolge Vorteiler, Referenzspannung und 
'ADC ein' eingestellt werden müssen, damit alles klappt. Vielleicht gibt 
es da keinen Zusammenhang, vielleicht auch schon.

Was ist so schwer drann, die Routine erst mal 1:1 zu übernehmen und erst 
hinterher den Optimierstift anzusetzen?
Wie heißt es so schön: Vorzeitige Optimierung ist die Wurzel allen 
Übels.

von M. G. (elch)


Lesenswert?

Ok, diesmal habe ich wirklich den Code aus dem Tutorial exakt 
uebernommen, bis auf den Vorteiler.
1
    uint16_t ReadChannel(uint8_t mux)
2
    {
3
      uint8_t i;
4
      uint16_t result;
5
      ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Frequenzvorteiler
6
      // setzen auf 128 (1) und ADC aktivieren (1)
7
      ADMUX = mux; // Kanal waehlen
8
      ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
9
      /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
10
      also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
11
      ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
12
      while ( ADCSRA & (1<<ADSC) ) {
13
      ; // auf Abschluss der Konvertierung warten
14
      }
15
      result = ADCW; // ADCW muss einmal gelesen werden,
16
      // sonst wird Ergebnis der nächsten Wandlung
17
      // nicht übernommen.
18
      /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
19
      result = 0;
20
      for( i=0; i<4; i++ )
21
      {
22
      ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
23
      while ( ADCSRA & (1<<ADSC) ) {
24
      ; // auf Abschluss der Konvertierung warten
25
      }
26
      result += ADCW; // Wandlungsergebnisse aufaddieren
27
      }
28
      ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
29
      result /= 4; // Summe durch vier teilen = arithm. Mittelwert
30
      return result;
31
    }

Die Messspannung betraegt im Moment noch etwa 0,9 Volt. Aber selbst wenn 
ich die Fototransistoren , die die 0,9 Volt durchlassen nicht 
anschliesse, geben mir alle vier Kanaele 1023 aus.

von Karl H. (kbuchegg)


Lesenswert?

Hast du eine Möglichkeit, dir die Zahlenwerte genau anzusehen?
Ein LCD, UART oder vielleicht 8 LED am PortB auf die man den ADC Wert 
direkt ausgeben kann?

(Und noch einmal abspecken: Nimm nur einen Kanal und häng statt dem 
Transistor einen als Spannungsteiler verschaltetetes Poti drann, damit 
du die Messspannung gezielt einstellen kannst)

Mit LED zb so
(Wo stellst du eigentlich bei deinem Programm den Port B auf Ausgang?)
1
int main()
2
{
3
  unsigned int adc_links;
4
5
  DDRB = 0xFF;
6
  PORTB = 0x00;
7
8
  while( 1 ) {
9
    adc_links = ReadChannel(1);
10
    PORTB = adc_links / 4;     // 0 .. 1024; / 4 damit es in 8 Bit passt
11
  }
12
}

Und dann am Poti drehen.
Deine LED müssen sich verändern

von AVR (Gast)


Lesenswert?

ADC Initialisierung hat in ReadChanel Funktion nicht verloren.
Eine ADCinit Funktion wo Prescaler und Referenzspannung  initialisiert 
sind und ADC aktiviert ist, ist viel sinnvoller.
Außerdem braucht du den ADC nicht immer wieder deaktivieren.
Messen möchtest du ständig, oder?
Beispiel:
1
void ADCInit(void)
2
{
3
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Frequenzvorteiler
4
// setzen auf 128 (1) und ADC aktivieren (1)
5
ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
6
7
}
8
9
10
uint16_t ReadChannel(uint8_t mux)
11
{
12
 ADMUX &=~(1<<MUX0)|(1<<MUX1)|(1<<MUX2)|(1<<MUX3)|(1<<MUX4)); // nur MUX0 bis MUX4 löschen, REFS0 und REFS1 bleibt unberührt!
13
 ADMUX |= mux; // Kanal waehlen
14
 ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
15
      while ( ADCSRA & (1<<ADSC) ) {
16
      ; // auf Abschluss der Konvertierung warten
17
      }
18
      result = ADCW; 
19
}
20
21
int main()
22
{
23
  unsigned int adc_links;
24
25
  DDRB = 0xFF;
26
  PORTB = 0x00;
27
  DDRA = 0x00; // ADC-Pins als Eingang konfigurieren!
28
  PORTB = 0x00; // Ohne Pull-Ups!
29
  ADCInit();
30
31
  while( 1 ) {
32
33
    adc_links = ReadChannel(1);
34
    PORTB = adc_links / 4;     // 0 .. 1024; / 4 damit es in 8 Bit passt
35
  }
36
}

von Karl H. (kbuchegg)


Lesenswert?

AVR schrieb:
> ADC Initialisierung hat in ReadChanel Funktion nicht verloren.

Lass uns erst mal mit einer getesteten Funktion abklären, ob ein 
Hardwareproblem vorliegt.

von M. G. (elch)


Lesenswert?

Ich habe zwar gerade keinen solchen Aufbau da (und auch kein Display) , 
aber am Wochenende werd ich mir sowas mal bauen.
Port B war zwar anscheinend nicht als Ausgang eingestellt, aber 
geleuchtet haben die LED's trotzdem ^^
Ich hab den Port jetzt eingestellt und der einzige Unterschied ist die 
Helligkeit der LED's
Koennte es sein das sich der ADC mit dem PWM in die quere kommt?
Ich versuche naemlich zwei Servos mit den Werten aus dem ADC zu steuern.
Mit freundlichen Gruessen

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:
> Ich habe zwar gerade keinen solchen Aufbau da (und auch kein Display) ,
> aber am Wochenende werd ich mir sowas mal bauen.
> Port B war zwar anscheinend nicht als Ausgang eingestellt, aber
> geleuchtet haben die LED's trotzdem ^^
> Ich hab den Port jetzt eingestellt und der einzige Unterschied ist die
> Helligkeit der LED's

Klar.
Du hast am Port, der als Eingang geschaltet ist, die Pullups 
eingeschaltet. Und über diese Pullups wurden dann die LED versorgt.

> Koennte es sein das sich der ADC mit dem PWM in die quere kommt?

Wo kommt da jetzt plötzlich eine PWM her?

> Ich versuche naemlich zwei Servos mit den Werten aus dem ADC zu steuern.

Hör mal.
Ich spiel mich da jetzt nicht stundenlang, nur damit ich überlege, 
welche Fehler in Code sein könnten, den ich nicht sehen kann.

Ist das der Code den du laufen lässt, oder ist er es nicht?
Woher weißt du, dass der ADC immer 1023 liefert?

von M. G. (elch)


Angehängte Dateien:

Lesenswert?

Tut mir leid , da die PWM ohne Probleme funktioniert dachte ich es waere 
nicht wichtig fuer mein Problem.
Im Anhang befindet sich der komplette Code den ich momentan zum Laufen 
bringen will, allerdings habe ich auch folgenden Code ausprobiert.
Hier habe ich wirklich NUR die ADC Funktion kompiliert , mit dem selben 
Ergebnis. Demnach muss der Fehler am ADC liegen.
Das der ADC 1023 ausgibt habe ich durch Annaeherungen erreicht.
Beim ausfuehren des folgenden Codes leuchten beide LED's die an PB0 und 
PB1 sind, auch wenn nichts an den entsprechenden ADC kanal angeschlossen 
ist.

1
#define F_CPU 16000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
//Variablen :
7
uint16_t adc_links=0;  //Spannung des linken Infrarottransistors
8
uint16_t adc_rechts=0;  //Spannung des rechten Infrarottransistors  
9
uint16_t adc_oben=0;  //Spannung des oberen Infrarottransistors
10
uint16_t adc_unten=0;   //Spannung des unteren Infrarottransistors
11
12
13
14
15
16
uint16_t ReadChannel(uint8_t mux)
17
    {
18
      uint8_t i;
19
      uint16_t result=0;
20
      ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Frequenzvorteiler
21
      // setzen auf 128 (1) und ADC aktivieren (1)
22
      ADMUX = mux; // Kanal waehlen
23
      ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
24
      /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
25
      also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
26
      ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
27
      while ( ADCSRA & (1<<ADSC) ) {
28
      ; // auf Abschluss der Konvertierung warten
29
      }
30
      result = ADCW; // ADCW muss einmal gelesen werden,
31
      // sonst wird Ergebnis der nächsten Wandlung
32
      // nicht übernommen.
33
      /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
34
      result = 0;
35
      for( i=0; i<4; i++ )
36
      {
37
      ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
38
      while ( ADCSRA & (1<<ADSC) ) {
39
      ; // auf Abschluss der Konvertierung warten
40
      }
41
      result += ADCW; // Wandlungsergebnisse aufaddieren
42
      }
43
      ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
44
      result /= 4; // Summe durch vier teilen = arithm. Mittelwert
45
      return result;
46
    }
47
48
int main()
49
{
50
51
    
52
    DDRA=0x00;
53
    DDRB=0xff;
54
    while(1)
55
   {
56
    //Auslesen der ADC Kanaele:
57
    adc_links=0;
58
    
59
    adc_links=ReadChannel(0);
60
    _delay_us(120);
61
    
62
    
63
///////////////////////////////////////////////TEST
64
    if(adc_links==1023)PORTB|=(1<<PIN0);
65
    if(adc_links!=1023)PORTB&=~(1<<PIN0);
66
    
67
68
////////////////////////////////////////////////////
69
  }
70
71
}

von spess53 (Gast)


Lesenswert?

Hi

Hast du mal die Spannung an AREF gemessen?

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:

> Das der ADC 1023 ausgibt habe ich durch Annaeherungen erreicht.
> Beim ausfuehren des folgenden Codes leuchten beide LED's die an PB0 und
> PB1 sind,

Beide?

Die an PB1 schaltest du nie auf 1.
D.h. deine LED leuchten, wenn der Ausgangspin auf 0 steht.

Den Ausgangspin für PB0 setzt du aber dann auf 0, wenn der ADC einen 
Wert ungleich 1023 liefert. Und damit ist doch alles in Ordnung.
Du hast einfach nur die Bedeutung deiner Kontrolleds fehlinterpretiert.

Wenn der ADC einen Wert von 1023 liefert, dann geht die LED aus und 
nicht ein!

Leg mal +5V an den ADC Eingang (ändere im Programm noch die 1023 auf 
1020, damit sich kleine Abweichungen nicht auswirken) und du wirst 
sehen, dass die LED dann ausgeht.

Und mach die Abfrage besser so
1
    if( adc_links > 1020 )
2
      PORTB |= (1<<PIN0);
3
    else
4
      PORTB &= ~(1<<PIN0);
dann hast du den Grenzwert nur an einer Stelle im Programm und musst 
nicht aufpassen, dass 2 if auf den selben Wert prüfen.
AUch solltest du mit == sehr vorsichtig sein. Es ist völlig normal, dass 
der ADC Wert immer ein klein wenig schwankt. Und damit ist == eine 
schlechte Wahl.

von M. G. (elch)


Lesenswert?

Sorry, kleiner Fehler meinerseits, da bin ich durcheinandergekommen.
Ich habe anfangs beide LED's benutzt um die Werte der Kanaele zu 
ermitteln(so wie im Gesamtcode).
Mittlerweile leuchtet nur noch die an B0.

von Karl H. (kbuchegg)


Lesenswert?

OK.
Wie genau sind deine LED verschaltet?

(Das ganze Sache wäre so viel einfacher, wenn man sich den tatsächlichen 
Wert vom ADC ansehen könnte und nicht über Umwege erschliessen muss)

von M. G. (elch)


Lesenswert?

Die LED's sind mit dem positiven Fuss direkt an den Amega angeschlossen, 
der negative geht ueber einen widerstand zum negativen Anschluss der 
Spannungsquelle (Spannungsregulator).

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:
> Die LED's sind mit dem positiven Fuss direkt an den Amega angeschlossen,
> der negative geht ueber einen widerstand zum negativen Anschluss der
> Spannungsquelle (Spannungsregulator).

Hmm.
Das ist schlecht.
Jetzt weiß ich auch nicht mehr weiter.
Die ADC Routine aus dem Tut ist getestet und in Ordnung.
Das einzige was mir jetzt noch einfällt ist der Frequenzvorteiler. Den 
hab ich nicht nachgerechnet, ob du damit im erlaubten Bereich bist.

von M. G. (elch)


Lesenswert?

Laut Tutorial benoetigt der ADC eine Frequenz zwischen 50 und 200 kHz,
also 50000 und 200000 Hz.
Mein Atmega arbeitet mit 16Mhz also 16000000 Hz.
16000000/50000  = 320
16000000/200000 = 80
Also ein Prescaler zwischen 80 und 320.
Das Einzige was da in Frage kommt ist 128 also die Bits ADPS2, ADPS1 und 
ADPS0.
Kommt das hin ?

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:

> Kommt das hin ?

Kommt hin.

von spess53 (Gast)


Lesenswert?

Hi

>Kommt das hin ?

Ja.
Ich wiederhole mich ungern, aber hast du die Referenzspannung mal 
gemessen?

MfG Spess

von M. G. (elch)


Lesenswert?

Mit dem Code von gestern hatte ich ja eine normale Referenzspannung, als 
ich gerade eben nochmal nachgemessen habe nicht mehr.
Jetzt liegt auf Aref keine Spannung mehr.
Ausserdem gibt mein Spannungsregulator nur noch 4,86 Volt her ...
Ich werd mal Versuchen diesen zu wechseln.

von spess53 (Gast)


Lesenswert?

Hi

>Jetzt liegt auf Aref keine Spannung mehr.

Das hatte ich befürchtet. Überprüfe mal, ob da nicht ein Kurzschluss von 
VREF nach Masse ist.

MfG Spess

von M. G. (elch)


Lesenswert?

Ich konnte zwar keinen kurzschluss ausmachen , allerdings habe ich 
anscheinend trotzdem einen beseitigt.
An Aref liegen nun 2,3 Volt an , und die LED's reagieren.
Nur tun sie das schon bei Spannungen unter einem Volt.
Mit freundlichen Gruessen.

von M. G. (elch)


Lesenswert?

Das Problem koennte diesmal an der Hardware liegen .
Ich werden morgen ein paar Modifizierungen vornehmen und es ernuet 
versuchen.
Allerdings scheint der ADC zu funktionieren.
Vielen Dank schonmal an alle die bis jetzt geholfen haben!

von M. G. (elch)


Lesenswert?

Ok, der ADC scheint wirklich zu funktionieren.
An Aref liegt nun entweder 2,5 Volt oder 5 volt an, je nachdem ob die 
interne Referenzspannung oder Avcc als Referenzspannung eingestellt ist.
Wenn die Sensoren (Phototransistoren) nicht an den Atmega angeschlossen 
sind, dann bleibt die LED, beim Ausfuehren des oberen Codes , aus.
Wenn ich den Phototransistor anschliesse faengt die LED an wild zu 
blinken, als wuerde sie ein PWM Signal ausgeben.
Woran koennte das liegen?
Es scheint als blinkt die LED langsamer wenn eine hoehere Spannung am 
Phototransistor anliegt.

von Thomas (kosmos)


Lesenswert?

es wurde ja schon gesagt das der ADC Wert schwank, 5V mit 10bit 
aufgelöst sind knapp 5mV Genauigkeit.

Du kannst die Wandlerfrequenz verringern, Mittelwerte aus mehreren 
Messungen verwenden oder halt die Schaltschwelle anderst 
programmieren.Dann wirken sich die Schwankungen der ADC Messung bzw. 
deines zugeführten Signals nicht so stark aus.

z.B.
Wenn Wert 1 > 1019 und Wert 2 >1019 prüfe auf Differenz...
Wert 1 =1022 und Wert 2 =1024; Differenz < 5 also LED nicht einschalten
Wert 1 =1018 und Wert 2 =1024; Differenz > 5 also LED einschalten.
Im Bereich über 1019 wird also nur auf eine Wertänderung > 5 bzw. >25mV 
reagiert.

Probiere es mal wie folgt. Poti an ADC und 10 LEDs an an 2 Port, nach 
der Wandlung gibts du das ADCL Register an Port 2 und ADCH Register an 
Port 1 aus und siehst wie die letzen Bits wackeln jetzt kann du deine 
Glättungsroutine verfeinern.

von M. G. (elch)


Lesenswert?

Wie gesagt, das mit dem Poti werde ich wohl morgen oder uebermorgen mal 
probieren.
Allerdings ist der ADC im Moment komischer Weise sehr sensibel.
Wenn ich das Kabel das zum ADC pin fuehrt nur beruehre , leuchtet die 
LED.
Und das auch wenn keine Spannung auf dem Kabel ist, und das Kabel eine 
Isolierung hat. Also reagiert der ADC auf wenige millivolt, obwohl die 
LED erst bei 5 Volt leuchten sollte, oder?

Ich habe gerade Aref nochmal nachgemessen, und die Spannung an Aref ist 
jetzt -5 Volt , obwohl ich AVCC als Referenz eingestellt habe, wo + 5 
Volt anliegen.
Ist das normal?
Wenn nicht dann liegt da warscheinlich das Problem.

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:
> Wie gesagt, das mit dem Poti werde ich wohl morgen oder uebermorgen mal
> probieren.

Solltest du unbedingt.
Und su solltest dir auch eine Möglichkeit schaffen, wie du den 
Zahlenwert direkt sichtbar machen kannst. 8 LED, LCD, UART
Auf Dauer ist nämlich dieses 1 Led schaltet bei einem Grenzwert ziemlich 
mühsam um daraus im Umkehrschluss den ADC Wert zu erraten

> Allerdings ist der ADC im Moment komischer Weise sehr sensibel.
> Wenn ich das Kabel das zum ADC pin fuehrt nur beruehre , leuchtet die
> LED.
> Und das auch wenn keine Spannung auf dem Kabel ist, und das Kabel eine
> Isolierung hat. Also reagiert der ADC auf wenige millivolt, obwohl die
> LED erst bei 5 Volt leuchten sollte, oder?

Wenn 5V in 1024 Stufen aufgelöst werden, dann hat jede Stufe 5/1024 V. 
Das ist etwas weniger als 5mV. Und 5mV sind nicht viel.

> Ich habe gerade Aref nochmal nachgemessen, und die Spannung an Aref ist
> jetzt -5 Volt , obwohl ich AVCC als Referenz eingestellt habe, wo + 5
> Volt anliegen.
> Ist das normal?

Du hast dein Voltmeter falsch rum angeschlossen

von M. G. (elch)


Lesenswert?

Ich bin mir ziemlich Sicher , ich habe extra nochmal nachgemessen.
Wenn ich das Kabel der Positiven Buchse des Voltmeters(V) an Aref halte, 
und das andere Kabel (COM) an GND, wird keine Spannung gemessen.
Wenn ich V allerdings an +5Volt halte und das andere Kabel(COM) an Aref, 
messe ich 5 Volt.

von Thomas (kosmos)


Lesenswert?

Spendier mal dem Eingang einen Pulldown-Widerstand von 10 kOhm gegen 
Masse, damit er nicht offen hängt.

von Gast 10 (Gast)


Lesenswert?

Miss mit einem Oszi mal die Referenz-Spannung. In einem Fall mußte
ein Kananl mit Uref = AVcc, ein anderer mit Uref = 1,2V (interne Ref)
arbeiten. Umschalten von "kleiner" nach "großer" Uref problemlos,
1..2 ms warten reichte locker. Beim Umschalten von Uref=AVcc nach 
interner
Ref. mehr als 10ms...20ms! Sehr interessante Messergebnisse in dieser 
Zeit!

Schau auch mal dieses "Eck" an.

von M. G. (elch)


Lesenswert?

>Ich habe gerade Aref nochmal nachgemessen, und die Spannung an Aref ist
>jetzt -5 Volt

Das wuerde auch erklaeren warum die test LED auch ohne Spannung leuchtet 
( 0 Volt) sind mehr als -5

von Karl H. (kbuchegg)


Lesenswert?

Wie bitte soll sich der Mega intern eine Referenzspannung von -5V 
generieren?
Das kann er nicht. Er hat die dazu nötige Ladungspumpe nicht mit an 
Bord. Physik lässt sich nicht überlisten.

> Wenn ich das Kabel der Positiven Buchse des Voltmeters(V) an Aref
> halte, und das andere Kabel (COM) an GND, wird keine Spannung
> gemessen.

Also 0V

> Wenn ich V allerdings an +5Volt halte und das andere Kabel(COM)
> an Aref, messe ich 5 Volt.

d.h. du hast von Aref zu +5V eine Spannungsdifferenz von 5V.
5 - 5 ist 0. Dein Aref ist 0V. In Übereinstimmung zur ersten Messung

von Thomas (kosmos)


Lesenswert?

vielleicht indem man VCC und GND oder AVCC und GND vertauscht. Ist der 
Magic Smoke aus dem IC ausgetreten, den bekommt man schlecht wieder rein 
;-) und dann ist der Chip hin.

von Karl H. (kbuchegg)


Lesenswert?

> Wenn ich das Kabel das zum ADC pin fuehrt nur beruehre ,
> leuchtet die LED.
> Und das auch wenn keine Spannung auf dem Kabel ist, und das
> Kabel eine Isolierung hat.

Ein Kabel, dessen Ende frei in der Luft hängt wirkt wie eine Antenne. 
Rund um uns schwirren jede Menge elektromagnetische Wellen durch die 
Luft, die in einer Antenne eine Spannung induzieren. Eine noch viel 
bessere Antenne ist aber der menschliche Körper. Du, als Person, fängst 
die 50Hz der ganzen 230V Leitungen rund um dich auf und wenn du das 
Kabel berührst, wird diese induzierte Spannung auf das Kabel 
weitergegeben. Und der ADC misst das dann.
Wenn du mit deinem Mega irgendwann einmal einen Frequenzzähler 
programmierst, wirst du sehen, dass das Berühren des offenen Eingangs 
ein wunderschönes 50Hz Signal liefert.

von Karl H. (kbuchegg)


Lesenswert?

M. G. schrieb:

> Ausserdem gibt mein Spannungsregulator nur noch 4,86 Volt her ...

Das ist schon ok.
Den 7805 kannst du ruhig nehmen, so lange die Spannung stabil ist.
Wie heißt es so schön: Wer misst, misst auch viel Mist.

Dein Messgerät wird einen kleinen Fehler haben, der 7805 wird nicht 
genau 5V haben. Du hast Übergangswiderstände. etc.

die 0.14V Abweichung können ein paar Ursachen haben, die nicht 
bedenklich sind. Und 0.14V sind in der Digitaltechnik praktisch gar 
nichts.

Wichtig ist, dass die Spannung stabil ist.

von Karl H. (kbuchegg)


Lesenswert?

WIe sieht eigentlich dein Aufbau aus?
Benutzt du eine fertige Platine? Ein Steckbrett?
Besonders billige Steckbretter sind dafür bekannt, dass sich die 
Wackelkontaktquote im Lauf der Zeit erhöht, um es mal freundlich 
auszudrücken.

von M. G. (elch)


Lesenswert?

Mitlerweile liegen wieder 5 Volt an Aref an ^^
Ausserdem funktioniert der ADC nun wirklich.
Solang keine weiteren Probleme mit dem ADC mehr auftreten bedank ich 
mich schonmal herzlich bei allen die mir hier geholfen haben !

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.