PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem bei 4 Kanal Servo PWM



The Man
16.11.2007, 14:33
Hallo Hallo,

ich bin dabei mir einen 4 Kanal Servo PWM Generator bauen.
Prinzip:

Takt = 8MHz

Ich habe zwei ISR:
die eine wird angesprungen, wenn eine ADC fertig ist.
hier werden AD Werte in die Ram Adressen 108 bis 111 geladen
und der AD Kanal um 1 erhöht.

Die andere bei einem Comparematch des TIMER 2 mit Prescaller = 1 und OCR2 = 30 zum Zug. Dort werden PINS des PORTD LOW gelegt und ein Zycluszähler erhöht.



Zu Begin des Programs werden 4 Analogwerte eingelsen.
Diese werden der Größe nach sortiert und mit dem Zugehörigen Pin in den Ramadressen 100 - 108 gespeichert.
************************************************** *******
Nach dem Sortieren kommt eine Verzögerungsschleife um ca. 18ms zu erreichen.
Dann wird der PORTD mit 01010101 belegt.(die Servo sind immer eins versetzt)
Nun folgt eine Verzögerung von 1ms.
Bis hierhin geht auch alles.

Der Pegel bleibt solange HIGH bis der Zyclus den selben Wert hat, wie
der dazugehörige PIN. Das Problem ist jetzt, dass diese Schleife bei etwa 3,8 ms liegt.(Osszi)
Findet sich im Code mit einer !!!!!-Reihe.

Im Simulator des AVR Studio läuft das Ganze.
Hat jemand eine Idee?




.include "m8def.inc"

.def tmp = r16
.def lowe = r17
.def lowz = r18
.def highe = r19
.def merker = r20
.def konst = r21
.def zyclus = r22
.def kanal = r23
.def zyclusnummer = r24
.def pin = r25

.def xlow = r26
.def xhigh = r27
.def ylow = r28
.def yhigh = r29
.def zlow = r30
.def zhigh = r31

.org 0x000
rjmp reset

.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue

.org ADCCaddr
rjmp adcc

reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000010
out TCCR0,tmp
ldi konst,8
ldi xlow,100


ldi ylow,116
ldi tmp,1
st y+,tmp
ldi tmp,4
st y+,tmp
ldi tmp,16
st y+,tmp
ldi tmp,64
st y+,tmp

ldi ylow,108
ldi zlow,108

ldi lowe,255
ldi tmp,0b00100000
out DDRC,tmp
ldi tmp,0b01010101
out DDRD,tmp
ldi tmp,0b011000000
out ADMUX,tmp
ldi tmp,30
out OCR2,tmp

nop
nop
nop

sei
main:
;*****************************
;***ADC Freerun + Interrupt***
;*****************************
ldi r16,0
ldi r17,255
ldi r18,0
ldi r19,0
ldi r20,0
ldi r21,0
ldi r22,0
ldi r23,0
ldi r24,0
ldi r25,0
ldi r26,100
ldi r27,0
ldi r28,108
ldi r29,0
ldi r30,108
ldi r31,0

ldi kanal,0b011000000
out ADMUX,kanal
ldi tmp,0b11001101 ;PRESCALER FEHLT
out ADCSRA,tmp

ldi xlow,108

pos:
cpi r26,112
breq voll2
rjmp pos
voll2:
ldi xlow,100
ldi lowe,255



schleife2:

schleife1:

ld lowz,y ;108 - 109 - 110 - 111
cp lowz,lowe
brsh istgrossr
mov lowe,lowz
mov zlow,ylow ;Z-Pointer zeigt auf Adresse mit kleinstem Wert (KW)
istgrossr: ;(KW)
inc ylow ;109 - 110 - 111 - 112 ;(KW)

cpi r28,112 ;(KW)
brlo schleife1 ;(KW)
add r30,konst ;0b10000000 => Bereich 136 bis 139 ;(KW + 4)
ld merker,z ;dort ist der PIN Wert gespeichert ;(KW + 4)
subi r30,8 ;(KW)

st x+,lowe ;100 - 102 - 104 - 106 ;(KW)
st x+,merker;101 - 103 - 105 - 107 ;(KW)
ldi lowe,255 ;(KW)

