Forum: Compiler & IDEs ADC-Wert immer gleich


von Daniel (Gast)


Lesenswert?

N'abend,
ich hab ein Problem bei einem Programm, wo ich den ADC verwende, auf 
einem ATMEGA32.
Hier erstmal das Programm:
1
#include <stdio.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/pgmspace.h>
5
#include <stdlib.h>
6
7
#include "uart-routines.h"
8
9
//ADC
10
uint16_t ADC_Read(uint8_t channel)
11
{
12
  uint8_t i;
13
  uint16_t result=0;
14
15
  ADMUX  = channel;
16
17
  ADCSRA |= ((1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0));  //ADC aktivieren; Teilungsfaktor: 128 (ADPS*)
18
  
19
  ADCSRA |= (1<<ADSC);                      //ADC einmal starten um Dummy zu lesen, sonst passiert nix
20
  
21
  result = ADCW;                          //ADCW einmal lesen sonst beim naechsten mal keine Uebernahme
22
  
23
  result = 0;
24
  
25
  for(i=0;i<4;i++)
26
  {
27
    ADCSRA |= (1<<ADSC);                    //single conversion
28
    while( ADCSRA & (1<<ADSC) )
29
    {
30
      ;                            //Warten auf Konvertierung
31
    }
32
    result += ADCW;                        //Wandlungsergebnis aufaddieren
33
  }
34
  
35
  ADCSRA &= ~(1<<ADEN);                      //ADC deaktivieren
36
  
37
  result = result/4;                        //Wandlungsergebnis durch Anzahl Messungen
38
  
39
  return result;
40
}
41
42
int main (void)
43
{   
44
  uint16_t bat_mess_wert;
45
  char string[20];
46
  sei();
47
  uart_init(UART_BAUD_SELECT(9600,F_CPU));
48
49
  bat_mess_wert = ADC_Read(0);
50
  itoa(bat_mess_wert,string,10);
51
  uart_puts(string);
52
  uart_puts_P("\r\n");
53
        return (0);
54
55
}
Ich will damit die Spannung eines Akkus messen, zur Zeit haengt er auf 
5V mit einem Spannungsteiler 2*10k.
Externe Referenzspannung ist 3,3V.
Jetzt sollte mir ueber UART theoretisch nach Formel: 
ADC=(U_in*1024)/U_Ref=(2,5*1024)/3,3=775 angezeigt werden, aber ich 
bekomme nur 460+/-5 angezeigt.
Hab ich jetzt einen Denkfehler oder stimmt was mit dem ADC nicht?
Vielen Danke
Daniel

von John S. (linux_80)


Lesenswert?

Wird der ADC-Eingang auch auf Eingang gestellt, oder hab ich das 
übersehen ?

von Daniel (Gast)


Lesenswert?

kay, herzlichen danke,
hab jetzt mit:
DDRA = 0x00;
PORTA = 0x1;
den Eingangs-Pull-Up aktiviert und krieg jetzt 1023+/-1 angezeigt, das 
sieht schon besser aus.
Leider hab ich den Akku nicht da, kann also nicht testen ob bei 
Spannungsverringerung dich der Adc wert ändert, aber das sollte jetzt ja 
passen oder?

von John S. (linux_80)


Lesenswert?

Mit Pullup kommt der max. Wert raus, könnte passen, ohne Pullup sollte 
dann gegen 0 gehen.
Wenn die Ref aber nur 3.3V hat, der Pullup aber 5V liefert, weiss ich 
nicht ob das so gut für den ADC ist.

Testen kannst Du mit einem Poti, oder einfach 2 Widerständen.

von Stefan E. (sternst)


Lesenswert?

@ Daniel:

Ein fehlendes "DDRA=" ist sicher nicht das Problem, denn da du den Pin 
nirgendwo auf Ausgang stellst, ist er bereits ein Eingang.

So nebenbei:
Deine Dummy-Messung geht als erste Messung mit in das Ergebnis ein, weil 
du nicht auf das Ende dieser Messung wartest.

von Oliver (Gast)


Lesenswert?

Lass das mit dem dummy-lesen einfach weg. Das steht zwar so im Tutorial, 
ist aber nur erforderlich, wenn auch der allererste Wert nach 
Power-On-Reset schon fehlerfrei sein muß.

Oliver

von Daniel (Gast)


Lesenswert?

Jetzt bin ich ein bisschen verwirrt, also die Routine ist der im 
GCC-Tutorial nachempfunden, da steht das so drin, deswegen verwundert 
mich das die Dummy-Abfrage so nicht funktionieren soll.
Also muss ich auch nicht den PULL-UP aktivieren?
Wie gesagt, wenn ich den Pull-up deaktiviere komm ich auf einen Wert von 
460.
Meine Anwendung soll sein, ich werd einen Lithium-Ionen Akku 
anschliessen der hat voll aufgeladen 3,7V, jetzt will ich mit dem ADC 
feststellen wie weit der entladen ist. Die Spannung greif ich ueber 
einen Spannungsteiler 2*10k ab, so das ich als abgegriffene Spannung 
3,7V/2 haben sollte.
Da ich den Akku bis jetzt noch nicht da hab, hab ich 5V Versorgung 
genommen, auch uebers Spannungsteiler 2*10k, sollten 2,5V rauskommen, 
kommen auch, das mit der ADC Formel: ADC=2,5*1024/3,3=775 sollten 
angezeigt werden.
Wie gesagt wird aber nicht?

