Hallo zusammen, ich möchte bei einem ATMEGA32 einen Joystick
anschließen, der ein Kettenfahrzeug antreiben soll. Allerdings scheitere
ich gerade dabei, zwei analoge Signale gleichzeitig mit den AD Eingängen
auszuwerten. Einen Eingang kann ich auswerten, das funktioniert, sobald
ich aber den zweiten Eingang danach auch auslesen möchte, funktioniert
nichts mehr. Bitte um Hilfe. Der zweite Teil der AD- Wandung der
auskommentiert ist, funktioniert nicht. Hier die C Datei:
Hi
>Einen Eingang kann ich auswerten, das funktioniert, sobald>ich aber den zweiten Eingang danach auch auslesen möchte, funktioniert>nichts mehr.
Dann zeig mal die Stellen im Programm, wo die einzelnen AD-Wandlungen
gestartet werden und auf das Ende der Wandlungen gewartet wird.
MfG Spess
tust du dir keinen Gefallen. Das ist nicht mehr durchschaubar, was du da
eigentlich alles einschaltest bzw. aktivierst.
Nach Einbindung der ADC Routinen aus dem Tutorial (und Anpassung der
Einstellung für die Referenzspannung), könnte dein Code so einfach sein
wie
"Gleichzeitig" geht sowieso nicht, da es nur einen Wandler gibt :-).
Du meinst wahrscheinlich kurz nacheinander.
Vor dem Auslesen musst du wartennnnnnnnnnnnn, bis der Wandler fertig
ist.
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=(adc_input & 0x0f) | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
ist Unsinn. Wenn du wissen willst, ob der WErt kleiner/gleich 450 ist,
dann schreib das auch so hin
1
if(adcwertx<=450)
wo liegt der Sinn, im C Code die Zahlenwerte als Hex-Werte anzuschreiben
und dann im Kommentar den Dezimalwert dazu anzugeben?
Ob du eine Hex-Schreibweise benutzt oder die Zahlen als Dezimalzahl
anschreibst, ist eine reine Frage der Schreibweise. In der Bedeutung
sind beide aber gleich: beides sind Zahlen und 0x1c2 bzw. dezimal 450
sind dieselbe Zahl.
Solche Geschichten sind auch immer fehlerträchtig:
1
ADMUX=0x04;
2
3
...
4
5
ADMUX=0x05;
Das mag in deinem speziellen Fall gut gehen, wenn du mit der internen
Referenzspannung und rechtsbündigem Ergebnis (Niedrigste 8 bit in ADCL,
obere zwei Bit in ADCH) messen willst, ansonsten sind derartige
Holzhammerzuweisungen eher zu vermeiden.
Würde dir eher zu folgender Vorgehensweise raten:
1
ADMUX&=0xE0;// Oberste drei Bit bleiben bestehen, MUX4:0 werden 0
2
ADMUX|=0x04;// Kanal 4 einstellen
Und das gleiche für Kanal 5:
1
ADMUX&=0xE0;// Oberste drei Bit bleiben bestehen, MUX4:0 werden 0
Ich danke euch für die Antworten, ich habe alle Kommentare beachtet und
das Programm neu überschreiben, indem ich Funktionen aus dem Tutorial
was mir empfohlen wurde benutzt habe und die main Funktion daraufhin neu
geschrieben habe. Allerdings Funktioniert immer nur ein Teil der
Funktion, entweder die value_x ODER die value_y, beides leider nicht.
Könnt ihr mir weiterhelfen?
1
#ifndef F_CPU
2
#define F_CPU 16000000 // Taktfrequenz = 16 MHz
3
4
#endif
5
#include<avr/io.h>
6
#include<util/delay.h>
7
#include<stdint.h>
8
9
10
11
12
uint16_tADC_Read(uint8_tchannel);
13
voidADC_Init(void);
14
intmain(void)
15
{
16
17
DDRB=0xff;//alle portb´s sind ausgänge
18
DDRD=0xF0;
19
DDRA=0x00;//alle PORTA´s sind eingänge
20
21
TCCR1B=0x03;
22
OCR1B=0xF0;
23
TCCR1A=0xA1;
24
OCR1A=0xF0;
25
26
while(1)
27
{
28
29
30
uint16_tvalue_x,value_y;
31
32
ADC_Init();
33
34
value_x=ADC_Read(4);
35
36
if(value_x<=450)
37
{
38
PORTD=0x40;//Motor1 linkslauf ; PORTD6=1
39
PORTB=0x02;
40
}
41
42
43
if(value_x>=650)
44
{
45
PORTD=0x80;//Motor1 rechtslauf; PORTD7=1
46
PORTB=0x04;
47
}
48
49
if(value_x<=650&&value_x>=450)
50
{
51
PORTD=0x00;//Motor1 rechtslauf; PORTD7=1
52
PORTB=0x00;
53
}
54
55
56
value_y=ADC_Read(5);
57
58
59
if(value_y<=450)
60
{
61
PORTD=0x80;//Motor1 linkslauf ; PORTD6=1
62
63
}
64
65
if(value_y>=650)
66
{
67
68
PORTB=0x04;
69
}
70
71
if(value_y<=650&&value_y>=450)
72
{
73
PORTD=0x00;//Motor1 rechtslauf; PORTD7=1
74
PORTB=0x00;
75
}
76
77
78
}
79
80
}
81
82
voidADC_Init(void)
83
{
84
85
// die Versorgungsspannung AVcc als Refernz wählen:
86
ADMUX=(1<<REFS0);
87
// oder interne Referenzspannung als Referenz für den ADC wählen:
88
// ADMUX = (1<<REFS1) | (1<<REFS0);
89
90
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
91
// schon auf 0, also single conversion
92
ADCSRA=(1<<ADPS1)|(1<<ADPS0);// Frequenzvorteiler
93
ADCSRA|=(1<<ADEN);// ADC aktivieren
94
95
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
96
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
97
98
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung
99
while(ADCSRA&(1<<ADSC)){// auf Abschluss der Konvertierung warten
100
}
101
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
102
Wandlung nicht übernommen. */
103
(void)ADCW;
104
}
105
106
107
/* ADC Einzelmessung */
108
uint16_tADC_Read(uint8_tchannel)
109
{
110
// Kanal waehlen, ohne andere Bits zu beeinflußen
111
ADMUX=(ADMUX&~(0x1F))|(channel&0x1F);
112
ADCSRA|=(1<<ADSC);// eine Wandlung "single conversion"
113
while(ADCSRA&(1<<ADSC)){// auf Abschluss der Konvertierung warten
Und noch ein guter Rat.
Lerne mit Einzelbitoperationen umzugehen!
Das ist eigentlich so ziemlich das wichtigste, wenn man seine
µC-Karriere beginnt.
Denn hier
1
PORTD=0x00;//Motor1 rechtslauf; PORTD7=1
2
PORTB=0x00;
setzt du alle 8 Bits vom Port auf 0. Auch die die für deinen Motor gar
nicht zuständig sind!
Bit setzen
1
Register|=(1<<Bitnummer);
Bit löschen
1
Register&=~(1<<Bitnummer);
und wenn du dann noch mittels einem #define dem Bit einen schönen
'Namen' gibts, dann wird das ganze auch noch übersichtlich und leicht zu
lesen.
Danke erstmal für eure Hilfe, habe jetzt nocheinmal alles umgeschrieben,
indem ich die Bits der Ports jetzt einzeln setzte und lösche. Allerdings
ist irgendetwas noch falsch, vielleicht die schreibweise mit dem value_x
oder value_y ? Wenn ich value_x auskommentiere, funktioniert value_y
einwandfrei, andersrum genauso, beides zusammen immernoch nicht. Woran
liegt das?
Wieviele Motoren hast du eigentlich?
Und warum setzt du da manchmal 4 Bits, manchmal nur 2?
Ich denke, dein Hauptproblem ist, dass dir eigentlich nicht wirklich
klar ist, wie die beiden Knüppel auf den/die Motor(en) einwirken sollen.
IN deinem Code macht der Y Knüppel jeweils das rückgängig, was der X
Knüppel eingestellt hat und umgekehrt.
Die ADC_Init() solltest du aus der Endlosschleife herausnehmen. Es ist
nicht nötig, den ADC bei jedem Schleifendurchlauf neu zu initialisieren,
das reicht einmal.