st z,lowe ;(KW)
ldi ylow,108
ldi zlow,108

cpi xlow,108
brlo schleife2

ldi r26,100
ld r0,x+;100 zyclus
ld r1,x+;101 pin
ld r2,x+;102
ld r3,x+;103
ld r4,x+;104
ld r5,x+;105
ld r6,x+;106
ld r7,x+;107
ldi r26,100
ldi r30,108
ldi tmp,0
sorten:

ld lowe,x+ ;100 - 107
st z+,lowe ;108 - 115
ld pin,x+
add pin,tmp
mov tmp,pin
st z+,pin ;108 - 115
ld lowz,x

cp lowz,lowe
brne diff
dec r30
dec r30
rjmp gleich
diff:
ldi tmp,0
gleich:
cpi r26,108
brne sorten





ldi r26,108
ld r8,x+;108 zyclus
ld r9,x+;109 pin
ld r10,x+;110
ld r11,x+;112
ld r12,x+;113
ld r13,x+;114
ld r14,x+;115
ld r15,x+;116

ldi r26,0
ldi tmp,0
out TCNT0,tmp

waita:
in tmp,TCNT0
cpi tmp,252
brlo waita
ldi tmp,0
out TCNT0,tmp
inc r26
cpi r26,72
brlo waita



ldi tmp,0b00001001 ;RPESCALER 1
out TCCR2,tmp

ldi r26,108
ldi tmp,0
out TCNT2,tmp



ldi tmp,0b01010101
out PORTD,tmp
ldi tmp,0b10000000
out TIMSK,tmp
ldi zyclus,0
warten1:
cpi zyclus,250
breq wigger

rjmp warten1
wigger:
sbi PORTC,5
ldi zyclus,0
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!
pulse:

ld zyclusnummer,x+
ld pin,x+
in tmp,PORTD
com pin
and pin,tmp

loop:
cp zyclusnummer,zyclus
brne loop

in tmp,PORTD

cpi tmp,0
brne pulse
cbi PORTC,5
warten:
cpi zyclus,249
brsh ende
rjmp warten
ende:

ldi tmp,0
out TIMSK,tmp

ldi ylow,108
ldi r30,108
ldi r26,100
ldi tmp,0
nullen:
st x+,tmp
cpi r26,116
brlo nullen
ldi merker,0
ldi zyclusnummer,0

rjmp main




;**********************************
;speichert den ADC Wert in die
;Vektoradresse und schaltet auf den
;nächsten ADC Kanal
;**********************************
adcc:
in tmp,ADCH

andi tmp,0b11111100
st x+,tmp ;108=>109=>110=>111=>112
cpi kanal,0b011000011
brsh fertig
inc kanal
out ADMUX,kanal
ldi tmp,0b11001101 ;PRESCALER FEHLT
out ADCSRA,tmp
fertig:
reti

hitvalue:
inc zyclus
cp zyclus,zyclusnummer
brne nicht
out PORTD,pin
nicht:
reti


Danke,
The Man

Besserwessi
16.11.2007, 15:26
Das mit dem Sortieren habe ich nicht verstanden. Bei den ISR routinen ist noch ein Fehler drinn:
Am anfang der ISR Routine muß man das Porzessor status register sichern, sonst werden die Flags für das Hauptprogramm geändert. Ähnlich muß man entweder seperate Register für die ISR routinen nehmen oder die Register vorher retten.

The Man
16.11.2007, 21:22
Was hat das mit dem Prozessor Register auf sich? Kann ich einfach sagen z.B.
in tmp,SREG ?

Was das ändern von registern in den ISR angeht, dass ist schon so gewollt.

