Hallo,
ich habe eine Frage zu dem Artikel Soft-PWM hier auf der Seite. Ich habe
einen atmega16 mit 16 Mhz und habe dies als einziges im Code geändert,
sowie dass PORTD statt PORTB verwendet wird. Ich verstehe nun aber
nicht, wieso schon bei einem Wert von 50 die vollen 2ms high sind bzw
wie ich bei diesem Code die 256 auf 2 ms mappen kann.
Vielen Dank schonmal
Vielleicht habe ich mich ungenau ausgedrückt.
Ich habe vor, eine Servosteuerung für 16 Servos zu programmieren. Diese
müssen in einem Intervall von 18 ms immer ein Signal zwischen 1 und 2 ms
bekommen. ich habe es jetzt geschafft 2 ms auf 256 zu mappen indem ich
die PWM Frequenz erhöht habe und am Ende vom Timer nochma 18ms ins OCR1A
Register geschrieben habe. jedoch sobald ich versuche 256 auf 1 ms zu
mappen, da das ja reicht für meine Servos, funktioniert das alles
nichtmehr mit der Taktanzahl in der ISR usw. :(
Es muss doch eine Möglichkeit geben. Ich weiß nicht, ob es mit weniger
als einem Grad Genauigkeit funktioniert. Wäre schön wenn ich mind. einen
Wert pro Grad des Servos habe.
@Chris (Gast)
>bekommen. ich habe es jetzt geschafft 2 ms auf 256 zu mappen indem ich>die PWM Frequenz erhöht habe und am Ende vom Timer nochma 18ms ins OCR1A>Register geschrieben habe.
Ob das so einfah funktioniert?
>mappen, da das ja reicht für meine Servos, funktioniert das alles>nichtmehr mit der Taktanzahl in der ISR usw. :(
Das ist wohl das Problem.
>Es muss doch eine Möglichkeit geben. Ich weiß nicht, ob es mit weniger>als einem Grad Genauigkeit funktioniert. Wäre schön wenn ich mind. einen>Wert pro Grad des Servos habe.
Schon mal gerechnet, wie hoch man da zeitlich auflösen muss?
1-2ms = 0-270 Grad
-> 3,7µs/Grad
Macht selbst bei 16 MHz gerade mal 60 Takte.
Such mal im Forum, da gibt es einen 20 Kanal Servogeber, der kann das,
funktioniert aber anders.
MFG
Falk
> Ich habe vor, eine Servosteuerung für 16 Servos zu programmieren.
Dann sei schlau und lass nicht alle Servos zur gleichen Zeit anlaufen,
sondern verteile die Impulse zeitlich nacheinander, du hast offiziell
25msec Zeit, die kann man auch auf 32msec dehnen.
Also ein Timer, ein Servo, 1-2msec seinen Ausgang high, dann der nächste
Servo auf anderem Ausgang mit demselben Timer nur neuem Timerwert.
Denn wenn du bei allen 16 Servos gleichzeitig eine Positionsänderung
auslöst und alle gleichzeitg anfangen Strom zu ziehen, dann bricht deine
Betriebsspannung zusammen.
hmm
also wenn die alle synchron laufen wäre schon recht wichtig und ich hab
mal geschaut wenn sich alle bewegen ohne großartig Gewicht dran sind es
ungefähr 700 mAh. Dafür ist meine Platine ausgelegt. Unter gewisser Last
komme ich grad so an die 2 Ah. das ist zwar kritisch aber noch
schaffbar.
Und selbst wenn ich sie versetzt laufen lasse, habe ich noch nicht das
Problem mit den max 100 unterschiedlichen Servopositionen gelöst.
@ Christian (Gast)
>also wenn die alle synchron laufen wäre schon recht wichtig
Das tun sie auch bei der beschriebenen methode, aber nicht gleichphasig.
>und ich hab>mal geschaut wenn sich alle bewegen ohne großartig Gewicht dran sind es>ungefähr 700 mAh.
Ohne h.
> Dafür ist meine Platine ausgelegt. Unter gewisser Last>komme ich grad so an die 2 Ah.
dito.
>Und selbst wenn ich sie versetzt laufen lasse, habe ich noch nicht das>Problem mit den max 100 unterschiedlichen Servopositionen gelöst.
Doch. Eben weil man bei versetzter Ansteuerung deutlich kleinere
Zeitauflösungen schafft. Praktisch nahezu bis auf den Controllertakt
runter, ggf. etwas mehr. Stichwort Output Compare Funktion und Interupt.
MFG
Falk
Ich weiß nicht, wie du das vorhast?
Soll ich beide OC1A und OC1B nutzen für die Versetzung oder wie?
Mir reicht ansich Pseudocode oder eine Idee. Und wie soll ich die Servos
auf nahezu 16 MHz laufen lassen? wenn die Interruptroutine zu häufig
aufgerufen wird, klappt die Uart nichtmehr, da die ja auch eine Weile
braucht.
@ Christian (Gast)
>Soll ich beide OC1A und OC1B nutzen für die Versetzung oder wie?
Nein, einer reicht. In einem OCR1A Interrupt muss man zwei Sachen
machen.
Pin Nr. X einschalten. Dann nach der gewünschten Anzahl Takte den
Interrupt wieder aktiv werden lassen, im Prinzp so wie bei Soft-PWM.
1
ISR(TIMER1_COMPA_vect){
2
staticuint8_tchannel=0;
3
4
// aktuellen Pin löschen
5
PORTD&=~portvalue[channel];
6
7
// neuen Kanal
8
channel++;
9
if(channel==15)channel=0;
10
11
//neuen Pin setzen
12
PORTD|=portvalue[channel];
13
14
// Pulszeit einstellen
15
16
OCR1A+=(uint16_t)pulsewidth[channel];
17
}
>Mir reicht ansich Pseudocode oder eine Idee. Und wie soll ich die Servos>auf nahezu 16 MHz laufen lassen?
Die Servos kaum, dein AVR schon. Siehe oben.
>wenn die Interruptroutine zu häufig>aufgerufen wird, klappt die Uart nichtmehr, da die ja auch eine Weile>braucht.
Das passt schon, keine Bange. Die Servo-Pulse sind mindesten 1ms breit,
eine kleine Ewigkeit für deinen uC.
MFG
Falk
Eh sry, dass ich dafür einen zweiten Beitrag mache, aber nach der Idee
würde doch dann erst ein Pin angesteuert, nach seiner Zeit also max 2 ms
würde der Nächste usw. Das hieße ich hätte nach max 32 ms alle 16 servos
angesteuert oder? wäre das net bissl viel versetzt wenn der erste 30 ms
vor dem zweiten Servo seine Position anfährt?
@ Christian (Gast)
>würde doch dann erst ein Pin angesteuert, nach seiner Zeit also max 2 ms>würde der Nächste usw. Das hieße ich hätte nach max 32 ms alle 16 servos>angesteuert oder?
Ja.
> wäre das net bissl viel versetzt wenn der erste 30 ms> vor dem zweiten Servo seine Position anfährt?
Jain. Die Servos halten doch ihre Position. Wenn du nicht gerade
superschnelle, hochkomplexe Servobewegungen machen willst, sollte die
versetzte Ansteuerung kein Problem sein.
MfG
Falk