Forum: Mikrocontroller und Digitale Elektronik Problem mit AD-Wandler (über interrupt)


von Sanguin (Gast)


Angehängte Dateien:

Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.