Zum sortieren:
Ich lese AD Kanäle 0 bis 3 ein.
Dabei ist jeder Wert nachher entsprechend seinem Kanal für einen bestimmten PIN. Jetzt wollte ich das nicht so machen, dass ich die HIGH Pegel hinter einander schachtele, sondern alle in einem einzigen Durchgang behandele. Dabei löst der TIMER2 mit Presc = 1 bei OCR2 = 32 und 8MHz einen Comparematch Interrupt aus. In der ISR wird die Anzahl mit gezählt. Stimmt diese mit dem ADC Wert einer der PIN´s überein, wird der entsprechende LOW gesetzt. Da die AD Werte ja nicht der Größe nach von Kanal 0 bis 3 ansteigen, muss man sie vorher sortieren und ggf. selbe kombinieren. Der Witz an der Sache ist, das ich theoretisch einige mehr als acht PWM erzeugen könnte - wenn ich das irgenwann mal vorhabe und außerdem ist der µC nicht nur ausschließlich mit der Generierung beschäfftigt und könnte sich in den ewig langen 18 ms um etliches anderes kümmern.

Greetings

Besserwessi
17.11.2007, 18:02
Die idee mit in tmp,SREG ist schon mal richtig. Man hat dann allerdings tmp mit SREG belegt und den alten inhalt von tmp überschreiben. Eine typische ISR routine fängt daher so an:
push tmp
in tmp,SREG
push tmp
Das retten der Register ist ein ganz wesentlicher Teil der ISR programmierung. Am besten noch mal ein Tutorial lesen, die könne das bestimmt besser erklären. Wenn man genug register frei hat, kann man auch extra Register für die Interrupts reservieren und kann sich das retten auf den Stack sparen.
Das mit dem sortieren hab ich jetzt verstanden, ist mal ein anderer Ansatz als üblich.

The Man
17.11.2007, 18:18
Ich geb zu, dass mit dem Pusg und so hab ich schon gemacht, ohne auf die Antwort zu warten.
Geht aber noch nicht, muss ich mir mal mit nem Osszi ansehen.

Was währe denn eine übliche Methode?

Besserwessi
20.11.2007, 16:01
Zum debuggen wäre der Simulator von AVRStudio bestimmt besser als ein Oszilloskop.
Die üblich Methode um das PWM Signal zu erzeugen, ist es die Kanäle weitgehend unabhängig zu berechnen. Also einen Zähler hochlaufen lassen und für die Kanäle eine 1 ausgeben, für die der Wert größer als der Zähler ist. Der eine Zähler kann für mehrere Kanäle benutzt werden, aber sonst sind Kanäle unabhängig. Wenn man es mit Interrrupt realisieren will, dann macht der Interrupt im wesentliche folgendes:
1) Kanal 1 mit Zähler vergleiche und 1 oder 0 ausgeben
2) Kanal 2,3,... mit Zähler vergleiche ...
3) Zähler hochsetzen
4) testen of Zähler fertig ist -> neu von 0 Starten


Für die Servos muss nach dem Puls noch eine Lange pause dazu.

The Man
20.11.2007, 17:14
Der Witz ist, im Simulator läuft das Program vorallem auch beliebig oft.
Nur auf dem µC dann nicht mehr... Und das der zu langsam ist kann nicht sein, da der Simulator mit 4 und der AVR dann mit 8MHz läuft.

Ok, mein Ziel war es, während des HIGH Pegels möglichst wenig Aufwand zu haben und alles was man vorher machen kann zu erledigen. Aber dann versuche ich es mal mit der Variante.

Danke,
The Man

Besserwessi
21.11.2007, 19:20
Im Simulator ist zwar eine taktfrequenz eingetragen, die dient aber nur zur umrechnung in Zeiten. Die tatsächliche Geschwindigkeit mit der simuliert wird ist deutlich langsamer und hängt vom PC ab.
Gerade wenn etwas mit dem Retten der Register im interrrupt nicht richtg ist, kann das eine ganze weile (ein paar sekunden ?) gut gehen. Der simulator ist so langsa, dass man kaum die Geduld aufbringt so lange zu simulieren. Man kann solche fehler am besten erkennen wenn man an den Anfang der ISR Routine einen Breakpoint setzt und dann die OSR Routine im Einzelschritt durchläuft. Vor dem RTI müssen alle normalen Register wieder so sein wie zuvor. Sonst poste doch noch mal den Code. Die eigenen Fehler findet man halt oft schwieriger als fremde.

The Man
22.11.2007, 16:00
Also ich hab hier jetzt mal die übliche Variante angewendet.
in

