Forum: Compiler & IDEs Mehrere AD-Werte auslesen


von lukas (Gast)


Lesenswert?

Hi Leute,

messe bei einem Fensterhebermotor den Aufnahmestrom, bzw. messe eine 
Spannung an einem Shunt-Widerstand.
Da ich einen für die Fahrerseite und einen für die Beifahrerseite 
benötige, muss ich zwei AD-Werte auslesen. Diese Spannungen liegen an 
PINC0 und PINC1.
Habe das Problem, dass egal an welchem AD-Eingang die Spannung über den 
eingestellten Wert von Binär 128 übersteigt, beide Motoren abgeschaltet 
werden. Ich denke es liegt daran, dass ich für beide Spannungen das ADC 
Register abrufe.
Die Kanalwahl funktioniert ja einwandfrei sobald ich jeweils den anderen 
auskommentiere.
Irgendwie überschreibt ein AD-Eingang jeweils eine "wert"-Variable, weil 
er ja schließlich auch das ADC-Register überschreibt.
Ich brauch schnelle Hilfe und wäre sehr dankbar dafür.

Hab das Hauptprogramm mal angehängt:



    int main ()
{
  DDRC=0b00000000;
  DDRD=0b11001100;

  ADCSRA=0b11000001;
  while (bit_is_set(ADCSR,6));     // Warten bis Initialisierungsmessung 
erfolgt ist

    while(1)
  {
    ADMUX&=~(1<<MUX0);
    ADCSRA|=(1<<ADSC);
    while (bit_is_set(ADCSRA,6));
    wert1=ADC;

    ADMUX|=(1<<MUX0);
    ADCSRA|=(1<<ADSC);
    while (bit_is_set(ADCSRA,6));
    wert2=ADC;


    if (wert1<128) {endschalter_fahrerseite=1;} else 
{endschalter_fahrerseite=0;}
    if (wert2<128) {endschalter_beifahrerseite=1;} else 
{endschalter_beifahrerseite=0;}


    fenster_fahrerseite();
    fenster_beifahrerseite();
  }
}

von Edi R. (edi_r)


Lesenswert?

Nachdem hier noch keiner geantwortet hat, probier ich es mal.

Auf Anhieb habe ich nichts gesehen, was mir verdächtig vorgekommen wäre. 
Möglicherweise steckt der Fehler ganz woanders. Es wäre vielleicht 
nützlich, wenn Du uns den gesamten Quellcode zeigst. Außerdem ist es 
immer sinnvoll, wenn Du auch den Controllertyp angibst. Und nachdem es 
offensichtlich um einen Atmel-Controller geht, sind auch die 
Fuse-Einstellungen wichtig.

lukas schrieb:
> ...eingestellten Wert von Binär 128...

Das sind aber dezimal 128, nicht binär.

lukas schrieb:
> Ich denke es liegt daran, dass ich für beide Spannungen das ADC
> Register abrufe.

Daran kann es nicht liegen, weil dazwischen ja eine neue Wandlung 
vorgenommen wird.

von lukas (Gast)


Lesenswert?

hi,
ja sorry war dezimal 128 gemeint xD
und es handelt sich um ein atmega8.
der rest des programmes ist nicht wichtig. und fuse-einstellungen
sind alle richtig eingestellt. es geht ja nur rein um die AD-Wandlung
zweier eingänge. ich muss die zwei werte irgendwie zwischenspeichern.
es funktioniert ja auch soweit mit der kanalwahl und mit der wandlung 
wenn ich es nur mit einem AD-Eingang zu tun habe. aber sobald ich die 
werte zweier eingänge zwischenspeichern will, klappt es nicht, weil ja 
das ergebnis der wandlung immer in das ADC-Register geschrieben wird. 
man switcht ja nur zwischen den eingängen hin und her.
kann mir denn da keiner so wirklich helfen?
geht quasi nur um das hier:

while(1)
{
    ADMUX&=~(1<<MUX0);
    ADCSRA|=(1<<ADSC);
    while (bit_is_set(ADCSRA,6));
    wert1=ADC;

    ADMUX|=(1<<MUX0);
    ADCSRA|=(1<<ADSC);
    while (bit_is_set(ADCSRA,6));
    wert2=ADC;
}

muss doch eine lösung geben, wie ich die werte zweier eingänge 
längerfristig speichern kann, ohne das der wert gleich vom anderen 
überschrieben wird.

mfg

von Karl H. (kbuchegg)


Lesenswert?

lukas schrieb:

> muss doch eine lösung geben, wie ich die werte zweier eingänge
> längerfristig speichern kann, ohne das der wert gleich vom anderen
> überschrieben wird.

Das ist nicht das Problem.

So wie es aussieht(*), kommt der ADC mit der schnellen Umschaltung nicht 
zurecht. Das kann zb sein, weil sich die interne Sample&Hold Stufe nicht 
schnell genug auf den Spannungspegel des anderen Kanals umstellen kann.

Schneller Ad-Hoc Ansatz:
Wandle jeden Kanal 2 mal und nimm nur das 2-te Ergebnis. Dazu wäre es 
natürlich vernünftig, aus der ADC Abfrage eine Funktion zu machen, damit 
man nicht immer wieder den eigentlich identischen Code hat.

Das hier
  ADCSRA=0b11000001;
schlüssle ich jetzt sicher nicht nach den Bits auf, um zu sehen, ob 
nicht deine Wandelrate zu hoch eingestellt ist.
Schau dir im AVR-GCC-Tutorial an, wie man sowas auch lesbarer 
schreiben kann. Dort findest du auch ADC-Routinen, die die ADC-Benutzung 
sauber in Funktionen aufgliedern, so dass das ganze einfach benutzbar 
wird.


(*) natürlich nur unter der Voraussetzung, dass der von dir nicht 
gezeigte Rest des Programmes soweit in Ordnung ist. In der 
Verarbeitungskette Eingabe-Verarbeitung-Ausgabe gibt es nun mal 3 
Stellen, an denen sich Fehler verstecken können, auch wenn sich alle 
Welt meistens nur auf den 2ten Schritt stürzt.

von Julian B. (julinho)


Lesenswert?

Ich verwende bei meinen ADC-Routinen immer das ADIF-Bit um festzustellen 
wann die Wandlung fertig ist, das klappt irgendwie besser als mit dem 
ADSC-Bit. Das ADIF-Bit muß nach jeder Wandlung wieder gelöscht werden.

von lukas (Gast)


Lesenswert?

Danke!!!

Ich hab einfach mal mit der ersten idee angefangen, die eingänge jeweils 
zweimal einzulesen und es funktioniert!! genial.
danke jungs

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.