www.mikrocontroller.net

Forum: Compiler & IDEs Hilfe bei einem kleinen C-Programm (AD-Wandler)


Autor: Bastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
    ...

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

Bewertung
0 lesenswert
nicht 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?

Autor: Bastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe halt dadurch nur ein 8-Bit Wandler. Beim Vergleichen ist das 
doch eigentlich egal, oder?

Autor: Bastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

}

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

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

Bewertung
0 lesenswert
nicht lesenswert
> wenn sich die Werte um mindestens 256 (8 Bit) unterscheiden.

Er hat ADLAR gesetzt.

Autor: Bastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht lesenswert
Ich denke Stefan hat das ADLAR Bit übersehen.
Wenn es dir nichts ausmacht die untersten 2 Bits nicht
zu berücksichtigen, dann passt das schon.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

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.