ich starte den ADC mit Kanal 0
und lese das ein, wenn die Conversion fertig ist.

das läuft dann vier mal, jedes mal mit dem nächsten ADC Kanal und einem anderen Register zum speichern.

dann ca.8ms verzögern

dann 1 ms verzögern

und dann in eine schleife bis PORTD = 0 ist und danach warten bis auch die zweite ms vorbei ist.

Das seltsame ist, ich beeinflusse alle AD Werte mit allen Potis?!!?

Das register "pause" stellt sicher, dass der Port nicht schon während der ersten ms bearbeitet wird. Sieht man auch in der ISR.

hier der Code:


.include "m8def.inc"

.def tmp = r16
.def k0 = r17
.def k1 = r18
.def k2 = r19
.def k3 = r20
.def zyclus = r21
.def kanal = r22
.def pause = r23
.org 0x000
rjmp reset

.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue



reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000010
out TCCR0,tmp

ldi tmp,0b00100000
out DDRC,tmp
ldi tmp,0b01010101
out DDRD,tmp
ldi tmp,0b011000000
out ADMUX,tmp
ldi tmp,30
out OCR2,tmp

nop
nop
nop


sei
main:

ldi kanal,0b01100000
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal0:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal0
in k0,ADCH



ldi kanal,0b01100001
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal1:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal1
in k1,ADCH



ldi kanal,0b01100010
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal2:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal2
in k2,ADCH


ldi kanal,0b01100011
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal3:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal3
in k3,ADCH


ldi tmp,0
out TCNT0,tmp

;_________________18ms Pause_____________-
waita:
in tmp,TCNT0
cpi tmp,252
brlo waita
ldi tmp,0
out TCNT0,tmp
inc r26
cpi r26,74
brlo waita
;________________________________________-


ldi tmp,0b00001001 ;RPESCALER 1
out TCCR2,tmp

ldi tmp,0
out TCNT2,tmp



ldi tmp,0b01010101
out PORTD,tmp
ldi tmp,0b10000000
out TIMSK,tmp
ldi zyclus,0
ldi r26,0

;*******************1ms Offset*****************
warten1:
cpi zyclus,250
breq wigger

rjmp warten1
wigger:
;**********************************************

sbi PORTC,5
ldi zyclus,0
out TCNT2,zyclus
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!
ldi pause,1

pulse:

in tmp,PORTD
cpi tmp,0
brne pulse

warten:
cpi zyclus,249
brsh ende
rjmp warten
ende:
cbi PORTC,5

ldi zyclus,0
out TCCR2,zyclus
ldi pause,0
ldi kanal,0b01100000
out ADMUX,kanal
rjmp main




;**********************************
;speichert den ADC Wert in die
;Vektoradresse und schaltet auf den
;nächsten ADC Kanal
;**********************************


hitvalue:
cpi pause,0
breq null

cp zyclus,k0
brne ka
cbi PORTD,0
ka:

cp zyclus,k1
brne kb
cbi PORTD,2
kb:

cp zyclus,k2
brne kc
cbi PORTD,4
kc:

cp zyclus,k3
brne kd
cbi PORTD,6

kd:

null:
inc zyclus
reti


The Man

Besserwessi
22.11.2007, 20:53
In der ISR routinge feht immer noch das retten des Status registers. Alsoe z.B. in sr_save,SREG am Anfang der ISR und out SREG,SR_save vor RTI. Ohne retten des Status ist das Programm ziehmlich unberechenbar (soweit das mit ner CPU geht).

Insgesammt ist das Porgramm schwer zu verstehen, weil fast keine Kommentare vorhanden sind. Das gegenseitige Beinflussen der AD Kanäle tritt typischerweise auf, wenn die Potis zu hochohmig sind (> 20 KOhm). Ein kleiner Kondensator (1nF...100nF) gegen Masse an jedem AD Eingang kann da Abhilfe schaffen.

The Man
23.11.2007, 10:01
Danke für den Hinweis mit den Kondenastoren, wenn ich mich richtig erinerre, habe ich da 25k Potis drin.

Wenn ich nach dem "in ADCH" noch ein ldi anhänge, läuft das ganze, aber ich werde dann noch die bereinigte Versiuon mit dem save hochladen.

