von
Sanguin (Gast)
11.08.2009 18:34
Ich möchte über PC-0 und PC-1 (ATmega8) also über die AD-Wandler zwei
Potis einlesen, und anhand der Stellung zwei Modellbauservos (an PD0
und PD1) unabhängig voneinander steuern.
(Signal für den Servo: Alle 18ms einen Impuls, der 1ms-2ms lang ist, 1ms
bedeutet ganz links 2ms ganz rechts ).
Der ATmega8 läuft bei 1MHz (1 Takt = 1µs).
In der Simulation scheint alles zu funktionieren, und auch die Schaltung
funktioniert mit einem ähnlichen Code.
Es wird in die Interrupt-Routine gesprungen, auch die PMW scheint zu
funktionieren, nur das Poti hat keinen Einfluss auf den Servo.
Scheinbar stimmt irgendwas mit dem ADC nicht.
Der Servo Steht immer ganz links. wenn ich allerdings bei Servominnimum
(im Quelltext markiert) 200 schreibe steht der Servo wie zu erwarten
ganz rechts.
(im Anhang der andere Code, mit dem die Schaltung funktioniert )
1 .include "m8def.inc"
2
3
4
5
6 .org 0x000
7 rjmp start ; Reset Handler
8
9 .org ADCCaddr ; AD-Wandlung abgeschlossen
10 rjmp ADChandle
11
12 start: ;################################## INITIALIZE #####################################
13
14
15
16 ldi R16, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse Stack initialisieren
17 out SPL, R16
18 ldi R16, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
19 out SPH, R16
20
21
22
23 ldi r16, 0b00111111 ; Port C adc
24 out DDRC, r16 ; Alle Pins außer reset und nicht existent am Port C
25 ; als Eingang konfigurieren
26
27
28
29 ldi r16, 0xff
30 out DDRD, r16 ; Alle Pins am Port D durch Ausgabe von 0xFF ins
31 ; Richtungsregister DDRD als Ausgang konfigurieren Port D Ausgang
32
33
34 ; ADC initialisieren: single conversion, interrupt enabled, Vorteiler 16, 8 höchste bits in ADCH,
35 ; Kanal 0, interne Referenzspannung AVCC, start conversion
36
37 ldi r16, 0b01100000
38 out ADMUX, r16
39 ldi r16, 0b11001100
40 out ADCSRA, r16
41
42
43 sei ;Interrupts erlauben
44 rjmp beginc
45
46
47
48 ADChandle: ; AD-Wandlung abgeschlossen
49
50 push r16
51
52 ldi r16,90 ;servominimum (0,9ms) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< hier (siehe text)
53
54 SBIC admux, 0 ;prüfen welcher Kanal Aktiv ist (bei 1 zu chan 1 springen)
55 rjmp chan1
56
57
58 in r1, ADCh ; ADC einlesen: High Byte
59 lsr r1 ; durch 2 teilen
60 add r1,r16 ;servominimum dazuaddieren Ergebnis ist eine zahl zwichen (90+0) und (90+127) entsprich 0,9ms-2,17ms
61
62
63
64 ; ADC initialisieren: single conversion, interrupt enabled, Vorteiler 16, 8 höchste bits in ADCH,
65 ; Kanal 1, interne Referenzspannung AVCC, start conversion
66
67 ldi r16, 0b01100001 ; Einlesen von kanal1 Initialisieren
68 out ADMUX, r16
69 ldi r16, 0b11001100
70 out ADCSRA, r16
71
72 rjmp endadc ;zum ende der Interrupt-routine springen
73
74 chan1:
75 in r2, ADCh ; ADC einlesen: High Byte
76 lsr r2 ; durch 2 teilen
77 add r2,r16 ;servominimum dazuaddieren Ergebnis ist eine zahl zwichen (90+0) und (90+127) entsprich 0,9ms-2,17ms
78
79 ; ADC initialisieren: single conversion, interrupt enabled, Vorteiler 16, 8 höchste bits in ADCH,
80 ; Kanal 1, interne Referenzspannung AVCC, NICHT STARTEN
81
82 ldi r16, 0b01100000
83 out ADMUX, r16 ; Einlesen von kanal0 Initialisieren
84 ldi r16, 0b10001100
85 out ADCSRA, r16
86
87 endadc:
88 pop r16
89 reti
90
91
92
93
94
95
96 beginc:
97
98
99
100 ldi R25,HIGH(1800) ; 1 Takt
101 ldi R24,LOW(1800) ; 1 Takt
102
103 Loop1c: ; Schleifenbeginn
104
105 nop ; tue nichts, 1 Takt
106 nop ; tue nichts, 1 Takt
107 nop ; tue nichts, 1 Takt
108 nop ; tue nichts, 1 Takt (ein schleifendurchlauf entspricht 10µs 1800 Durchläufe: 18ms )
109 nop ; tue nichts, 1 Takt (2x interrupt ist vernachlässigbar)
110 nop ; tue nichts, 1 Takt
111 sbiw R24,1 ; 2 Takte
112 brne Loop1c ; 2 Takte wenn nicht Null, (1 Takt bei Null) Schleifenende
113
114
115 ldi r16, 0b11111111 ;all servos high
116 out PORTD, r16 ;all servos high
117
118 clr r3
119 Loop2c: ; Schleifenbeginn 2
120
121
122
123 CP R3,r1 ;1 Takt
124 brne notjet1 ; 2 Takte wenn nicht Null, (1 Takt bei Null) PD0 abschalten, wenn r3= r1(servoposition1) ist
125 cbi PORTD,0 ; (2 Takte) < ansonsten das übergehen
126
127 notjet1:
128
129 CP R3,r2 ;1 Takt
130 brne notjet2 ; 2 Takte wenn nicht Null, (1 Takt bei Null) PD1 abschalten, wenn r3= r2(servoposition1) ist
131 cbi PORTD,1 ; (2 Takte) < ansonsten das übergehen
132
133 notjet2:
134
135 inc R3 ; 2 Takte
136 brne Loop2c ; 2 Takte wenn nicht Null, (1 Takt bei Null) Schleifenende2 (ein schleifendurchlauf entspricht 10µs 255 durchläufe)
137
138
139
140 sbi ADCSRA, ADSC ; adc wieder starten
141
142 rjmp beginc
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.