Forum: Mikrocontroller und Digitale Elektronik Allgemeine Fragen zu PWM


von UBoot-Stocki (Gast)


Lesenswert?

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

von Günter König (Gast)


Lesenswert?

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

von UBoot-Stocki (Gast)


Lesenswert?

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

von Günter König (Gast)


Lesenswert?

Jo,
ich mache das mit dem 16bit Timer. Den 8bit Timer benutze ich nur zur 
Auswertung des Drehencoders.

Gruß,
Günter

von Rainer Hübner (Gast)


Lesenswert?

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

von Toto (Gast)


Lesenswert?

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.

von Günter König (Gast)


Angehängte Dateien:

Lesenswert?

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

von Günter König (Gast)


Lesenswert?

@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

von Gerhard (Gast)


Angehängte Dateien:

Lesenswert?

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

von Toto (Gast)


Angehängte Dateien:

Lesenswert?

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

von Günter König (Gast)


Lesenswert?

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

von Toto (Gast)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.