Besserwessi
23.11.2007, 22:22
Mit 25 K Potis sollte es eigentlich kaum Probleme geben mit den AD eingängen. Hab mich oben mit dem Wert etwas vertan, kritisch wird es erst ab 50 kOhm und dann auch eher langsam.

Eine ISR routine die das SREG verändert (so wie im code oben) führt fast immer zu unerwarten Fehlern im Rest des Programms. Diesen Punkt unbedingt beheben.

The Man
24.11.2007, 15:05
Ok, ich hab mal die üblichen ADC Maßnehmen ergriffen, also Induktivität und C an Aref und die Kondensatoren an den Eingängen gegen Masse.
Trotzdem zappelt da alles weiter vor sich hin. Muss ein Fehler im Code sein.
Ich hab auch mal ein Register zum sicher von SREG => save_sreg angelegt.


.include "m8def.inc"

.def tmp = r16
.def k0 = r17;Servo 0
.def k1 = r18;Servo 1
.def k2 = r19;Servo 2
.def k3 = r20;Servo 3
.def zyclus = r21
.def kanal = r22 ;geht an ADMUX
.def pause = r23 ;für die 1ms Offset und die zweite ms für
; die Servoposition wird die selbe ISR benutzt. Ist Pause = 0
;wird über das LOW setzten weggesprungen, wenn Pause = 1 eben nicht.
;sinngemäß wird Pause nach der ms erhöht und nach dem Positionsstellen
;erniedrigt.
.def save_sreg = r24 ;erklärt sich sicher von selbst
.org 0x000
rjmp reset

.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue



reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000010
out TCCR0,tmp

ldi tmp,0b00100000
out DDRC,tmp
ldi tmp,0b01010101
out DDRD,tmp
ldi tmp,0b011000000
out ADMUX,tmp
ldi tmp,30
out OCR2,tmp

sei
main:
;################################################# #################
;################################################# #################
;hier werden die ADC Werte für das jeweilige Servo erfasst

ldi kanal,0b01100000 ;Hier wird für den Servo 0
out ADMUX,kanal ;die Position ermittelt
ldi tmp,0b11000101 ;PRESCALER 32 - Singleconversion
out ADCSRA,tmp
kanal0:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal0
in k0,ADCH



ldi kanal,0b01100001
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal1:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal1
in k1,ADCH



ldi kanal,0b01100010
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal2:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal2
in k2,ADCH


ldi kanal,0b01100011
out ADMUX,kanal
ldi tmp,0b11000101 ;PRESCALER 32
out ADCSRA,tmp
kanal3:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal3
in k3,ADCH
;################################################# ############
;################################################# ############

ldi tmp,0
out TCNT0,tmp

;_________________18ms Pause_____________-
waita:
in tmp,TCNT0
cpi tmp,252
brlo waita
ldi tmp,0
out TCNT0,tmp
inc r26
cpi r26,74
brlo waita
;________________________________________-


ldi tmp,0b00001001 ;RPESCALER 1
out TCCR2,tmp

ldi tmp,0
out TCNT2,tmp



ldi tmp,0b01010101 ;Pins für das Signal HIGH setzten
out PORTD,tmp
ldi tmp,0b10000000
out TIMSK,tmp
ldi zyclus,0
ldi r26,0

;*******************1ms Offset*****************
warten1:
cpi zyclus,250
breq wigger

rjmp warten1
wigger:
;**********************************************

sbi PORTC,5 ;wurde zur Kontrolle der Zeiten benutzt und mit Oszi gemessen
ldi zyclus,0
out TCNT2,zyclus
ldi pause,1
;ab hier Stellungs kritische ms

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;diese Schleife wird solange durchlaufen,
;bis der PORTD an dem die Servo angeschlossen sind
;komplett LOW ist
pulse:

in tmp,PORTD
cpi tmp,0
brne pulse
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

;'''''''''''''''''''''''''''''''''
;diese Schleife macht die ms ggf. voll,um das PWM nicht zu verzerren
warten:
cpi zyclus,250
brsh ende
rjmp warten
ende:
;'''''''''''''''''''''''''''''''''
cbi PORTC,5

