Hilfe bei einem kleinen C-Programm (AD-Wandler)

Gast #502700
Lesenswert?

Hy,
habe das Programm in AVR Studio geschrieben und ist für den Mega8 
bestimmt. Auf der Platine habe ich alles nachgemessen und das stimmt 
soweit.
Das Programm soll Bits setzen wenn der ADC1 und der ADC2 
unterschiedliche Werte haben. Leider werden die Bits nicht gesetzt. Kann 
mir vielleicht jemand weiterhelfe? Wäre super.

#include <avr/io.h>

void reset();

int main (void) {
    reset();

    int adclow;
    int vertikallinks;
    int vertikalrechts;
  while(1)
  {

    ADMUX= 1;
          ADCSRA = (1<<ADSC);     //Start der Wandlung
    while ( ADCSRA & (1<<ADSC) ) // auf Abschluss der     Konvertierung 
warten
    {
    }
    adclow=ADCL;
    vertikallinks=ADCH;

    ADMUX=2;
    ADCSRA = (1<<ADSC);     //Start der Wandlung
    while ( ADCSRA & (1<<ADSC) ) // auf Abschluss der Konvertierung 
warten
    {
    }
    adclow=ADCL;
    vertikalrechts=ADCH;
    int ergebnis=vertikallinks-vertikalrechts;
    if(-1>ergebnis||1<ergebnis)
    {
      if(-1>ergebnis)
      {
        PORTB = (1<<PB2) | (0<<PB3);
      }
      else
      {
        PORTB = (0<<PB2) | (1<<PB3);
      }
    }
    else
    {
    PORTB=(0<<PB2)|(0<<PB3);
    }
  }  main();

   return 0;
}


void reset(){
        DDRD= 0xff;
    DDRB= 0x00;

    ADMUX= (0<<REFS1)|(1<<REFS0)|(1<<ADLAR);
    ADCSRA= (1<<ADEN)|(1<<ADPS2)|(ADPS1)|(ADPS0);
}
Gast #502711
Lesenswert?

Du vergleichst ja nur die oberen 8 Bit (ADCH) und verwirfst die unteren 
8 Bit (ADCL).

Dementsprechend hast du nur eine Chance, wenn wenn sich die 
digitalisierten Werte genügend unterscheiden.

Wie wäre es mit einer Nutzung der vollen Digitalisierungswerte?

    adclow = ADCL;
    vertikallinks = ADCH;
    vertikallinks = (vertikallinks << 8) | adclow;
    ...
    adclow = ADCL;
    vertikalrechts = ADCH;
    vertikalrechts = (vertikalrechts << 8) | adclow;
    ...
#502719
Lesenswert?

Was mir auf die Schnelle auffällt:

Du konfigurierst hier

 ADCSRA= (1<<ADEN)|(1<<ADPS2)|(ADPS1)|(ADPS0);

den ADC. Leider zerstörst du dir hier

    ADCSRA = (1<<ADSC);     //Start der Wandlung

die Konfiguration. Wenn du dem Register ADCSRA etwas
zuweist, wird das komplette Register neu beschrieben,
nicht nur das ADSC Bit

  ADCSRA |= ( 1 << ADSC );


Mit ADMUX machst du genau den gleichen Fehler.

Eine extrem gute Idee ist es auch, sich einfach nur den
eingelesenen Wert einmal ausgeben zu lassen. Zuerst
mit dem einen Kanal und erst dann mit dem anderen.

In der Programmkette

  Eingabe
  Verarbeitung
  Ausgabe

kann man in jeder Stufe Fehler machen. Es hat keinen Sinn
daran zu glauben, dass man selbst jede Stufe hinkriegt.
Wenn das Gesamtsystem nicht funktioniert, dann muss jede
Stufe überprüft werden. Sinnvollerweise fängt man mal
damit an, ob die Eingabe überhaupt klappt. In deinem
Fall heist das: Welche Werte kommen den eigentlich vom ADC?
Gast #502729
Lesenswert?

 @ Karl heinz Buchegger
Ei klaro, da hab ich ja gar nicht dran gedacht. Hab es geändert und es 
funktioniert. Falls es interresiert, hier noch mal das Programm:

#include <avr/io.h>

void reset();

int main (void) {
    reset();

    int adclow;
    int vertikallinks;
    int vertikalrechts;
  while(1)
  {

  ADMUX= (0<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(1<<MUX0)|(0<<MUX1);
  ADCSRA= (1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADSC);
    while ( ADCSRA & (1<<ADSC) ) // auf Abschluss der Konvertierung 
warten
    {
    }
    adclow=ADCL;
    vertikallinks=ADCH;

  ADMUX= (0<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(0<<MUX0)|(1<<MUX1);
  ADCSRA= (1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADSC);
    while ( ADCSRA & (1<<ADSC) ) // auf Abschluss der Konvertierung 
warten
    {
    }
    adclow=ADCL;
    vertikalrechts=ADCH;
    int ergebnis=vertikallinks-vertikalrechts;
    if(-1>ergebnis||1<ergebnis)
    {
      if(-1>ergebnis)
      {
        PORTB = (1<<PB2) | (0<<PB3);
      }
      else
      {
        PORTB = (0<<PB2) | (1<<PB3);
      }
    }
    else
    {
    PORTB=(0<<PB2)|(0<<PB3);
    }

  }  main();

   return 0;
}


void reset(){
        DDRD= 0xff;
    DDRB= 0x00;

}
Gast #502737
Lesenswert?

Aber dann nimm zum Vergleich die unteren 8 Bit. Im Moment wird ein 
Unterschied nur erkannt (Einwand von Karl heinz beachten!), wenn sich 
die Werte um mindestens 256 (8 Bit) unterscheiden. Es ist die Frage, ob 
du so grosse Änderungen anlegst.

Eine weitere Sache: Du holst dauernd frische Werte und du reagierst nur 
auf Änderungen von eben nach jetzt. Wenn sich nix ändert, werden die 
Bits von dir zurückgesetzt. Denk daran so ein µC ist sau schnell. Wenn 
die Bits z.B. eine LED steuern - du wirst das kurze Aufflackern nicht 
sehen!
Gast #502753
Lesenswert?

@Stefan
Danke für die Tips. War mein erstes C-Programm und mein erster 
AD-Wandler Einsatz (soll kein Ausrede sein;) ). Aber der obere Absatz 
verstehe ich nicht ganz. Es sollen einfach Spannungen von ca. 0V bis ca. 
3V gegeneinander verglichen werden. Und das mit einer Hysterese.
Gast #502781
Lesenswert?

> Er hat ADLAR gesetzt.

Das habe ich nicht gesehen. Dann werden ja nur die zwei der 
niedrigwertigsten Bits weggeworfen.

x/X sind die 10 relevanten Bits für 0V..3V

ADCH     ADCL
xxxxxxxx XX000000

Mit voller 10-Bit Auflösung hätte man 3V / 2^10 = 2,93 mV 
Digitalisierauflösung. Ohne die Bits X hat man dann eine vierfach (2^2) 
gröbere Auflösung (11,72 mV).

Ich dachte es werden 8 Bits in ADCL weggeworfen. Das wäre eine 
Verminderung der Digitalisierauflösung um den Faktor 256 (2^8), d.h. ein 
Wert zum nächsten müsste sich um die 256er Stufe unterscheiden, um als 
anderer Wert erkannt zu werden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren