Problem mit AD-Wandler (über interrupt)

Gast #1370115
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
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren