Hi,
mein Nick "Uboot-Stocki" sagt eigentlich alles. Ich beschäftige mich mit
Modellbau. Für mich ist natürlich u.a. die Ansteuerung von Servos mit
AVRs besonders interessant. Ich habe für dieses "Problem" auch schon
mehrere Lösungen mittels Timer gebaut und erfolgreich getestet (siehe
u.a. Codesammlung).
Vor ein paar Tagen habe ich hier im Forum einen Beitrag über die
Ansteuerung eines Servos mittels PWM-Timer-Features gelesen (Dummerweise
finde ich den Link gerade nicht).
Bisher war ich der Meinung das geht mit den AVR-Timern nicht, weil die
erforderlichen Signale zu lang sind ?!
Frage:
Ist es Möglich (beliebiger AVR - idealerweise Tiny26) mittels
Timerkonfiguration (PWM, Compare was auch immer) ein Signal für einen
Servozu erzeugen (Frequenz: 50Hz, Impulsbreite 1-2ms) ????
Bisher habe ich immer die Signale über mehrfache Timerumkonfiguration
innerhalb eines Zykluses erzeugt. Das geht zwar, ist aber im Vergleich
mit HW-Features nicht elegant ...
Gruß
Uboot-Stocki
Hi Uboot-Stocki,
ja, das geht. Ich selbst mache etwas ähnliches und der Softwarestand ist
derzeit folgender:
Frequenz = variabel von 10Hz - 3000Hz getestet
P/P Verhältnis einstellbar von 1 - 99% getestet
zur Zeit läuft das noch im Lochrasteraufbau folgendermassen: Frequenz
wird durch einen Dezimalwert im Programm vorgegeben und eine Routine
errechnet dann je nach Encoderstellung das P/P Verhältnis. Ausgabe dann
auf PD5. Bei höheren Frequenzwerten (>1KHz) gibt es leider noch kleine
Probleme mit der Abstufung, die Frequenz wird kurzzeitig instabil. Wird
noch dran gearbeitet.
Als Controller benutze ich einen 8515.
Bei der PWM Endstufe (Mosfet) bin ich noch am testen und werde das
Ergebnis mal zur Diskussion hier ins Forum stellen.
Gruß,
Günter
Hi,
ich bin mir da im Moment nicht so richtig sicher, ob und wie das geht:
Wenn ich die 20ms Impulslänge mit meinem 8 BIT-Timer "abfrühstücken"
möchte bedeutet das 20ms/255=100µs. Dies liefert mir für meinen
Servo-Impuls von 1-2ms nur 10 Schritte Auflösung was entschieden zu
wenig ist. Das Servo hätte dann nur 10 verschiedene Stellungen.
Ich möchte die vollen 8Bit des Timers haben, um mein Servo zu
verstellen. Damit der Servo-Weg (1ms -> Servo rechts, 1,5ms -> Servo
mitte, 2ms -> Servo links) optimal kontrolliert werden kann, brauche ich
da 255 Schritte.
Ein 8-BIT-Timer scheidet also aus ...
Gibts das auch mit 16 BIT ?
Gruß
Uboot-Stocki
Hallo Zusammen,
Ich finde eure Diskussion sehr interessant, da auch ich mit dererlei
Problemen herumschlage. Ich möchte für einen Roboterantrieb auch Servos
benutzen und habe als µController den SAB80c537. Der hat einen
unabhängigen Capture/Compare-Timer - 16bit breit, und kann bis 50okHz
bei 12MHz takt. Mein Problem hierbei ist Programmierung dieser Einheit,
könnt ihr mir da helfen?
mfg Rainer
Hi UBoot
Ich hatte vor ein paar Tagen einen Beitrag darüber geschrieben,
vielleicht meinst du ja den
http://www.mikrocontroller.net/forum/read-2-30705.html
Ich hab mich jetzt mal ein bisschen in die Materie eingearbeitet und bin
zu dem Schluss gekommen, das die Servoansteuerung mit PWM nicht
geht.(Wenn doch einer weiss wie's geht bitte Sourcecode mit Erklärung
schicken.
Es sollen mindestens 2 Kanäle angesteuert werden.
Man kann mit der PWM (16 bit Timer) immer nur feste Frequenzen ausgeben,
nach folgender Formel:
8bit/9bit/10bit
F(PWM)=(F(Quarz)/(510,1022,2046)) /Vorteiler(1,8,64,256,1024)
Also bei 8MHZ
8bit 15686-1960-245-61-15 HZ
9bit 7827-978- 122-30- 7 HZ
10bit 3910-488- 61- 15 3 HZ
Und die Auflösung ist auch nicht so "töfte"
z.B Bei 10bit mit Vorteiler 256 ->
Top Wert des Zählers =1023 FRQ = 32250HZ
1Takt dauert also 1/32250 =0,000032 s =0,0032ms
bei einer Pulslänge von 1-2 ms ergibt sich eine Auflösung von
31.25 Takten.
Wie gesagt ich lasse mich gerne eines besseren belehren aber bitte mit
Sourcecode oder wenigstens ein Erklärung.Nicht nur einfach sagen ja es
geht.
Vielleicht hat ja einer ein Bsp. mit wenigstens 2 Kanälen wenns geht in
C. Ich hab nur Beispiele mit sleep Befehlen gefunden, ist so nicht
akzeptabel weil noch andere Aufgaben nebenbei erfüllt weden sollen.
Ich arbeite z.Z auch daran wenn ich ein Lösung gefunden habe stell ich
den Code mal in die Codesammlung.
Tach auch du ungläubiger Toto,
ich habe mal eine PWM-Routine geschrieben die ich zur Steuerung von
Motoren verwenden will. Fakt ist, das die Routine noch nicht so ist wie
ich sie brauche aber zum Verständnis und zur weiteren Verarbeitung soll
es reichen.
Die einzelnen Programmteile:
1. Routine "Initial:
Standardinitialisierung und Timer 0 aktivieren, Interruptfreigabe
2. Routine "main:
Aus den Werten "Frequenz" und dem Wert "Startwert" wird ein minimales
Puls / Pausenverhältnis festgelegt.
Der Wert für den Zahlenwert "Frequenz" errechnet sich aus
fquarz/Teilerverhältniss/gewünschte Frequenz. Das ergibt einen Wert von
6250 Wert für 80Hz.
In der Software ist ein Wert von 6240 eingetragen. Das hat den Grund,
weil ein Drehencoder mit 24 Rastungen (Stufen/Umdrehung) an PB0 / PB1
angeschlossen ist (activ low).
Der Frequenzwert sollte daher auch durch 24 teilbar sein. Nächster Wert
ist dann also 6240. Die Frequenz liegt daher etwas unter 80Hz.
in den Zeilen
ldi dv16ul,low(24)
ldi dv16uh,high(24)
kann ich die Auflösung festlegen. Bei einem Wert von 24 entspricht das
+delta Pause/step = $104. Um den gleichen Betrag ändert sich dann auch
in umgekehrter Richtung die Pulszeit.
In "Main" erfolgen dann die Unterprogrammaufrufe zur Berechnung der
Puls- und der Pausenzeit.
Die Programmaufrufe "4. unterer Grenzwert..." und "5. oberer
Grenzwert..." dienen in diesem Moment noch zur Festlegung der Startwerte
und sind für den endgültigen Zweck reserviert.
Nach Abschluss der Berechnungen (Division, Multiplikation und Pulszeit)
in "Main" wird die PWM-Routine mit den Werten für Lowbyte Pause (SRAM
$61),Highbyte Pause (SRAM $60), Lowbyte Puls (SRAM $63) und Highbyte
Puls (SRAM $ 62) gestartet.
3. Routine "Start PWM":
Ich denke, hier brauch es keine groben Erklärungen.
4. Routine "timer1compa":
Auch hier meine ich, die Sache ist selbsterklärend.
Generell ist ja zu den Routinen "Start PWM" und "timer1compa" zu sagen,
da nach Ablauf der Pausenzeit ein Interrupt ausgelöst wird und die
Pulszeit beginnt. Die Festlegung des Verhältnisses erfolgt wiederum
durch die Rechenroutinen.
Was ist noch zu sagen, es handelt sich um (noch) einen groben Entwurf.
Auch was zur Bedienung falls es jemand testen will: Liegt PB1 auf "H"
wird ein Pegelwechsel von H->L an PB0 als "aufwärtszählen gewertet = P/P
wird erhöht.
Liegt PB1 auf "L" wird ein Pegelwechsel von H->L als abwärtszählen
interpretiert, P/P wird also erniedrigt.
Ach ja, die "include-Zeile" muss natürlich auch geändert werden wenn die
VMLAB Software nicht vorhanden ist.
Die Grundgedankenken zu Lösung diese Problems stammen übrigens aus dem
Trampert Buch "AVR-RISC Microcontroller" und aus den AVR Datenblättern.
Auch dieses Forum hat zum Gelingen beigetragen.
Gruß,
Günter
@TOTO:
ich habe mir nochmal deinen Beitrag vom 11.6. intensivst durchgelesen
und bin eigentlich zu einem doch etwas erschütternden Ergebnis gekommen:
du forderst hier offensichtlich eine Komplettlösung.Aber die kannst du
doch nur bekommem, wenn du ein wenig dazu beiträgst. Es ist schön wenn
du deine Wünsche mathematisch begründest, erklärst wie es sein soll,
aber nicht weisst wie es geht.
Du hättest doch mal deinen Code (VMLAB) hierrein setzen können. Oder mal
sagen, welche Version du hast (VMLAB hatte ein Timerproblem, ist aber
mit V3.7 behoben), jedenfalls tritt es da nicht mehr auf.
Nur mal so zum Beispiel: ich hatte eine mit VMLAB nichtfunktionierende
Routine geschrieben, Hardwareanbindung und so war alles O.K.. Trotzdem
funzte es nach programming, obwohl VMLAB immer Fehler meldete.
Aber was solls,
Rückfrage an "AMTOOLS" = known error 2.4, please download actuall
version!
Toto, in dieser Group sind so viele tolle Leute drin, irgendwie passt da
alles zusammen. Versuche daher nicht, dich in irgendeiner Form zu
separieren.
ich Grüße dich,
Günter
Hallo ,
hab mir das Problem gestern mal mit Bascom angeschaut und
muss sagen dass die Routine für die Modellbau-Servos super
funzt. (geht bis 16 Servos an einem Controller)
Nachfolgend ein ganz kleines Bascom Prog.
Im Anhang das dazugehörende OBJ-File, könnt Ihr mal
disassemblieren mit AVR-Studio , villeicht hilfts euch.
$regfile = "2313def.dat"
$crystal = 9216000
Ddrb = &B11111111
Config Portb = Output
Config Servos = 1 , Servo1 = Portb.0 , Reload = 10
Enable Interrupts
Servo(1) = 120
Do
Loop
End
Gruss Gerhard
Hi @all
ich hab mir jetzt auf Umwegen eine Lösung gebastelt mit der es
möglich ist mit Hardware PWM Servoimpulse auszugeben.Es
können 2 Servos unabhängig voneinder angesteuert werden.
Das Bsp. wurde mit dem Codevision AVR C Compiler(Vers.1.23.8c)
erstellt und mit dem Visual MicroLab simuliert(Vers. 3.6)
Wer Intresse hat kann ich mal die kompletten Datein zum simulieren
schicken.
Die Auflösung ist noch sehr gering ~31 Schritte,was für meine
Zwecke ausreichend ist,weil ich nur eine Geschwindigkeitsseuerung
brauche keine Positionssteuerung.
Müsste aber durch einen kleineren Vorteiler der Quarzfrequenz
besser werden.
Ist noch nicht perfekt, der erste Impuls ist zu lang
(20ms), ich weiss noch nicht woran es liegt.Danach werden Impulse aber
korrekt ausgegeben und die Frequenz stimmt auch.
Die Frequenz und Impulslänge sind in bestimmten Grenzen variabel.Bevor
einer fragt, das Projekt ist noch nicht fertig
es werden im Moment noch feste Imulslängen ausgegeben,lassen sich aber
über den Compwert A und B ändern.
Die genauen Zusammenhänge der Frequenz und Impulslängen mit den im Bsp.
angegebenen Werten ist mir noch nicht ganz klar,da
muss ich mich wohl doch mal mit der Assemblerprogrammierung auseinander
setzen.
@ den erschütterten Günther König
wenn ich hier jemanden auf den Schlips getreten bin, tut'
mir leid.
Vielleicht kanns du mir ja nochmal erklären was ich schlimmes
verbrochen habe. Ich hab hier weder jemanden beleidigt oder persönlich
angegriffen.
Bisher dachte ich auch immer so ein Forum ist zum gemeinsamen
Erfahrungsaustausch da.Und wenn jemand das selbe Problem schonmal gelöst
hat warum sollte er den Code nicht ins Forum stellen.
Und das ich hier nur schmarotzend auf eine fertig Lösung warte
stösst mir auch ziemlich sauer auf. Ich arbeite erst seit 1 Woche mit
den AVR's und hab soviel Grundlagen zur Lösung ins Forum gestellt wie
ich konnte.
Wenn ich wüsste wie es geht, hätte ich nich schreiben müssen.
So,jetzt will ich mich aber nicht weiter separieren
mfG
Toto
Hi Toto,
bei deinem Beitrag vom 11.6. störte mich irgendwie die folgende Aussage:
----------
Ich hab mich jetzt mal ein bisschen in die Materie eingearbeitet und bin
zu dem Schluss gekommen, das die Servoansteuerung mit PWM nicht
geht.(Wenn doch einer weiss wie's geht bitte Sourcecode mit Erklärung
schicken.
Es sollen mindestens 2 Kanäle angesteuert werden.
Man kann mit der PWM (16 bit Timer) immer nur feste Frequenzen ausgeben,
nach folgender Formel:
8bit/9bit/10bit
F(PWM)=(F(Quarz)/(510,1022,2046)) /Vorteiler(1,8,64,256,1024)
----------
Es ist die Sicherheit gewesen mit der du etwas ausschliesst von dem du
keine Kenntniss hast. Forderst aber im gleichem Atemzug eine Lösung für
dein spezielles Problem.
Mag sein das ich überreagiert habe, tut mir leid.
Es grüsset dich,
Günter
Hi Günter
Erstmal danke für deine Antworten und deinem Sourcecode.
So stelle ich mir einen vernünftigen Beitrag vor.
Werde mich da mal durchwurschteln.
Nochmal zu deiner Aussage das ich mit Sicherheit ausschliesse das es
nicht geht.
Zitat:
Wenn doch einer weiss wie's geht bitte Sourcecode mit Erklärung
schicken.
Zitat ende.
Ich habe nur gesagt das >"ich"< zu dem Schluss gekommen bin.
Aber lassen wir die Haarspaltereien.Hat sich um ein Missveständnis
gehandelt.Also ich freu mich über jede Antwort die mir hilft.Und ich
lasse mich gerne eines besseren belehren wenn ich falsch liege.
Also zurück zum eigentlichen Sinn des Forums.
mfg
Toto