Hi,
macht es euch doch nicht so schwer. Den PWM kannst du ganz einfach mit den Timern lösen.
Ich habe mal einige Ausschnitte aus den Programmen für Meine RC-Fernsteuerung auf Basis der XBee-Pro Funkmodule zusammengepuzzelt und angehängt, mit dem an einem Mega8 Prozessor 5 Servos angesteuert werden können sollten.
Ich hoffe es ist verständlich auskommentiert.
Es gibt ein Array mit 9 Servokanälen - 1bis 5 sind die Servos am Portb.0 bis Portb.4, Servos 6-9 gehen an eine Dummy-Variable um die Pause zwischen den Impulsen auf min ca 10ms zu halten - auch wenn alle Servos gerade nur mit 1,0ms angesteuert werden. (Die Pausenzeit ist hier Variabel - bei RC-Servos sollte sie nicht unter 10ms und nicht über 20ms liegen, alles dazwischen ist unkritisch)
Das Array beginnt mit S(1) soll aber Portb.0 ansteuern, darum das Handling mit aktservo und _aktservo.
Das ganze läuft mit 7Bit Daten (S(1)=0 erzeugt am Portb.0 einen Impuls mit 2ms Dauer, S(2)=127 erzeugt am Portb.1 einen Impuls mit 1ms Dauer)
ADC-Messungen erfolgen am Portc.1 ... Portc.5
Edit: Ich habe es aber nicht nochmal in dieser Form getestet - ich hoffe, daß es Funzt, kann es aber nicht garantieren...
Code:
$regfile = "m8def.dat"
$crystal = 8000000
Config Portb = Output
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Config Timer0 = Timer , Prescale = 64 'Timer für Servos
Start Timer0
On Timer0 _timer0
Enable Timer0
Enable Interrupts
Dim Durchlauf As Byte 'Zähler Servoimpulsdurchläufe
Dim Aktservo As Byte 'Aktuelles Servo (ISR)
Dim _aktservo As Byte 'Portpin des akt. Servos
Dim S(9) As Byte 'Servowertearray
Dim Servo As Word 'Dummy für verarbeitung der 4 Dummyservokanäle für die Pausenzeit
Dim A as Byte 'Zähler For Next
Dim B as Byte 'Zähler For Next
Dim C as Word 'Annahme vom ADC
Dim Temp as Word 'Mittelwertbildung ADC
'Initialisieren der Startwerte (damit Servos nicht total rumzicken oder sich im Kreis drehen...)
For A = 6 To 9 'Dummykanäle der Pausenzeit
S(a) = 64
Next
Do
For A = 1 To 5 'Die 5 Servokanäle Sollwerte erfassen
Temp = 0
For B = 1 To 16 'Mittelwertbildung aus 16 Messungen
C = Getadc(a)
Temp = Temp + C
Next
Shift Temp , Right , 7 '16 Messungen a 10Bit ergeben 14Bit, diese werden auf 7Bit runterdividiert - das geht am einfachsten und schnellsten mit Shiften
S(a) = Temp
Next
Loop
'**ISR des Servotimers**
_timer0:
If Aktservo < 6 Then 'servos 1-5 sind echte Portpins,
Portb._aktservo = 0 'Servos 6-9 gehen an Bits der Dummyvariable Servo,
Else ' um die Pausenzeiten auf ca. 13...19ms zu bringen
Servo._aktservo = 0 'Hier wird der Impuls abgeschaltet, nachdem die Zeit abgelaufen ist
End If
Incr Aktservo 'Zähler, welches Servo gerade seinen Impuls bekommt
_aktservo = Aktservo - 1 'da die Ports mit Pin 0 beginnen, wird -1 gerechnet
If Aktservo = 10 Then 'Rücksetzen nach den 9 Durchläufen
Aktservo = 1
_aktservo = 0
End If
If Aktservo < 6 Then 'Nachdem die Aktservo erhöht wurde, wird der nächste Impuls eingeschaltet
Portb._aktservo = 1
Else
Servo._aktservo = 1
End If
Timer0 = S(aktservo) + 4 'und der Timer wird passend vorgeladen - S=0 =2ms, S=127 =1ms, S=64 =1,5ms
Return
Lesezeichen