Hallo Zusammen, Bin ganz frisch hier im Forum, also zuerst mal Grüße an alle! Ich habe eine kleine Herausforderung zu bewältigen. Vorweg: Ich habe schon mehrere Tage das Net und das Forum hier durchsucht bevor ich den Beitrag aufgemacht habe. Kurze Beschreibung: Aufgabe: Mir steht ein PIC16F874 zur Verfügung, mit dem ich 3 Servos individuell ansteuern möchte. Meine Lösungsvorschlag: Die PWM - Steuerung auf einen externen PWM - Baustein auslagern. Mit dem PIC über I2C den Baustein ansprechen und den gewünschten Duty-Cycle in dessen entsprechende Register schreiben . Dann den gewünschten Servo über den PWM - Baustein ansteuern. (Rein prinzipiell, kein Anspruch auf Details). Mein grundsätzliches Problem: Passenden PWM - Baustein finden. Bin hier im Forum auf massenhaft Artikel über PWM - Bausteine gestoßen, sehr oft wurden PCA9634 und PCA9685 genannt. Dies sind allerdings LED - Treiber. Was meiner Meinung rel. egal ist, da ich die benötigte Leistung dann über den Treiber zur Verfügung stelle. Beim PWM - Baustein ist mir rein die Pulsung wichtig. Meine Frage: Weiß jemand hier im Forum noch weitere, geeignete Bausteine mit denen sich über I2C Pulsweiten vorgeben lassen? 3 Ausgangskanäle (eben für die 3 Servos) würden reichen. Vielen Dank für Antworten, Dumbledore
Wo ist das Problem einfach 3 Ausgänge als SoftPWM anzusteuern? Ist wahrscheinlich weniger Aufwand als I2C zu programmieren.
Hallo, zuerst mal Danke für ihre Antwort. Ich möchte die Realisierung aber gerne über Hardware - PWM machen, zusätzlich bin ich in Sachen Soft - PWM ein Greenhorn :-/ Mfg, Dumbledore
Michael B. schrieb: > Hallo, > > zuerst mal Danke für ihre Antwort. > Ich möchte die Realisierung aber gerne über Hardware - PWM machen, Ist doch viel komplizierter als mit Software > zusätzlich bin ich in Sachen Soft - PWM ein Greenhorn :-/ Dann musst du dich weiterbilden. Alles was du brauchst ist ein Timer, der über einen Compare-Match Interrupt verfügt. Dann kannst du ohne Probleme bis zu 10 bis 12, wahrscheinlich auch noch ein paar mehr (Servos sind nicht sehr heikel), Servos ansteuern. Belastung für den µC: irgendwo im Promillebereich. Wenn du Timergesteuert eine LED blinken lassen kannst und die Blinkzeit über den Compare-Match Interrupt durch Verändern des Compare Wertes einstellen kannst, bist du schon fast dort. Die 'Blinkzeiten' sind bei Servos einfach nur ein wenig schneller als das was bei einer LED sinnvoll ist. Mehr musst du im Grunde nicht können, der Rest ist einfach nur ein wenig Organisation im Programm.
...im übrigen macht es für diese Anwendung keinen Sinn, drei Hardware-PWMs aufzubauen: Es reicht ja sogar, wenn man reihum den drei Servos die jeweils passende Pulsbreite verabreicht. Servos sind ja für den Einsatz im Umfeld RC designt und hier kommen die Werte für die Pulsbreite gezwungenermassen nacheinander. Für die Erzeugung der passenden Pulsbreite könnte man folgendes tun: 1) Simple Warteschleife (Jitter durch Interrupts) 2) Warteschleife mit Timer (per Interrupt oder auch ohne) 3) PWM des Prozessors per Singleshot. Zur Weiterleitung des Pulses an den passenden Servo könnte man den Puls über jeweils ein Gate (UND-Gatter)leiten.
Danke auch für die weiteren Antworten. Habe mir nochmal Gedanken über die Sache gemacht. Ihr habt mich umgestimmt, werde mich jetzt wohl mit Soft - PWM versuchen. Vom Prinzip her hatte ich das schon verstanden, wollte aber an meiner Hard - PWM festhalten. Nachdem aber solche IC´s echt schwer zu bekommen sind (nach LANGER Suche bei Futureelectronic und Digi-Key für PCA 9685, falls sie doch jemand kaufen möchte) denke ich ist der Aufwand für Software - PWM tatsächlich geringer. Werde mal meine Ergebnisse und Fortschritte posten. Danke für die "Beratung" :-) Dumbledore
@ dumbledore Wenn du noch Interesse daran hast: Ich habe mal mit einem PIC16F883 10 Servos angesteuert. Könnte dir ja das asm-file mal zukommen lassen.
> mit dem ich 3 Servos individuell ansteuern möchte.
Das ist spotteinfach und macht ein uC quasi im Leerlauf,
an beliebigen 3 Pins Impulse von 1-2 Millisekunden Länge
auszugeben, die er alle 25 Milisekunden wiederholt.
Das kann man sogar in BASIC programmieren und man braucht
auch keine Hardwaretimer oder PWM-Funktionsgruppen im uC
dafür.
Falls der uC nach was anderes machen soll (z.B.
Lagestabilisierung eines Flugzeugs) kann es sinnvoll sein,
die Zeit mit einem zentralen Hardwaretimer des uC mitzuzählen,
dann muß er nicht bei allen Sachen darauf achten wie lange
sie dauern, sondern kann immer mal nachgucken ob es schon
"Zeit" ist.
@ Erhard: Danke für das Angebot, gerne. Schick mir mal ne Nachricht mit deiner Mail -Adresse. @MaWin: Ja, ich hab mir mal die Sache überlegt, ist wirklich rel. simpel. Ich kann die meisten Features des PIC im Schlaf, nur über SW - PWM hatte ich mir keine Gedanken gemacht. Auf jeden Fall was gelernt. Schönen Abend, Dumbledore
@ dumbledore Bin leider nicht angemeldet, kann somit deine E-Mail nicht in Erfahrung bringen.
Hallo wieder, muss doch nochmal einhaken: Wollte zum Test auf 2 Pins 2 verschiedene Pulsweiten - Signale ausgeben: Der Timer ist so eingestellt, dass er alle 1.02ms überläuft void main() { init(); TMR2ON = 1; for(;;) { if (TMR2IF) // Wenn Timer überläuft, setze beide Kanäle auf High { RA0 = 1; RA1 = 1; TMR2IF = 0; } if (TMR2 == Dauer1) // nach 576us RA0 Low setzen { TMR2ON = 0; RA0 = 0; TMR2ON = 1; } if (TMR2 == Dauer3) // nach 128us RA1 Low setzen { TMR2ON = 0; RA1 = 0; TMR2ON = 1; } } } Hab je einen Pin an einen Oszi - Kanal gehängt, sowohl die Pulsdauern als auch die Periodendauer des Timers stimmen optimal (+/- 1us). Stelle ich jedoch für die Dauern andere Zeiten ein (egal ob kleiner oder größer), stimmt gar nichts mehr: Periodendauer falsch, Pulsdauer falsch. An was kann das liegen? Ist meine ganze Umsetzung falsch? Das TMR2ON = 0 oder 1 dient zum Starten / Stoppen des Timers, ohne diese Befehle funktioniert es nicht. Meine Vermutungen: - Code ist in C zu träge, ich muss es in Assembler machen (?) - Geht nur mit Interrupts (nach Aussage von MaWin oben ja nicht, er sagt ja ich bräuchte nicht mal HW - Timer) (?) - Ich bin zu dumm Für Hilfe bin ich dankbar, Dumbledore
Dumbledore schrieb: > An was kann das liegen? Ist meine ganze Umsetzung falsch? Ich denke schon. Dein Timer kann doch sicherlich auch Interrupts generieren? Das Problem ist, dass du hier im Forum nicht sehr viele finden wirst, die deinen Prozessor kennen. D.h. deine Zuweisungen an irgendwelche Register sind für die meisten hier 'böhmische Dörfer'. > Das TMR2ON = 0 oder 1 dient zum Starten / Stoppen des Timers, > ohne diese Befehle funktioniert es nicht. Das ist nicht logisch. Ob du einen Portpin auf 0 oder 1 setzen kannst, kann ja nicht davon abhängen ob ein Timer läuft, solange der Pin nicht irgendwie hardwaremässig mit diesem Timer verknüpft wurde (der Timer zb eine PWM auf diesem Pin generiert). Selbst wenn ich deinen Prozessor nicht kenne, traue ich mich das aus der holen Hand heraus zu behaupten. > Meine Vermutungen: > - Code ist in C zu träge, ich muss es in Assembler machen (?) Quatsch. Wie schnell tickt denn dein Timer? Gibt es da so etwas wie einen Prescaler? Wie ist der von dir eingestellte Zusammenhang zwischen Taktfrequenz und Frequenz mit der der Timer zählt. Aber wenn du der Sache nicht traust, kannst du ja mal so ersetzen
1 | if (TMR2 >= Dauer1) |
dann bist du nicht darauf angewiesen, dass dein Programm genau dann den Timer begutachtet, wenn er exakt den richtigen Wert hat. Ein bischen später reicht auch. > - Geht nur mit Interrupts (nach Aussage von MaWin oben ja nicht, er sagt > ja ich bräuchte nicht mal HW - Timer) (?) Interrupts sind nicht unbedingt notwendig. Aber sie vereinfachen die Dinge meistens.
Hallo Karl - Heinz, habe mein Programm nochmal überarbeitet. Bin auch darauf gestoßen, dass die Abfrage if(TMR2 == Dauer1) der Fehler war. Mit if (TMR2 > Dauer1) funktioniert es. Damit spare ich mir, wie du schon richtig angemerkt hast, das unnötige Starten und stoppen des Timers. Nun funktioniert es bestens mit Genauigkeit +/- 3us. Danke, Dumbledore
@Erhard Vielleicht könntest du mir den Code einfach hier rein posten, mir reichen zwar keine 10 Servos, aber es wäre cool so was mal Professionell gemacht zu sehen, ich hab das schon mal hin bekommen... aber leider nur mit zuckeln und ruckeln... Vielen Dank im Voraus... @kbuchegg <quote> Alles was du brauchst ist ein Timer, der über einen Compare-Match Interrupt verfügt. *-was macht ein solches Compare-Match?* Dann kannst du ohne Probleme bis zu 10 bis 12, wahrscheinlich auch noch ein paar mehr (Servos sind nicht sehr heikel), Servos ansteuern. Belastung für den µC: irgendwo im Promillebereich. Wenn du Timergesteuert eine LED blinken lassen kannst und die Blinkzeit über den Compare-Match Interrupt durch Verändern des Compare Wertes einstellen kannst, bist du schon fast dort. Die 'Blinkzeiten' sind bei Servos einfach nur ein wenig schneller als das was bei einer LED sinnvoll ist. Mehr musst du im Grunde nicht können, der Rest ist einfach nur ein wenig Organisation im Programm. *Hat ein PIC von Microchip so ein ding?* Gruß Saimen
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.