Gruß
Daniel

von Stefan E. (sternst)


Lesenswert?

Daniel wrote:
> Jetzt bin ich ein bisschen verwirrt, also die Routine ist der im
> GCC-Tutorial nachempfunden, da steht das so drin,

Nein, dort wird auf die Dummy-Messung gewartet.

Du solltest als erstes mal nachmessen, welche Spannungen du denn 
tatsächlich an Vref und am ADC-Eingang hast.

von Oliver (Gast)


Lesenswert?

>Hab ich jetzt einen Denkfehler oder stimmt was mit dem ADC nicht?

Ich habe schonmal einen Mega32 mit zerschossenenm ADC-Eingang, der 
direkt an 5V 200mA gezogen hat. Der würde dir natürlich die 
Eingangspannung vom Spannungsteiler in den Keller ziehen. Das sollte 
sich aber schnell nachmessen lassen.

Der ADC selber hat dabei immer noch richtig gemessen, ohne Vorwiderstand 
stimmte alles. Nur der Stromverbrauch war dann etwas hoch :-)

Oliver

von Oliver (Gast)


Lesenswert?

> Jetzt bin ich ein bisschen verwirrt, also die Routine ist der im
> GCC-Tutorial nachempfunden, da steht das so drin,

Wie schon geschrieben wurde, steht da was anderes.
Der Kommentar in deiner Version
1
//ADC einmal starten um Dummy zu lesen, sonst passiert nix
ist auf jeden Fall verkehrt. Der dummy-read ist ein ganz normlaes 
Auslesen des ADC's, es kann nur vorkommen, daß der erste gelesene Wert 
nach einer bestimmten Aktion fehlerhaft ist. Insofern musst du da auch 
ganz normal auf das Ende der Konversion warten.
Welche Aktionen zu fehlerhaften Werten führen, steht im Datenblatt. Ob 
gewollt oder nicht, unterscheiden sich die Datenblätter der 
verschiedenen AVR's da etwas. Das des Mega32 lese ich so, daß in deinem 
Fall kein dummy-Read erforderlich ist. Solange kein 
timimg-Problemcauftritt, schadet der dummy-read natürlich nicht.

Oliver

von Daniel (Gast)


Lesenswert?

also danke das mit dem dummy-Read hab ich verbessert,
so hab dann mal an Vref und ADC-Eingang gemessen:
Vref=3,29V
Vadc=2,49V
sollten nach Formel: 779 geben, krieg aber jetzt 450 ohne Pullup.

von Johannes M. (johnny-m)


Lesenswert?

Warum gibst Du überhaupt die Interrupts frei? Wenn Du keine Interrupts 
nutzt, lass das sei() weg!

von Johannes M. (johnny-m)


Lesenswert?

BTW: AVCC korrekt angeschlossen?

von Daniel (Gast)


Lesenswert?

sei() brauch ich fuer den uart und AVCC hat 3,29V mit nem 100nF gegen 
Masse.

von Johannes M. (johnny-m)


Lesenswert?

Du betreibst den AVR mit 3,3 V? Warum dann die externe Referenz? AVCC 
kann man auch intern als Referenz wählen...

von Daniel (Gast)


Lesenswert?

jo betreib ihn mit 3,3V, hab mal umgestellt:
  ADMUX |= (1<<REFS0);                            //AVCC als 
Spannungsreferenz
jetzt wieder 450 als Ausgabe.

von Karl H. (kbuchegg)


Lesenswert?

Hmmm

Wie sieht dein Programm jetzt aus?

Kannst du mal ein Poti an den ADC Eingang hängen, den ADC kontinuierlich 
in einer Schleife auslesen (und natürlich den Wert anzeigen) und mal 
nachsehen, ob sich der Wert mit Drehen am Poti verändern lässt?

von Michael 9. (michael93) Benutzerseite


Lesenswert?

Ein Li-Ion Akku hat voll aufgeladen eine Spannung von 4,2 V pro Zelle. 
Und an AVCC muss die selbe Spannung liegen wie an den restichen VCC 
pins.

Michael

von Daniel (Gast)


Lesenswert?

Sorry Leute, ich muss mich entschuldigen, ich bin manchmal so ein Depp, 
ich hab es leider voll verrissen, Es war der falsche Pin^^ Ich hin gar 
nicht an PORTA.0 sondern an 7. Bin da auch nicht draufgekommen weil an 
der A.0 auch was hing, na gut danke fuer die zahlreichen Tipps und sorry 
bezueglich meiner Bloedheit
Gruß
Daniel

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.