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


von Thomas Haarhoff (Gast)


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.
1
// Bibliotheken
2
#include <avr/io.h>        // Input/Output des AVRs
3
#include <avr/interrupt.h>  // Interrupts des AVRs
4
5
6
volatile unsigned char ti = 64;         // Einstellung der PWM
7
volatile unsigned char to = 0;         // Einstellung der PWM
8
volatile unsigned char nextreload = 128; // Einstellung der PWM
9
volatile unsigned char signal = 0;      // Takterzeugung
10
volatile uint16_t adw;               // Wert der AD-Wandlung  
11
12
// MAIN
13
int main()
14
{
15
 TIMSK |= (1 << TOIE2);  //Timer 2 Overflow Interrupt enabled
16
 TCCR2 |= (1 << CS02);   //Timertakt stellen
17
18
 ADCSRA |= (1 << ADEN);  //AD-Wandler enabled
19
 ADCSRA |= (1 << ADFR);  //Free Running Mode
20
21
22
 ADMUX |= (1 << REFS0);  // AVcc als Referenzspannung
23
 ADMUX |= (0 << REFS1);  //
24
 ADMUX |= (0 << ADLAR);   // Die 8 bit kommen in das Low-Register 
25
 ADMUX |= (1 << MUX0);   // PC5 als Eingang für den Abstandssensor
26
 ADMUX |= (1 << MUX2);
27
28
 ADCSRA |= (1 << ADPS1);  // Vorteiler
29
 ADCSRA |= (1 << ADPS0);  // auf /8
30
31
 ADCSRA |= (1 << ADSC);  // convert starten (muss nach MUX geschehen)
32
33
 //Port C Eingabe / Port D Ausgabe
34
 DDRC = 0x28;
35
 DDRD = 0xFF;
36
37
 sei(); //Interrupts zulassen
38
39
 // Hauptprogramm (Endlosschleife)
40
 while(1)
41
 {
42
   
43
 }
44
}
45
46
// Timer 2 Overflow Interrupt
47
ISR(TIMER2_OVF_vect)
48
{
49
 // 8bit Wandler deshalb können wir einfach adw den
50
 // Wert von ADCL zuweisen
51
 adw = ADCL;
52
 PORTD = adw;
53
54
 // ist dieser Wert > 82 heißt das, dass die Spannung > 1,6V ist was heißt,
55
 // dass der Abstandssensor näher als 8cm an dem Hindernis steht.
56
57
 if(adw > 82 )  // Zu nah an einem Hinderniss (8cm)
58
 {
59
   PORTC |= 0x20;
60
 }
61
 else           // Weit genug entfernt
62
 {
63
   PORTC &= 0xDF;
64
 }
65
66
// Ab hier beginnt die Servosteuerung, die aber nicht interessiert, da sie funktioniert^^
67
 TCNT2 = nextreload;    
68
 to++;
69
 if((to / ti)%2 == 0)
70
 {  
71
  if(signal == 1)
72
  {
73
   PORTC &= 0xF7;
74
   signal = 0;
75
   nextreload = 225;
76
  }
77
  else
78
  {
79
   PORTC |= 0x08;
80
   signal = 1;
81
   nextreload = 30;
82
  }
83
 }
84
 if((to / ti)%2 == 1)
85
 {
86
  if(signal == 1)
87
  {
88
   PORTC &= 0xF7;
89
   signal = 0;
90
   nextreload = 240;
91
  }
92
  else
93
  {
94
   PORTC |= 0x08;
95
   signal = 1;
96
   nextreload = 15;
97
  }
98
 }
99
}

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.

von Karl H. (kbuchegg)


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, ....

von Thomas Haarhoff (Gast)


Lesenswert?

hieße, ich schreibe da ma adw = ADC hin.

von Thomas Haarhoff (Gast)


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

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

In Zwischenzeit scheint's ja zu klappern ;)

von Matthias L. (Gast)


Lesenswert?

1
if((to / ti)%2 == 0)
2
{
3
... anweisungen gerade
4
}
5
if((to / ti)%2 == 1)
6
{
7
... anweisungen ungerade
8
}

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

Das geht aber einfacher ohne modulo:
1
if(  (to/ti) & 0x01  )
2
{
3
... anweisungen ungerade
4
}
5
else
6
{
7
... anweisungen gerade
8
}

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.