Hallo
ich möchte mit meinem uC ein Servo ansteuern, per Timer / Interrupt
Der Code ist folgendermaßen:
Alle 20ms wird ein Interrupt ausgelöst der dann das Signal, je nach
Einstellung zw. 1 und 2ms lang einschaltet
Thomas P. schrieb:> Funktioniert ohne Probleme...habs schon mit folgendem Programm getestet:
Bin ich blind? Oben bindest du <util/delay.h> doch nicht ein?
Thomas P. schrieb:> Was mache ich falsch?
Läuft der Prozessor wirklich mit der Frequenz, die mit F_CPU angegeben
ist?
Falls du kein Oszi hast, könntest du das testen, indem du einen
1-Sekunden Takt auf einem Pin erzeugst und per LED anzeigen läßt.
> TCCR1B |= 1<<CS11 | 1<<WGM12; //Prescaler: -> 50Hz
Was ist das für ein Vorteiler
> OCR1A = 0x9C40; //Prescaler Settings
Schreibs doch dezmal hin! Dann braucht man nicht lange umrechnen, damit
man deine Einstellung kontrollieren kann. Oder bist du so gut im
Hex-Rechnen?
OCR1A = 40000;
Ohhhh damt... <util/delay.h> einbinden vergessen.....
aber das war trotzdem nicht der Fehler, weil in "rncontrol.h" wird es
bereits verwendet, also bereits eingebunden!
Wie kann ich die Optimierung einstellen?
mfg thomas
> for(i=0;i<pwm_time;i++)> _delay_us(1); //PWM Time warten
die For-Schleife wird hier bereits einen nicht unbedeutenden Anteil an
der Gesamtzeit haben. Die Positionen werden nicht ganz stimmen, aber das
ist jetzt noch nicht das Problem.
Thomas P. schrieb:> Ne, hab kein Oszi :(> Aber ja, CPU läuft mit 16 MHz
Woher weißt du das?
Mit dem Programm
Beitrag "Re: Servoansteuerung mit Timer (ATmega32)"
Nö. Wenn das hier funktioniert und du nicht die 16 Mhz in den Project
Settings angegeben hast (was ich bezweifle, denn dann wüsstest du wo man
den Optimizer einschaltet, ist gleich darunter), dann nicht. Dann läuft
dein µC mit 1Mhz
Ja ich weiß, ich bin Anfänger....
Ja, wie könnte man das sonst lösen? Denn _delay_us bzw _ms lässt keine
variablen zu, nur konstanten und meine PWM Ausgänge am µC kann ich nicht
verwenden, da bereits ein Motortriber verwendet wird...
mfg thomas
Thomas P. schrieb:> Ja ich weiß, ich bin Anfänger....>> Ja, wie könnte man das sonst lösen? Denn _delay_us bzw _ms lässt keine> variablen zu, nur konstanten und meine PWM Ausgänge am µC kann ich nicht> verwenden, da bereits ein Motortriber verwendet wird...
Du hast noch einen 2-ten Compare Match zur Verfügung.
Aber erst mal solltest du dich darum kümmern, ob die 16Mhz tatsächlich
stimmen. Bis jetzt hab ich da aus der Ferne noch kein Vertrauen dazu.
Ich hab ne LED einfach mit 1Hz Blinken lassen....
Also:
1) Wo zum Teufl stellt man die F_CPU in den Project Settings ein?????
2) Wo sind die Project Settings???
3) Ich hab nur die Zeile #define F_CPU 16000000 mitkopieren vergessen...
4) Zur Info: ich verwende AVR Studio 5
mfg thomas
Inwieweit einen zweiten?
Welche Ausgänge sind das?
Ich verwende OC1A, OC1B, TOSC1, TOSC2, T0, T1 und OC für
Frequenzabhängige Anwendungen, was bleibt denn dann noch über?
mfg thomas
Thomas P. schrieb:> Inwieweit einen zweiten?
OCR1B
> Welche Ausgänge sind das?
erst mal gar keine.
Erst mal sind das nur Interrupts, die bei bestimmten Zählerständen
ausgelöst werden.
> 3) Ich hab nur die Zeile #define F_CPU 16000000 mitkopieren vergessen...
Sowas lieben wir hier :-)
Das erleichtert das kontollieren der Einstellungen ungemein, wenn die
Hälfte der relevanten Informationen fehlt :-)
Ja, weißt eh, war mit reiner Absicht ;)
Ok, aber die Interrupts kann ich dann ja auf Ausänge legen oder?
mfg thomas
PS: ich bin totaler Interrupt Anfänger :(
Thomas P. schrieb:> Ja, weißt eh, war mit reiner Absicht ;)>> Ok, aber die Interrupts kann ich dann ja auf Ausänge legen oder?
In den Interrupts kannst du dann ganz normal die Pins schalten, so wie
du das jetzt auch machst.
In der Zwischenzeit hab ich mir im Datenblatt die Prescaler
Einstellungen gesucht. CS11 ist ein Prescaler von 8, mit den 40000
ergibt das die 20ms (eigentlich sollten das 39999 sein, spielt aber
keine Rolle, die 20ms sind sowieso nicht wichtig).
Mach doch in deiner ISR erst mal einfach nur ein _delay_ms(1.5) zwischen
den Port Operationen um zu sehen, ob die for-Schleife dir das Timing so
weit versaut.
mach doch hier
int pwm_time=PWM_NULL; //Globale Variable für PWM HIGH Time
mal ein
volatile int pwm_time=PWM_NULL;
draus.
Wer weiß, was dein Compiler da optimiert.
Thomas P. schrieb:> Jep...es ist die for Schleife...> mit _delay_us(1500); fährts wunderbar in die Mitte ;)>> Was könntn wir da machen?
anstatt eines 1µs delays erst mal ein 10µs delay.
Dafür die Schleifenwiederholungen entsprechend reduzieren.
(Der ganze Ansatz mit dem _delay in der ISR ist nicht zielführend. Da
kannst du dir die ganze ISR auch gleich sparen.)
Thomas P. schrieb:> Ja und wie soll ich das dann lösen?
zb mit 2 Compare Matches.
Der Match auf OCR1A schaltet den Pin auf 1, der Match auf OCR1B schaltet
ihn wieder auf 0
Hier
OCR1A = 0x9C40;
TIMSK |= 1<<OCIE1A;
hast du den Compare Match für den Compare A eingerichtet.
Jetzt schaust du ins Datenblatt, ob das für den Comparematch B genauso
geht und rechnest dir den Wert aus für 1.5ms
Hier
ISR(TIMER1_COMPA_vect)
{
hast du für den Compare Match A die ISR eingerichtet.
Wie wird das dann wohl für Compare Match B aussehen?
In der A setzt du den Pin auf 1, in der B wieder auf 0.
Einfacher als einem Baby den Schnuller klauen.
Karl Heinz Buchegger schrieb:> Einfacher als einem Baby den Schnuller klauen.
Das ist nicht Schnuller klauen, sondern Pferd von hinten durch's Auge
erschießen :D
Das ist Schnuller klauen:
1
// ATMega32@16MHz
2
3
#include<avr/io.h>
4
5
intmain(void)
6
{
7
DDRD=(1<<PD5)|(1<<PD4);// Servo 1 an PD5, Servo 2 an PD4
MWS schrieb:> Karl Heinz Buchegger schrieb:>> Einfacher als einem Baby den Schnuller klauen.> Das ist nicht Schnuller klauen, sondern Pferd von hinten durch's Auge> erschießen :D
[ ] Ich hab weiter oben gelesen, dass er die Pins nicht frei hat, ist
mir aber Wurscht, ich geb meinen Senf trotzdem dazu.
[ ] Ich habs nicht gelesen und muss mich trotzdem einbringen
Karl Heinz Buchegger schrieb:> MWS schrieb:>> Karl Heinz Buchegger schrieb:>>> Einfacher als einem Baby den Schnuller klauen.>> Das ist nicht Schnuller klauen, sondern Pferd von hinten durch's Auge>> erschießen :D>
[ ] Ich hab weiter oben gelesen, dass er die Pins nicht frei hat, ist
mir aber Wurscht, ich geb meinen Senf trotzdem dazu.
[x] Ich habs nicht gelesen und muss mich trotzdem einbringen
Ist doch klar...
Karl Heinz Buchegger schrieb:> [ ] Du hast weiter oben gelesen, dass er die Pins nicht frei hat
Nein, war versteckt, tatsächlich nicht gelesen, wäre vom Eingangspost
her auch nicht davon ausgegangen. Die OC1A..B hängen am LM298 und dienen
dort zur PWM-Steuerung, Timer1 wäre also nicht verfügbar, sollte man die
vernünftig nutzen wollen.
> [X] Ich habs nicht gelesen und muss mich trotzdem einbringen
Hab' ich doch gern gemacht :D
> //Timer 1 - 20ms
TCCR1B |= 1<<CS11 | 1<<WGM12; //Prescaler: -> 50Hz
OCR1A = 40000; //Prescaler Settings
TIMSK |= 1<<OCIE1A;
//Timer 2 - 1.5 ms
TCCR1B |= 1<<CS10 | 1<<WGM12; //Prescaler -> 666Hz
OCR1B = 24000;
Ähm. Du hast da was falsch verstanden.
Du hast nur EINEN Timer 1.
Der hat aber 2 Stück Compare Match Register (A und B). Wenn der
Timerzählerstand identisch mit dem jeweiligen Compare Match Register
ist, dann wird die ISR ausgelöst.
Zusätzlich hast du dann noch den Timer in den CTC Modus geschaltet,
sodass er beim Compare Match A wieder bei 0 zu zählen anfängt. (Was ja
auch in Ordnung ist)
Das ist dein Setup mit dem du arbeiten musst.
Mit dem A-Compare Match machst du dir deine 20ms und setzt den Pin auf
1. Und irgendwann, während der Timer von 0 bis 40000 zählt, schaltet der
Compare Match B den Pin wieder auf 0. Der Timer zählt aber weiterhin bis
40000.
Nachtrag
Der von mir gezeigte Code lässt sich übrigens problemlos umzustellen,
hab's mal gemacht und das läuft hier mit 2 Servokanälen auf beliebigen
Ports.
Aber ich denke einmal wenigstens Dir, Karl-Heinz, ist das aufgefallen,
Du wolltest wohl lediglich nicht von Deinem Konzept ablenken, kein
Problem für mich.
Karl Heinz Buchegger schrieb:> In der A setzt du den Pin auf 1, in der B wieder auf 0.
Warum verschwendest Du einen Kanal, wenn Du ICR als Top nehmen kannst ?
Reicht dem TO ein Kanal ?
Thomas P. schrieb:> Also ich hab das jetzt mal so umgesetzt:> Timersettings:> //Timer Compare Match A - 20ms> TCCR1B |= 1<<CS11 | 1<<WGM12; //Prescaler: -> 50Hz> OCR1A = 40000; //Prescaler Settings> TIMSK |= 1<<OCIE1A;>> //Timer Compare Match B - 1.5 ms> TCCR1B |= 1<<CS10 | 1<<WGM12; //Prescaler -> 666Hz
gratuliere.
Damit sind deine 20ms zur Makulatur geworden. Und .... 1.5ms sind das
auch nicht.
Du hast nur EINEN Timer. Also willst du den Vorteiler auch nur EINMAL
einstellen! Der Vorteiler gehört zum Timer und nicht zum Compare Match.
Der Compare Match schreit nur "Hier", wenn der Timer einen bestimmten
Zählerstand erreicht hat. Aber die Compare Match Register haben nichts
damit zu tun, wie schnell der Timer zählt.
(Jetzt ist es natürlich blöd, dass du bisher immer deinen Timer-Rechner
zur Berechnung der Konstanten herangezogen hast. Sorry ... aber jetzt
musst du selber ran und dir den Wert für OCR1B ausrechnen. Auf Dauer ist
es immer besser, wenn man versteht was man da tut.)
MWS schrieb:> Aber ich denke einmal wenigstens Dir, Karl-Heinz, ist das aufgefallen,> Du wolltest wohl lediglich nicht von Deinem Konzept ablenken, kein> Problem für mich.
Spätestens nachdem ich auf die Frage nach dem Vorteiler als Antwort
einen Link zu einem Timer-Rechner gekriegt habe, war mir klar, dass der
TO von Timer, sagen wir mal, wenig Ahnung hat.
> Karl Heinz Buchegger schrieb:>> In der A setzt du den Pin auf 1, in der B wieder auf 0.>> Warum verschwendest Du einen Kanal, wenn Du ICR als Top nehmen kannst ?> Reicht dem TO ein Kanal ?
Keine Ahnung. Lass uns erst mal das Ding so wie es ist, über die Bühne
bringen. Er hat schon genug damit zu tun, 2 OCR Register an einem Timer
zu akzeptieren.
Ok...das heißt...ich komm nicht mit ;)
Also wie muss ich das Ganze jetzt machen?
Also ich erzeug mit OCR1A einen Interrupt alle 20ms mit dem ich den Pin
auf HIGH ziehe....
Und mit OCR1B einen der alle 1.5ms (1...2 ms) den Pin auf LOW legt...
also muss es so passen?
Thomas P. schrieb:> also muss es so passen?
Ohne das ich rechne.
Wenn das ...
> OCR1A = 40000; //Prescaler Settings
... 20 Millisekunden sind, dann können ...
> OCR1B = 24000;
... keine 1.5 Millisekunden sein. 24-tausend ist etwas mehr als die
Hälfte von 40-tausend. 1.5 ist aber sicher nicht etwas mehr als die
Hälfte von 20.
Der Timer zählt in 20 Millisekunden von 0 bis 40000. Wie weit kann er
daher in 1.5 Millisekunden zählen? Bzw. Umgekehrt: wie weit muss er
zählen, damit er dafür 1.5ms braucht?
Nja einfache Schlussrechnung:
20ms .... 40000
1.5ms ... 3000
Also so läuft das Ganze ab ;)
Und jetzt funktioniert das auch :D
danke euch allen
Ich werde euch noch mein fertiges Programm mit Steuerung posten!
mfg thomas
Thomas P. schrieb:> also muss es so passen?
Ohne dass ich mein Werk ein weiteres Mal anpreisen möchte, aber fällt
Dir was auf ? :D
MWS schrieb:> ICR1 = 39999; // Wiederholrate 50Hz> OCR1A = 2000; // Servoposition Servo 1, 2000 = 1.0ms> OCR1B = 3000; // Servoposition Servo 2, 3000 = 1.5ms
Thomas P. schrieb:> Nja einfache Schlussrechnung:> 20ms .... 40000> 1.5ms ... 3000>> Also so läuft das Ganze ab ;)> Und jetzt funktioniert das auch :D
Jetzt setzt du noch anstelle der 40000 die Zahl 39999 ein, dann stimmts
auch in diesem Detail noch.
Der Timer zählt (am Beispiel '8')
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2,
Zähl nach, wieviele Zählvorgänge wurden gemacht, um einmal von 0 bis
wieder zur 0 zu kommen? Auch das 'Rücksetzen' von 8 auf 0 ist ein
Zählvorgang. 9 Stück. Also immer um 1 mehr als die größte Zahl. Der
Compare Match muss bei 39999 auslösen, damit für einmal 'Rundum' 40000
Zählvorgänge benötigt werden. OK, der Fehler ist nicht gewaltig groß und
wie gesagt, dem Servo sind die 20ms ziemlich Wurscht.
> Also so läuft das Ganze ab ;)
Genau so läuft das mit einem Timer. Die nächste Stufe wäre das was MWS
vorgeschlagen hat. Die Timerhardware kann nämlich 'ihren' Pin auch ganz
alleine ohne ISR schalten. Aber leider, leider, hast du dir die Pins mit
denen das möglich wäre bereits anderweitig verbaut.
Nichts desto trotz hab ich das Gefühl, dass du jetzt ein bischen besser
verstehst, was man mit einem Timer machen kann und wie man das macht.
Nja, ich habs mi nicht verbaut - hab das RN Control Board, und da werden
diese Pins schon für den Motortreiber verwendet, und den möchte ich auch
nutzen ;)
Ja, um einiges besser :D
Wie versprochen das Programm mit Links/Mitte/Rechts Steuerung fürs RN
Control Board:
> OCR1B = (39999/20000)*pwm_time; //Positionsberechnung
Das ist schlecht.
erstens: du hast wirklich 40000 Zählvorgänge. Also musst du auch mit
40000 rechnen.
zweitens 39999 / 20000 ergibt 1
und nicht 1.99995
d.h. bei der danach folgenden Multiplikation hast du durch die fehlenden
Kommastellen einen gewaltigen Fehler. Wenn pwm_time den Wert 1500 hat,
dann kommt bei deiner Rechnung 1500 raus, wo eigentlich 2999 rauskommen
sollte!
Divisionen immer so weit es geht im Rechenprozess nach rechts
verschieben. Dabei aber mögliche Overflows im Auge behalten! Und in
deinem Fall: kürzen!
-> 4 * pwm_time / 2
-> 2 * pwm_time
das ist dann sogar insofern Spitze, weil eine Multiplikation mit 2 für
den µC ein Klacks ist.
Bei deinen Zahlen geht sich das jetzt gut aus, denn 40000/20000 hätte
auch eine glatte 2 ergeben. Aber bei anderen Zahlen schauts da dann
schon schlechter aus.
Thomas P. schrieb:> hab das RN Control Board, und da werden> diese Pins schon für den Motortreiber verwendet, und den möchte ich auch> nutzen ;)
Und wie machst Du das ? Denn die OC1A..B gehen an den EN-Eingänge des
L239, damit wird offenbar die Leistungsregelung der Motoren über HW-PWM
gemacht.
Dafür würde aber zwingend Timer1 benötigt, den Du ja jetzt anders
verwurstet hast. Wenn Du die Leistung der Motoren noch regeln willst,
müsstest Du also eine Soft-PWM über PD4..5 an den Motortreiber
randengeln. Die dürfte aber anspruchsvoller und vor allem
Leistungs-hungriger als diese Sache hier sein.
Ja ok, wär noch zu verbessern, aber es funktioniert !!
Ich will das Programm auch sozusagen Robotertauglich machen indem ich es
auf die 8 Bit Timer umprogrammiere - und somit sind die Pins ja wieder
frei, oder nicht?
mfg thomas
Thomas P. schrieb:> Ich will das Programm auch sozusagen Robotertauglich machen indem ich es> auf die 8 Bit Timer umprogrammiere - und somit sind die Pins ja wieder> frei, oder nicht?
Das bedeutet jetzt übersetzt was ? Das Programm oben ? Bekommst Du
direkt übersetzt nicht auf 'nen 8Bit Timer, geht allein von der
Auflösung nicht.
Du hast 3000 für 1.5ms bei 16Bit, bei 8Bit wären's bei gleichen
Bedingungen 3000 durch 256 gleich 12, bei 'nem theoretischen Prescaler
von 2048. Der höchste ist 1024, damit hättest Du ca. 16 Stufen für 180
Grad Servodrehung, bist aber mit der Wiederholrate zu schnell, die
meisten Servos packen das. Aber dieser Ansatz wird Dich nicht glücklich
machen.
Thomas P. schrieb:> Direkt schon klar, aber es wird ja wohl möglich sein die ca 180° auf 128> bzw am besten wären 256 Schritte auszudehnen, oder?
Dann versuch doch mal zu rechnen, es gibt Beschränkungen bezüglich der
möglichen Prescaler und schau auch mal was an Wiederholrate raus kommt
und ob Deine Servos da noch mitmachen. Das Beste, was Du direkt bekommen
kannst sind so um die 60 Schritte bei ca. 240Hz Wiederholrate.
Nur so als Anhaltspunkt, das Konzept wie oben lässt sich auf Timer0
umsetzen, 65 Schritte (93-125) von 1-2ms, Wiederholrate ~49Hz, Prescaler
dazu immer während des Betriebs zwischen 256 auf 1024 umschalten. Der
Code dazu ist noch recht einfach, also frisch an's Werk ;-)
Thomas P. schrieb:> Wie muss ich den Code denn ungefähr aufbauen?
Setz' es halt erstmal um den Timer0 herum so auf, dass die Pulslänge
zwischen 1-2ms bei maximal möglicher Auflösung verschoben werden kann,
unabhängig von der Wiederholrate. Kannst ja den Code dann zeigen.
Wenn das geht, dann schaltest Du nach jedem Overflow zwischen dem von
Dir dafür verwendeten und dem maximalen Prescaler hin und her. Wobei der
Pin nicht in der langen Prescalerphase gesetzt werden darf.
Hab's mal gezählt, in den ISR's befinden sich gerade 7 Zeilen aktiver
Code, ist also nix Komplexes.
MWS schrieb:> Wenn das geht, dann schaltest Du nach jedem Overflow zwischen dem von> Dir dafür verwendeten und dem maximalen Prescaler hin und her. Wobei der> Pin nicht in der langen Prescalerphase gesetzt werden darf.
Man könnte auch einfach in einer Variablen die Anzahl der Umläufe
zählen...
STK500-Besitzer schrieb:> Man könnte auch einfach in einer Variablen die Anzahl der Umläufe> zählen...
Klar, es gibt viele Wege nach Rom. Da ich zum Toggeln ein Prescalerbit
teste, brauch ich aber nicht mal 'ne Variable :D
Hallo
Ich habs endlich geschaft :)
Der Code ist im Anhang, funktioniert mit einem Servo. Das ganze reicht
im Moment mal für meinen kleinen "Ketten-Bot". Brauch ich nur zum hin
und her Bewegen des US Moduls
Als nächstes möchte ich mir mit Hilfe eines AVR mit vielen Timern ein
Servo Board realisieren, von dem werdet ihr dann natürlich hören!
Welcher AVR ist dazu am Besten geeignet?
Danke für eure Hilfe!!
mfg thomas
Thomas P. schrieb:> Als nächstes möchte ich mir mit Hilfe eines AVR mit vielen Timern ein> Servo Board realisieren, von dem werdet ihr dann natürlich hören!> Welcher AVR ist dazu am Besten geeignet?
Der gleiche. Nur die Software sieht etwas anders aus...
Du programmierst ein Schieberegister, das bei jedem Überlauf um einen
Schritt weiter geschaltet wird.
Dann brauchst du auch die Umschaltung der beiden Prescaler-Werte nicht
mehr zu realisieren...
Ja, aber das hat noch Zeit ;)
Zuerst muss mal mein Bot fertig werden....
Ich hab jetzt den Code (Annhang) in eine Routine umgebaut und somit
leichter zu handhaben!
Aber welcher AVR ist am besten für ein Servo Board für ca 10 Servos
geeignet?
mfg thomas
Thomas P. schrieb:> Als nächstes möchte ich mir mit Hilfe eines AVR mit vielen Timern ein> Servo Board realisieren, von dem werdet ihr dann natürlich hören!> Welcher AVR ist dazu am Besten geeignet?
Es gibt zwar ATmegas mit 3, 4 oder 6 Timern, aber ich bin nicht sicher,
ob das der richtige Weg ist. Ich glaube, ich würde nur einen Timer
verwenden und in dessen ISR die Pins für die Servos selbst steuern.
Also, PWM von Hand. Das ist gar nicht sooo kompliziert und läuft dann
auch auf den billigsten Mikrocontrollern.
Thomas P. schrieb:> Inwieweit von Hand?> Sozusagen:> if(timer == 0) {alle Pins LOW}> if(timer >= 15000) {PIN1 LOW}> usw...> ??
Im Prinzip ja. Aber natürlich nur im Prinzip, sonst schreibst du dir ja
einen Wolf. :-)
Man kann sowas über Bitmasken machen, die in einer Tabelle stehen. Oder
über Einzelabfragen mit Wertvergleichen. Ich kenn leider deine Anwendung
zu wenig, als dass ich dir zu einer konkreten Strategie raten könnte.
Hallo zusammen,
sorry, wenn ich einfach so anonym dazwischen funke.
@ThomasP.: Professionell ist die Lösung mit Deinem Code überhaupt nicht.
Ein atmega32 kann im FastPWM Mode ohne(!) ISR-Routine ein PWM-Signal
selbständig erzeugen, es frisst keinerlei Rechenzeit vom normalen
Programmablauf!
Du schaltest im Setup auf FastPWM-Mode für z.B. Timer1 und setzt:
ICR1 --> Maximum Counter(=TOP), bis hierher wird gezählt
OCR1A --> MATCH, Umschalten von high auf low
TOIE --> abschalten, Interrupt wird nicht benötigt!
Prescaling und passende Werte für TOP und MATCH mußt Du Dir natürlich
ausrechnen.
OC1A verwendet ausschliesslich Pin PD5 (siehe Datenblatt)!
Ablauf dann:
Count von 0 bis MATCH -> PD5 = HIGH
Count von MATCH bis TOP -> PD5 = LOW
usw.
Um den Servo links/rechts drehen zu lassen, veränderst Du im normalen
Programmablauf einfach den MATCH in OCR1A - fertig!
Eleganter geht's nicht mehr!
Just my 2 cents ;)
Hallo
@FastPWM:
1) Ich bin Anfänger und bin unheimlich stolz drauf gewesen, dass es so
funktioniert hat ;)
2) Geht das nur für Timer1 odr auch für Timer0?
3) Wie soll ich das ohne ISR aufbauen?
4) Falls du es nicht gelesen, von dem ich ausgehe, bei mir ist Timer1 in
verwendung für Motorensteuerung => somit ist auch OC1A und OC1B, also
PD4/5 belegt
Ok, danke für die Tipps, ich werde mal Schaltplan und Grundstruktur
anfertigen und posten!
mfg thomas
FastPWM schrieb:> @ThomasP.: Professionell ist die Lösung mit Deinem Code überhaupt nicht.
Die ist für ein einzelnes Servo absolut ok, wenn man keinen Timer1 zur
Verfügung hat.
> Just my 2 cents ;)
Eher 0 Cents, wenn Du Dir den Thread nur ein klein wenig durchgelesen
hast.
Thomas P. schrieb:> 2) Geht das nur für Timer1 odr auch für Timer0?
Ist es so schwer danach mal im Datenblatt zu gucken?
Timer0 hat auch die Möglichkeit eine PWM zu erzeugen.
Du kannst Timer0 im FastPWM-Modus betreiben.
Ihn mit einer Spannweite von 20ms zu betreiben ist natürlich Unfug.
Wie ich oben schon beschrieben habe:
Betreibe den Timer so, dass du die 2ms am Höchsten auflöst.
Ob das Servo alle 20ms oder mehr oder weniger häufig angesprochen wird,
war meinen Servos bis jetzt egal (je länger die Pause ist, umso
schwächer wurde es).
Ja natürlich ist es nicht schwer, aber
1) keine Lust :b
2) Mein Programm läuft für ein Servo perfekt ;)
3) Bin ich im Moment nicht neugiereig drauf um auf 400 Seitn 3 Sätze rus
zu suchen
Aber gut, dass machn wir ein anderes Mal, dann wenn ich das Servo Board
angehe ;)
mfg thomas
Thomas P. schrieb:> 1) keine Lust :b
Kenne ich von mir auch. Ich hab aber nicht gefragt...
> 2) Mein Programm läuft für ein Servo perfekt ;)
Bis zur ersten Erweiterung.
> 3) Bin ich im Moment nicht neugiereig drauf um auf 400 Seitn 3 Sätze rus> zu suchen
Schon mal die Suchfunktion des Acrobat Reader's ausprobiert?
Schon mal das Inhaltverzeichnis angesehen?
Deine Entscheidung.
Wieso solls dann nicht mehr funktionieren?
Mein Roboter soll folgendes können:
fahren und nicht anfahren - aus und fertig :b
so was wie Linienverfolgung, Kamera, Funk usw. soll erst später kommen,
dannn aber auch miit anderen Funktionen wie Greifarm usw.. Aber dann
muss sowieso eine komplett andere Elektronik her...aber das hat noch
Zeit!
Ja die kenn ich ;)
mfg thomas
Thomas P. schrieb:> @FastPWM:> 1) Ich bin Anfänger und bin unheimlich stolz drauf gewesen, dass es so> funktioniert hat ;)
Das ist doch auch völlig OK - jeder hat wahrscheinlich so mal
angefangen.
> 2) Geht das nur für Timer1 odr auch für Timer0?
siehe Datenblatt - alles vorkauen möchte ich hier nicht, vielmehr möchte
ich nur Tipps geben für eine evtl. in Frage kommende, bessere Lösung.
> 3) Wie soll ich das ohne ISR aufbauen?
Wie gesagt, für einige Servos lässt sich das einfacher und ohne ISR
bewerkstelligen. Daß es möglich ist, habe ich skizzenhaft angedeutet,
den Rest müsstest Du (aus meiner Sicht) selbst erarbeiten. Für mehrere,
z.B. 10 Servos ist die Frage, welchen Microcontroller man verwenden
will. Natürlich hat dann auch das bereits vorgeschlagene Software-PWM
seine Berechtigung, wenn es nur ein kleinerer Controller sein soll.
> 4) Falls du es nicht gelesen, von dem ich ausgehe, bei mir ist Timer1 in> verwendung für Motorensteuerung => somit ist auch OC1A und OC1B, also> PD4/5 belegt
Es ist eine Designfrage: Muß PD4/5 unbedingt belegt werden oder kann
dasselbe nicht auch an anderen Pins bewerkstelligt werden? Vor allen
Dingen gibt es ja auch noch andere Timer (und Counter!). wobei zu prüfen
wäre, was die jeweils können.
Grundsätzlich wollte ich lediglich auf die Möglichkeit der völlig
eigenständig laufenden PWM hinweisen. Zu diskutieren gibt es da
eigentlich nichts - es steht ja auch alles im Datenblatt. :)
... just my 0(!) cents. ;)
Hallo
Ok, ich werd mich in nächster Zeit damit beschäftigen
Also nochmals zu 4)
Die Pins sind am aktuellen RN-Control Board belegt (fix)
Bei einem selbstgebauten Servocontroller dann nicht, aber das ist dann
ein anderes Thema....
bis dann ;)
mfg thomas