ldi zyclus,0
out TCCR2,zyclus
ldi pause,0
ldi kanal,0b01100000
out ADMUX,kanal

rjmp main




hitvalue:
in save_sreg,SREG
cpi pause,0
breq null

cp zyclus,k0
brne ka
cbi PORTD,0
ka:

cp zyclus,k1
brne kb
cbi PORTD,2
kb:

cp zyclus,k2
brne kc
cbi PORTD,4
kc:

cp zyclus,k3
brne kd
cbi PORTD,6

kd:

null:
inc zyclus
out SREG,save_sreg
reti


Danke auch bis hier hin schon für die Mühen,
The Man

wkrug
24.11.2007, 20:22
Ich bin der Meinung dein Programm hängt viel zu viel in der Timer 2 Interrupt Routine rum.
Warum nimmst Du nicht den Timer 1 her und gibst dann ein Servo nach dem anderen aus ?
Der Timer kann bei einer Quarzfrequenz von 8MHz mit einem Prescaler von 8 verwendet werden. Mit diesen Parametern entspricht der Comparematch Zählerstand dann auch der Servoimpulslänge in µs.
Da der Timer 1 ein 16Bit Timer ist brauchst Du nicht mal ein Überlaufregister, weil ja 65ms in den Timer "reingehen".
Dann lässt Du eine Pause von 12ms folgen und startest den Zyklus neu.

Die Comparematch1A Routine würde dann in einem Zyklus 20ms nur 4mal durchlaufen und deine Servos kriegen genauso viele Impulse wie jetzt auch.

Zur Register Sicherung:

Meine Register Sicherung schaut immer folgendermassen aus:


PUSH temp ; temp Register sichern
IN temp,SREG; SREG ins temp Register
PUSH temp ; temp Register nochmal sichern
PUSH temp1... ; weitere in der Interruptroutine verwendete Register sichern
; #### Dein Quellcode ####
POP temp1 ; weitere Register zurückschreiben
POP temp
OUT SREG,temp ; SREG zurückschreiben
POP temp ; Werte des temp Registers zurückholen
RETI ; Raus aus dem Interrupt

The Man
26.11.2007, 08:26
Ich hab jetzt mal den Kanalwechsel im ADMUX wegkommentiert, damit alle Servo Register aus dem Selben Poti versorgt werden. laufen jetzt alle synchron. (Ich habe bei der ersten Version darauf geachtet, erst den Kanal zu ändern und dann die Wandlung zu starten) Das bedeutet ja, das das Program im Prinzip funktioniert. Ich verstehe nur nicht, warum er die Werte dann durch einander Würfelt, wenn ich die Kanäle weiterschalte
](*,)

The Man
28.11.2007, 09:00
SOOOOOOOOOOOOO,

ich hab das Problem gefunden! Ich lese an vier Stellen das ADCH ei´n (left adjusted). Das funktioniert ohne Interrupt über das ADC Flag Bit 4. Also in einer Schleife:

kanal0:
in tmp,ADCSRA
sbrs tmp,4
rjmp kanal0
in k0,ADCH

Der Gag ist, dass dieses Bit irgendwie nicht wie üblich automatisch gelöscht wird und das Program deshalb Sinnlos durchrennt. Das löscht sich nichtmal, wenn ich ADCSRA manuell mit NULL beschreibe.
Kann es sein, dass ich hier einem Vista Problem aufsitzte? Im Dec C++ Compiler hatte ich das auch schon...

Besserwessi
28.11.2007, 18:38
Das kommt davon wenn man nur einfach 4 schraubt um ds ADIF bit auszuwählen. Besser statt der den Bitnahmen (ADIF) verwenden, dann wird der code besser portabel und man sieht besser welches Bit gemeint ist.

Die Intteruptsflags werden gelöscht, indem eine 1 hineingeschrieben wird. Klingt unlogisch ist aber so.

The Man
28.11.2007, 20:06
for (applaus=0;applaus<1001;applaus++){
printf("=D> =D> =D> =D> =D> =D> DANKE!\n");
}

Jetzt läuft das Ding.