www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit dem ADC des ATmega8


Autor: Thomas Haarhoff (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach 2 Wochen Quälerei und Sucherei und Probiererei und und und... ohne 
Ergebnis verfasse ich hier nen Thread, in der Hoffnung, mir kann jemand 
helfen.

Also folgendes:
Projekt sieht so aus:
Ein Servomotor ist auf einer Holzplatte befestigt und dreht sich immer 
von links nach rechts, nach links usw. Das funktioniert schon 
hunderprozentig.
Das Problem ist folgendes:

Auf dem Servo ist ein Abstandssensor befestigt, der bei einem Abstand 
von 8cm 1,6V liefert, oberhalb von 30cm 0V liefert und bei 3cm sein 
maximum von 5v liefert. bei 1,6 V soll ein Signal(an Pin C 6) gegeben 
werden.

An Port C ist eine I/O-Platine angeschlossen und an PIN 4,5 und 6 sin 
LEDs, die ich zur Kontrolle nutze.

Diese platte befundet sich auf einem Kettenfahrzeug.

Dieser sensor mist den Abstand zu einem Hindernis. (dem später 
ausgewichen werden soll (nicht bestandteil, dieses Codes))
Der Code ist glaub recht übersichtlich kommentiert... es sollte also 
recht einleuchtend sein, was ich wo möchte.

Problem ist: im ADC Register steht immer der Maximalwert, egal was ich 
ändere...
Also, wenn wer helfen kann, ich würd mich freun.
// Bibliotheken
#include <avr/io.h>        // Input/Output des AVRs
#include <avr/interrupt.h>  // Interrupts des AVRs


volatile unsigned char ti = 64;         // Einstellung der PWM
volatile unsigned char to = 0;         // Einstellung der PWM
volatile unsigned char nextreload = 128; // Einstellung der PWM
volatile unsigned char signal = 0;      // Takterzeugung
volatile uint16_t adw;               // Wert der AD-Wandlung  

// MAIN
int main()
{
 TIMSK |= (1 << TOIE2);  //Timer 2 Overflow Interrupt enabled
 TCCR2 |= (1 << CS02);   //Timertakt stellen

 ADCSRA |= (1 << ADEN);  //AD-Wandler enabled
 ADCSRA |= (1 << ADFR);  //Free Running Mode


 ADMUX |= (1 << REFS0);  // AVcc als Referenzspannung
 ADMUX |= (0 << REFS1);  //
 ADMUX |= (0 << ADLAR);   // Die 8 bit kommen in das Low-Register 
 ADMUX |= (1 << MUX0);   // PC5 als Eingang für den Abstandssensor
 ADMUX |= (1 << MUX2);

 ADCSRA |= (1 << ADPS1);  // Vorteiler
 ADCSRA |= (1 << ADPS0);  // auf /8

 ADCSRA |= (1 << ADSC);  // convert starten (muss nach MUX geschehen)

 //Port C Eingabe / Port D Ausgabe
 DDRC = 0x28;
 DDRD = 0xFF;

 sei(); //Interrupts zulassen

 // Hauptprogramm (Endlosschleife)
 while(1)
 {
   
 }
}

// Timer 2 Overflow Interrupt
ISR(TIMER2_OVF_vect)
{
 // 8bit Wandler deshalb können wir einfach adw den
 // Wert von ADCL zuweisen
 adw = ADCL;
 PORTD = adw;

 // ist dieser Wert > 82 heißt das, dass die Spannung > 1,6V ist was heißt,
 // dass der Abstandssensor näher als 8cm an dem Hindernis steht.

 if(adw > 82 )  // Zu nah an einem Hinderniss (8cm)
 {
   PORTC |= 0x20;
 }
 else           // Weit genug entfernt
 {
   PORTC &= 0xDF;
 }

// Ab hier beginnt die Servosteuerung, die aber nicht interessiert, da sie funktioniert^^
 TCNT2 = nextreload;    
 to++;
 if((to / ti)%2 == 0)
 {  
  if(signal == 1)
  {
   PORTC &= 0xF7;
   signal = 0;
   nextreload = 225;
  }
  else
  {
   PORTC |= 0x08;
   signal = 1;
   nextreload = 30;
  }
 }
 if((to / ti)%2 == 1)
 {
  if(signal == 1)
  {
   PORTC &= 0xF7;
   signal = 0;
   nextreload = 240;
  }
  else
  {
   PORTC |= 0x08;
   signal = 1;
   nextreload = 15;
  }
 }
}

Mit freundlichen Grüßen

Thomas Haarhoff... ein verzweifelnder ITA-Azubi.

Bei Fragen, einfach posten.

Aber auch im ICQ unter 168131574 bis morgends um 6 zu erreichen und dann 
wieder ab 11:30.

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

Bewertung
0 lesenswert
nicht lesenswert
> ISR(TIMER2_OVF_vect)
> {
>  // 8bit Wandler deshalb können wir einfach adw den
>  // Wert von ADCL zuweisen
>  adw = ADCL;
>  PORTD = adw;

Können tust du schon. Nur helfen wirds nicht.
Durch den Zugriff auf ADCL wird der ADC gesperrt und
erst durch den Lesezugriff auf ADCH wird die Sperre wieder
gelöst. Da du aber auf ADCH nicht zugreifst, ....

Autor: Thomas Haarhoff (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hieße, ich schreibe da ma adw = ADC hin.

Autor: Thomas Haarhoff (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm ich kann nciht editerien.

Es ändert sich nichts.
Und ich hab noch nen Fehler in der beschreibung gefunden.
 > Problem ist: im ADC Register steht immer der Maximalwert
es steht immer 0 drin. egal ob 0V an ADC5 anliegen der 5V

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In Zwischenzeit scheint's ja zu klappern ;)

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if((to / ti)%2 == 0)
{
... anweisungen gerade
}
if((to / ti)%2 == 1)
{
... anweisungen ungerade
}

Das prüft doch bestimmt, ob (to/ti) eine gerade/ungerage Zahl ist

Das geht aber einfacher ohne modulo:
if(  (to/ti) & 0x01  )
{
... anweisungen ungerade
}
else
{
... anweisungen gerade
}

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.