PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Motor PWM 19KHz?



RolfD
15.08.2012, 15:06
Hallo,
nach einem tieferen Blick in die Motorsteuerung vom RP6 komme ich ins stutzen...
Dort wird FastPWM mit Vorteiler 1 und einem ICR1 von 210 aufgesetzt, OCR1xL legt dann das Pulsverhältnis fest.
Das soll dann eine PWM Frequenz von 19KHz ergeben denn ICR1 legt zusammen mit dem Vorteiler 1 ja die komplette Impulslänge fest.

Für Dummies wie mich wird das hier: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=78780&start=0 auch noch mal genau beschrieben.



1. Look at table "Waveform Generation Mode Bit Description" in Timer1 section of the datasheet. Pwm mode is chosen with bits WGM13:10. Let us set mode 14, fast pwm.
Code:

TCCR1A.WGM10 = 1
TCCR1A.WGM11 = 1
TCCR1B.WGM12 = 1
TCCR1B.WGM13 = 0

In the same table you can see TOP=ICRn. We use timer1, so Top will be ICR1.

2. Set frequency.
Timer with no prescaler inrements in every period of the oscillator frequency (20 MHz here).
40 kHz is 500 times less than 20 MHz. So we need 500 steps of timer for 1 period of 40 kHz signal.
Code:
ICR1 = 500

.
3. Set duty cycle 25%.
See table "Compare Output Mode, Fast PWM".
Here we set levels of the output.
Use "Clear OCnA/OCnB on Compare Match, set OCnA/OCnB at BOTTOM".
Duty cycle is set with output compare register OCR1A.
Code:
TCCR1A.COM1A1 = 1
TCCR1A.COM1A0 = 0
OCR1A = 125 ( = 25% of ICR1)

The frequency output is on the pin OC1A.

4. Set OC1A as output and start timer1.
Code:

DDRD.5 = 1
TCCR1B.CS10 = 1



Function:
Timer1 starts counting from 0. OC1A is high.
After timer reaches value of OCR1A, OC1A goes low.
After timer reaches value of ICR1 (Top), timer resets and OC1A goes high.


Berechne ich aber die üblichen 8MHz und ICR1 = 210 mit diesem Beispiel, komme ich auf ca. 38 khz .. und nicht 19 Khz.
Für 19 KHz bzw. 19000 pwm Zyklen/sec müsste ICR1 = 421 haben denn 421x19KHz ergibt 7999000... nicht 210x19KHz

Meine Frage daher.. ist das Beispiel da falsch, hab ich mich wo verrechnet... oder läuft unsere MotorPWM tatsächlich mit 38KHz statt mit 19 KHz wie in der Docu beschrieben?

Irgendwie sieht mir das eher nach einer Steuerung zum dimmen von LEDs aus, muss die Frequenz tatsächlich so hoch sein?
Werden die Motoren dadurch nicht zu Ultraschallquellen? Reichen PWM Frequenzen von 50-400 Hz nicht auch aus? (selbst auf die Gefahr hin, das die Motoren dann "brummen" oder "singen" wie z.B. moderne Eloks es auch tuen)

Für Motoren mit kleinen Induktivitäten wie unsere braucht man grundsätzlich hohe Frequenzen? Das ist so die Schlußfolgerung, die ich aus diversen Beiträgen rauslese.. dort spricht man aber üblicherweise von 8-16 und max 32 khz.

Ich wüsste halt gerne, ob man die Motor PWM Taktung runter setzen und dann ggf. durch eine SoftwarePWM laufen lassen kann.
http://www.mikrocontroller.net/articles/Soft-PWM
Für so hohe Frequenzen ist das jedoch recht ineffizient.

LG Rolf

radbruch
15.08.2012, 16:38
Hallo

Das ist das Setup des Timers beim RP6:

Mode 10, Phase Correct mit ICR1 als Top ergibt bei ICR1=210 ca. 8MHz/420=19047,6Hz

Hier betreibe ich damit eine Servoansteuerung:
https://www.roboternetz.de/community/threads/46512-2-Servos-gleichzeitig-ansteuern-geht-das-nur-mit-Stopwatches?p=447000&viewfull=1#post447000

Gruß

mic

RolfD
15.08.2012, 17:57
Hm..



8MHz/420=19047,6Hz


Wieso 420 wenn doch 210 ins Register geschrieben werden? Das genau verstand ich eben nicht... weil 8MHz/210=38095,2Hz

Aber ich habs...
Das hat mit Unterschieden im Mode 10 (PWM, Phase Correct) und Mode 14 (Fast PWM) (vergleiche Seite 109 im Dataheet) zu tun.

Demnach berechnet sich der Wert für das ICR bei FastPWM mit 8MHz/ICR1=Zyklus und bei PWM zu 8MHz/(ICR1*2)=Zyklus.
So les ich jedenfalls die Formeln auf Seite 100 und 101 im PDF... würde dann auch erklären warum "halber" ICR1 Wert und doch 19 Khz.

Vielelicht kann noch jemand was zum Thema "Frequenz runter setzen" was sagen?

Danke und Gruß

SlyD
15.08.2012, 18:01
Hallo,

die Treiberstufen sind so dimensioniert, dass die hohe Frequenz kein Problem darstellt.
19kHz weil das gerade ausserhalb des menschlichen Hörbereichs liegt.


> FastPWM

Wie mic schon sagt und auch in den Kommentaren der Lib steht, ist es phase correct PWM.


> Ich wüsste halt gerne, ob man die Motor PWM Taktung runter setzen

Du darfst gerne mit den Motoren Musik machen wenn Du magst ;-)
Das hat auch soweit ich mich erinnere mal wer für den RP6 gemacht, find ich aber auf die schnelle nicht mehr.
Beim ASURO klingt das jedenfalls so:
http://www.youtube.com/watch?v=FNPMCI5b8Ys

;-)


> und dann ggf. durch eine SoftwarePWM laufen lassen kann.


Wozu denn?


MfG,
SlyD

radbruch
15.08.2012, 18:10
Zu "Frequenz runter setzen": Ein einfacher Ansatz wäre der Prescaler, 19kHz/8 ergibt 2,4kHz und 19kHz/64 sind ca. 300Hz.

Neuen Prescaler in TCCR1B setzen:
TCCR1B = (1 << WGM13) | (0 << WGM12) | (1 << CS11) | (1 << CS10); // prescaler /64, 300Hz

FAST PWM zählt von bottom zu top, Phase Correct zählt jedoch von bottom zu top zu bottom. Deshalb dauert ein Zyklus doppelt so lange.

RolfD
15.08.2012, 19:09
Hallo,
der singende Asuro.. wie süß :D
Ich kannte nur das hier http://www.youtube.com/watch?v=yHJOz_y9rZE

Neee es geht mir darum, wie im FreeRTos Thread beschrieben den Timer1 frei zu kriegen bzw. die Motor-PWM evtl. anders zu generieren...
Das ist in der RP6 Lib alles schon gut so gelöst... hilft mir aber nur bedingt.

Das mit dem prescaler 8 versuch ich glaub ich mal. Danke

Noch ne Frage... kann man im PWM Mode zusätzlich ein Timerinterrupt auslösen lassen wenn die bottom ond/oder top werte erreicht werden? Da könnte ich ja den Tasksheduller dann reinhängen.

Gruß Rolf

radbruch
15.08.2012, 19:59
... kann man ... zusätzlich ein Timerinterrupt auslösen lassen, wenn die bottom ond/oder top werte erreicht werden?Na, genau das mache ich hier:
TIMSK |= (1 << TOIE1); // Die Timer1 Overflow-ISR zur Servoansteuerung
(Aus https://www.roboternetz.de/community/threads/46512-2-Servos-gleichzeitig-ansteuern-geht-das-nur-mit-Stopwatches?p=447000&viewfull=1#post447000)

Jedesmal, wenn bottom erreicht ist, wird ein Overflow-Interrupt ausgelöst und die dazugehörige ISR ausgeführt:


ISR (TIMER1_OVF_vect)
{
...
}



btw.: https://www.roboternetz.de/community/threads/51774-FreeRTos-auf-RP6

Und das noch:

http://www.youtube.com/watch?v=0eWzkXVaRtk
https://www.roboternetz.de/community/threads/28675-ASURO-DDS?p=459189&viewfull=1#post459189

RolfD
15.08.2012, 21:07
\\:D/ Danke!

Edit: Ach Radbruch.. ich seh grad dein BTW Edit... ja wir haben schon mal hin und her überlegt... ich habs nicht aus den Augen verloren.
Na ich denke, die Chancen stehen nun recht gut für RP6RTOS :)

Und noch nen Edit:
Wer wissen möchte wie das mit den Laufwerken geht....
http://georgewhiteside.net/projects/diskette-organ/

LG Rolf

RolfD
23.08.2012, 00:29
Hallo,
also ich hab das mal ausprobiert mit prescaler 64 im Example_05_Move_01 und komme zu etwas unerwarteten Ergebnissen.
Der Bot neigt nun im Leerlauf aufgebockt dazu, "zu schwingen" .. das heist die Drehzahl beider Ketten steigt... sinkt.. steigt sinkt.. etwa im 2 Sekundentakt und unabhängig von einander, manchmal bleiben sie kurz ganz stehen und schwingen dann auch nach "oben" in der Drehzahl aus. Es gibt aber auch Phasen, wo sich die Drehzahlen auf einen kontinuierlichen Wert einpendeln. Bremst man eine Kette mit dem Finger, neigt sie beim loslassen zum heftigen überschwingen als wenn ein Gummizug darin verbaut wäre. Lässt man den Bot auf dem Boden fahren, ist von Spurtreue bzw. "gradeausfahren" keine Rede... er zieht einen recht engen Kreis von ca. 1 m Durchmesser.
Is schon witzig alles... und nur weil das PWM Timing verändert ist. Man hört auch tatsächlich einen leisen PWM Ton bei ca. 300 Hz.
Mir ist klar das dies alles letztlich von vielen Aspekten abhängt... das ganze RP6 Motorsystem ist ja ein (eigentlich 2 unabhängige) klassisch rückgekoppeltes Regelsystem mit Lautzeiteigenschaften usw..
Aber das es wegen Timings so drastisch aus der Bahn kommt, hätte ich nicht für möglich gehalten und suche noch nach einer sinnvollen Erklärung.
Denn es werden hier genau so viele ISRs aufgerufen wie in der 19KHz Version den die sind abhänig von den Achsdrehungen bzw. Lichtschranken dort...
Es müssten auch sonst alle Timings gleich sein... bis auf die PWM Frequenz halt. Da die TIMER1_OVF_vect derzeit keinen Code enthält, sollte dies auch kein Einfluß haben.
Ich kann mir jedoch beim besten Willen nicht vorstellen, das es nur wegen der 19Khz->300Hz Umstellung zu solch massivem Nachlaufen der Reglerstellglieder kommt, das sogar das System zu schwingen beginnt. Der Vergleich hinkt etwas aber Phasenanschnittsteuerungen arbeiten ja üblicher Weise bei weit geringeren Frequenzen auch noch stabil.
So ist das jedenfalls nicht zu gebrauchen... auch wenn das Einhängen der ISR (TIMER1_OVF_vect) damit nun wunderbar klappt.
Vielleicht hat ja jemand eine Idee?

Ich hab eben was interssantes im c'T-Bot Projekt unter http://www.heise.de/ct/projekte/ct-bot/doc/ct-bot/motor-low_8c-source.html gefunden...

00094 #ifdef SPEED_CONTROL_AVAILABLE
00095 _BV(CS10); // Prescaler = 1 => 31.2 kHz
00096 #else
00097 _BV(CS12); // Prescaler = 256 => 122 Hz
00098 #endif // SPEED_CONTROL_AVAILABLE

Dazu http://www.heise.de/ct/projekte/machmit/ctbot/wiki/ct-Bot-Software-Aktuatoren
und https://www.roboternetz.de/community/threads/42391-verbesserung-Drehzahlregelung-I-zu-PI-PID-Regler

Also über das Thema auf dem RP6 basierend kann man wohl sicherlich noch einige Doktorarbeiten schreiben...
LG Rolf

SlyD
24.08.2012, 15:43
Hallo,

ich war davon ausgegangen das Dir der Grund "die Motoren trällern ein Lied" schon ausreicht um von dem Plan abzusehen die PWM Frequenz runterzuschrauben ;-)

Das sich das Verhalten der Motoren dadurch ändert, kommt natürlich noch dazu.
Mit der Software hat das nicht viel zu tun, aber mit dem Motor ansich.
Der Motor hat eine Zeitkonstante die sich aus der Induktivität und dem Innenwiderstand ergibt. Das ist ein Tiefpass Filter, der glättet den Strom - Frequenzabhängig. Der Ripplestrom wird also bei niedriger Frequenz höher, der Wirkungsgrad sinkt und das Drehmoment schwankt stärker!
Die starken Vibrationen sind mechanisch auch nicht gerade hilfreich. Und noch andere Dinge...


Egal - ich versteh nicht wo das Problem ist statt Timer1 einfach den Timer0 zu nehmen, der wird in der RP6 Lib ja auch für die Stopwatches benutzt. Die brauchst Du aber mit FreeRTOS wohl nicht?
Die Stopwatches sind Software Timer.
Du kannst mit dem einen Timer beliebig viele Softwaretimer erzeugen - solange die Rechenleistung ausreicht.

MfG,
SlyD

RolfD
27.08.2012, 00:20
Hi Slyd....

"ich war davon ausgegangen..."
Warum sollte mich das "singen" abhalten in der Richtung das Eine oder Andere auszuprobieren? Nö der RP6 macht mit seinen Gearboxen auch so schon genug rabatz :) Da konnts nich drauf an...
Nun ich bin davon ausgegangen, das die niedrige Frequenz eben nicht so massive Auswirkungen hat und ich habe viel recherchiert, ausprobiert, dazu gelernt... ist doch alles fein :)

"ich versteh nicht wo das Problem ist"
Hätte es geklappt wie erst gedacht, wäre es die einfachste Möglichkeit gewesen, mit Timer1_OVF und 300Hz für den RTOS Tick zu arbeiten da Timer0 und 2 nun mal schon von der RP6Lib intensiv genutzt wird. Ich werde aber wohl nun den Timer0 nutzen müssen. Nein brauchen können tu ich die Stopwatches so sicher nicht, RTOS hat ne eigene Zeit/Timerverwaltung aber da hängen bei RP6Lib ja nicht nur die Stopwatches dran... leider. RTOS hat eine eigene Stackverwaltung, naked isr's usw... usw.. Das ist alles aus diversen Gründen leider nicht so einfach. Es langt auch nicht, das RTOS System mal eben durch ein Softwaretimer in das RP6Lib System einzuhängen.

Ich frag mich halt auch, ob das beschriebene Verhalten (schwingen) nun allein an der niedrigen PWM Frequenz/pysische Eigenschaften usw. liegt, oder (auch) an der Software zur Motorsteuerung. Wenn ich das richtig sehe, hast du in der RP6Lib sowas wie ein PI-Regler verwendet und die Steuerung hängt von den ISRs der Encoder, aber auch vom hochfrequenten Aufruf von task_motionControl, sowie von der TIMER0_COMP_vect mit Ausgabe der PWM Werte ab. Das heisst aber, das die Regelwerte quasi zeitungebunden bzw. CPU-Lastabhängig verarbeitet werden? Das würde vielelicht das besagte Schwingen erklären? Die CT'bot Lösung verwendet dagegen z.B. einen zeitsyncronisierten PID Regler mit Änderung der PWM Rate im Anschluß an den Regelkreis ohne weitere Laufzeitabhängigkeiten. Quasi so als wäre die task_motionControl ein Teil der TIMER0_COMP_vect.
LG Rolf

LG Rolf

SlyD
27.08.2012, 12:14
> ist doch alles fein

:)


> naked isr's

ah ja das stimmt natürlich, nicht dran gedacht.

> aber da hängen bei RP6Lib ja nicht nur die Stopwatches dran... leider.

Du kannst das auch so drehen, dass Du die anderen Sachen in den Timer1 Overflow Interrupt reinbaust um den Timer0 komplett frei zu bekommen.
Der RC5 Kram wird wegen des Timings nicht einfach so zu portieren sein (geht aber sicher auch irgendwie), aber die sanfte Änderung der PWM Werte und die paar anderen Softwaretimer sind z.B. kein großes Problem, einfach die Zeiten grob anpassen, das ist alles unkritisch.
Das die LED ab und zu blinkt wenn keine andere an ist, kannst Du ja komplett rausnehmen und als Thread realisieren.

Die Geschwindigkeitsmessung ist das einzige was wirklich kritisch ist. Da musst Du SPEED_TIMER_BASE anpassen.


MfG,
SlyD

PS:

aber auch vom hochfrequenten Aufruf von task_motionControl,

Naja 5x pro Sekunde, die wichtigen Dinge wie Geschwindigkeit messen sind alle in ISRs drin



sowie von der TIMER0_COMP_vect mit Ausgabe der PWM Werte ab.


Das ist nur damit sich die PWM Werte nicht zu abrupt ändern.



Das heisst aber, das die Regelwerte quasi zeitungebunden bzw. CPU-Lastabhängig verarbeitet werden? Das würde vielelicht das besagte Schwingen erklären? Die CT'bot Lösung verwendet dagegen z.B. einen zeitsyncronisierten PID (http://www.rn-wissen.de/index.php/Regelungstechnik) Regler mit Änderung der PWM Rate im Anschluß an den Regelkreis ohne weitere Laufzeitabhängigkeiten. Quasi so als wäre die task_motionControl ein Teil der TIMER0_COMP_vect.


Dort wird die Regelung komplett deaktiviert wenn Du die PWM so drastisch runterdrehst ;-)
Warum die überhaupt die 120Hz da drin haben ist mir schleierhaft, man verwendet bei so kleinen Motoren so niedrige PWM Frequenzen aus oben schon geanannten Gründen normalerweise nicht. Das hat fast nur Nachteile (egal ob mit Regelung oder ohne).


PPS:
Die Ketten des RP6 sind übrigens träger als die kleinen Räder des c't Bot.
Daher macht dort eine schnellere Regelung auch mehr Sinn.
Zudem ist die Auflösung beim c't Bot nur 60 Flanken / Umdrehung, die Software muss daher die Zeit zwischen zwei Encoderflanken messen und führt die Regelung bei jedem neuen Puls aus. Das erhöht die CPU Last natürlich enorm.
Der RP6 hat eine 10x höhere Encoderauflösung und verzichtet daher auf sowas.

RolfD
29.08.2012, 03:05
Also ich hatte beschlossen, den Timer1 auf 20KHz bzw. 10.000 PWM Impulse laufen zu lassen. Das ergibt ein Wert von 400 für das 16 Bit Register ICR1 bei Precaler 1 und eine Auflösung von 100 μs für die ISR (TIMER1_OVF_vect), wo ich da dann alles 1:1 rein setzen kann was vorher in der ISR (TIMER0_COMP_vect) stand. Damit ist der Timer0 frei für RTOS. Die Pole des Motorankers dürften so genügend Pulse Pro Sek. bekommen um sauber zu arbeiten auch wenn er dann etwas fiept und alle anderen Abläufe müssten gleich sein. Sogar die Stopwatches tuen es dann noch. Für die Anpassung der Sollgeschwindigkeit aus RP6 Lib Funktionen (passend zum ICR1 Dutycycle Wert) reicht zum testen eine Multiplikation / bitshift *2 welche einfach in die ISR Motorsteuerung einzubringen ist.
Dann noch ein RTOS Task der die RP6Tasks aufruft und alles müsste eigentlich passen... Eigentlich... denn es passt nicht!

Zunächst was ich noch nicht ganz verstehe, TCCR1A und TCCR1B sind ja die Timerconfigurationsregister. Die werden zu Anfang durch Hardwareinit gesetzt. Ok. Und teilweise später auf 0 gesetzt... Warum?
U.a. in emergencyShutdown, bei task_motionControl im Abschnitt CHANGE_DIRECTION_FAST wobei unter CHANGE_DIRECTION_MEDIUM nur geprüft wird, in der ISR (TIMER0_COMP_vect) ... allerdings auch wieder gesetzt..
Würde es nicht ausreichen TCCR1A in Ruhe zu lassen und nur einfach OCR1AL und OCR1BL mit 0 zu beschreiben damit der Bot stehen bleibt?
Irgendwie wird da das TCCR1A in der RP6Lib als 2.ter Ein/Aus Schalter fürs PWM benutzt - was aber zu Problemen führt wenn TIMER1_OVF_vect (s.o.) auch systemrelevante Funktionen steuert und daher weiter laufen soll.
Eine bessere Lösung wäre vielelicht auch die Directionbits im Port zu ändern da die PWM nur nach ausßen gelangt wenn die Portbits auf Ausgang stehen bzw. die Bits COM1A1:0 and COM1B1:0 in TCCR1A zu löschen.
vergl. S.107 im cpu-pdf

"The COM1A1:0 and COM1B1:0 control the Output Compare pins (OC1A and OC1B respectively)
behavior. If one or both of the COM1A1:0 bits are written to one, the OC1A output
overrides the normal port functionality of the I/O pin it is connected to. If one or both of the
COM1B1:0 bit are written to one, the OC1B output overrides the normal port functionality of the
I/O pin it is connected to. However, note that the Data Direction Register (DDR) bit corresponding
to the OC1A or OC1B pin must be set in order to enable the output driver."

Ok... also passend umschreiben.

Aber was mir noch aufgefallen ist... Radbruchs Tip TIMER1_OVF_vect zu nutzen scheint mir inzwischen nicht mehr die beste Idee wie dort Figure 47. Phase Correct PWM Mode, Timing Diagram etwa mitte des Bildes zeigt.
Die Interrupts fallen bei Mode 10 _nicht_ Zeitsyncron an, sondern je nach dem wie das PWM Verhältnis eingestellt ist. Deren Frequenz kann sich bis zu einem mehrfachen der ursprünglich erwarteten Frequenz steigern. Mit anderen Worten, die Rechnung oben zum Thema TimerISR umsetzen wäre für die Katz! Sehe ich das richtig so?

Praktisch ruckelt der Bot jedenfalls als würde jemand ständig Gas und Bremse vertauschen... Karnickelhüpfen quasi...

Ich will das Ganze noch mal mit Timer Mode 8, also "PWM, Phase and Frequency Correct" versuchen, ansonsten war das Ganze ein informativer Ausflug in die Timerprogrammierung und die RP6Lib aber leider ist so kein Blumenpott zu gewinnen...

LG Rolf

radbruch
29.08.2012, 08:58
Hallo


Aber was mir noch aufgefallen ist... Radbruchs Tip TIMER1_OVF_vect zu nutzen scheint mir inzwischen nicht mehr die beste Idee wie dort Figure 47. Phase Correct PWM Mode, Timing Diagram etwa mitte des Bildes zeigt.
Die Interrupts fallen bei Mode 10 _nicht_ Zeitsyncron an, sondern je nach dem wie das PWM Verhältnis eingestellt ist. Deren Frequenz kann sich bis zu einem mehrfachen der ursprünglich erwarteten Frequenz steigern. Mit anderen Worten, die Rechnung oben zum Thema TimerISR umsetzen wäre für die Katz! Sehe ich das richtig so?

In der Mitte von Bild 47 wird TOP verändert, deshalb ändert sich die Frequenz. Etwas weiter unten steht folgendes:


When using a static TOP value there are practically no differences between the two modes of operation.

Gruß

mic

RolfD
29.08.2012, 14:41
"When using a static TOP value there are practically no differences between the two modes of operation."

Diese Aussage bezieht sich auf den Unterschied von "PWM, Phase and Frequency Correct" und "PWM, Phase Correct".
Da wir mit ICR1 ein static TOP haben, verhält sich Mode 8 wie Mode 10... also dürfte Mode 8 auch nichts gegenüber Mode 10 verbessern. ok. Aber..

"The Timer/Counter Overflow Flag (TOV1) is set each time the counter reaches BOTTOM. When
either OCR1A or ICR1 is used for defining the TOP value, the OC1A or ICF1 Flag is set accordingly
at the same timer clock cycle as the OCR1x Registers are updated with the double buffer
value (at TOP). The Interrupt Flags can be used to generate an interrupt each time the counter
reaches the TOP or BOTTOM value."

Da Top = ICR1 und Bottom = 0 nicht verändert werden, müsste es so gehen.. nur warum "hüppelt" der Bot dann aber so?
Ich sehe schon ein das du theoretisch recht hast mit dem TIMER1_OVF_vect, Radbruch... praktisch tuts das aber so nicht.
Ob das an den noch nicht umgeschriebenen Registern TCCR1A = 0 (s.o.) liegen kann? Ich mach mich mal dran das zu ändern.
Denn das würde den Zeitgeber Timer1 beeinflussen und so ggf. Störungen in den 100uS Messschleifen verursachen.

Hier meine Änderungen bisher:
Init:

// Initialize Timer 0 - 2ms cycle or 500Hz RTOS
TCCR0 = (0 << WGM00) | (1 << WGM01)
| (0 << COM00) | (0 << COM01)
| (0 << CS02) | (1 << CS01) | (1 << CS00);
OCR0 = 250; // 500 Hz

// Initialize Timer1 - PWM and exTimer0 Funktions:
// PWM, phase correct with ICR1 as top value.
TCCR1A = (0 << WGM10) | (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = (1 << WGM13) | (0 << WGM12) | (1 << CS10); // prescaler /1

// 20000 Hz = ICR1 400, bzw. pwm von 10000 Hz -> 0,0001 S bzw. 100 μs bei prescaler /1

ICR1 = 400; // New Phase corret PWM top value, 400 = 10 KHz 100uS

Dann die ISR für Timer:
ISR (TIMER0_COMP_vect) in ISR (TIMER1_OVF_vect) geändert. Aufruf alle 100uS

ISR für den nun freien Timer0:


#if configUSE_PREEMPTION == 1
// ISR (TIMER0_COMP_vect, ISR_NAKED)
ISR (TIMER0_COMP_vect)
{
// vPortYieldFromTick();
// asm volatile ( "reti" );
}
#else
// ISR (TIMER0_COMP_vect, ISR_NAKED)
ISR (TIMER0_COMP_vect)
{
// vTaskIncrementTick();
}
#endif // portUSE_PREEMPTION

Um aktuell Komplikationen zu verhindern ist die nun zum RTOS gehörende ISR (TIMER0_COMP_vect)
so geändert, das sie als normale ISR ohne ins RTOS zu wechseln 500 mal /sec nichts macht. Da das RTOS
nicht angesprungen wird liegt es nur als toter Code im Hexfile - es geht also immer noch nur um die RP6Lib.

Is also alles keine Zauberei... und trotzdem ruckelt der Bot vor sich hin statt normal zu fahren.
LG Rolf

SlyD
29.08.2012, 16:49
Hallo,


Irgendwie wird da das TCCR1A in der RP6Lib als 2.ter Ein/Aus Schalter fürs PWM benutzt - was aber zu Problemen führt wenn TIMER1_OVF_vect (s.o.) auch systemrelevante Funktionen steuert und daher weiter laufen soll.

Nun mit der normalen Lib war das natürlich nicht vorgesehen und daher nicht nötig das anders zu machen.
Mit TCCR1A = 0 ist die PWM halt sicher aus und die Ports wieder normale I/Os.
Und man kann einfach mit if(!TCCR1A) testen ob beide PWM Werte schon bei 0 angekommen sind (bei change direction).
Kannst Du natürlich ändern oder nur die passenden Bits (COM1x1) in dem Register setzen.

Warum es ruckelt kann ich auf Anhieb nicht sagen ohne mir das genauer anzuschauen.

MfG,
SlyD

RolfD
29.08.2012, 19:28
Ich habe nun mal alle TCCR1A=0 entfernt und durch OCR1AL = 0; OCR1BL = 0; ersetzt und siehe da - der Bot bewegt sich - oh Wunder - sanft und ruhig.

Nun frag ich mich.... warum rief der denn vorher überhaupt in dem Beispiel Example_05_Move_01 das TCCR1A=0 auf?
Da steht ja nur drin: "Beweg dich langsam vorwärts (wobei er {beide RP6, die ich hab} da bei mir schon immer rückwärts anfuhr)".. also kein Richtungswechsel.. keine Speedänderung, kein Halten ...


Und man kann einfach mit if(!TCCR1A) testen ob beide PWM Werte schon bei 0 angekommen sind (bei change direction).
Das halte ich aber für ein dickes Gerücht.... ein gelesenes TCCR1A gibt aus was man als Config Bits reinschreibt - und keine Istwerte des Zählers. Im TCCR1A steht z.B. das Verhalten für COM1A1 und COM1B1 drin, also die Portpins bei Timerüber/unterlauf. Ferner steht da auch der PWM Mode drin....welcher sich zur Laufzeit niemals ändert. Ein TCCR1A kann also niemals 0 werden - egal wie der Status der PWM Counter ist. Ein OCR1AL = 0; OCR1BL = 0; sorgt eh dafür, das keine Impulse mehr rausgehen. Es ist nun wirklich nicht nötig, Änderungen im Dutycycle bei 10 bzw. 19 KHz PWM auf den aktuellen PWM Counter zu timen - wie du andeutest, Slyd. Der Code da in der ISR mit if(!TCCR1A) ist einfach nicht sinnvoll.
Siehe Seite 107-109 im CPU-PDF.
Ich vermute, da haben sich nur einfach ein paar Denkfehler in die bisherige Motorsteuerung eingeschlichen. Dies betrifft zumindest die lesende Nutzung des TCCR1A, sowie auch das mitten im Rollbetrieb scheinbar Konditionen entstehen, die dazu führen, das TCCR1A = 0 ausgeführt wird. Beides fällt in der alten Timerconfig halt nur nicht auf.

Jetzt kann man natürlich mit dem schlagenden Argument kommen "funktioniert doch bisher" ... und ich füge an ... "irgendwie".
Vielleicht wäre es wirklich mal an der Zeit, die RP6Lib zu überarbeiten. Nach TWI schon der 2. Problemkreis, der sich für mich auftut.
Aber da ich ja eh das RTOS portieren will... *seufz
Jedenfalls tuts jetzt die Idee mit TIMER1_OVF_vect, Timer0 ist frei und es kann los gehen mit RTOS, Danke noch mal an Radbruch für den Tip und alle beteiligten Leser fürs Mitdenken.
LG Rolf

SlyD
29.08.2012, 19:38
Ne ne hier verstehst Du nur was an dem Programmablauf nicht ganz ;-)


ein gelesenes TCCR1A gibt aus was man als Config Bits reinschreibt

Ja genau, und was wird im Timerinterrupt reingeschrieben wenn beide OCRs 0 sind?
--> 0
Was steht also drin wenn die PWM Werte auf 0 runtergeregelt wurden?
--> 0

Passt also.

MfG,
SlyD

RolfD
29.08.2012, 20:07
Hi Slyd,
du benutzt das TCCR1A bewust als Statusvariable für die PWM ... ok.. ja vermutet hatte ich den Zusammenhang ja oben schon mit dem ein/aus Schalter.
Ok kann man so machen...
Als Regelkreislauf kommt es aber offensichtlich dazu, das diese Kondition auch im Fahrbetrieb des Beispiels Example_05_Move_01 aufkommt - was hier dann zu ruckeln führte. Ok das ruckeln liegt an meiner Bastelei am Timer1...
Nur darf der Regelkreislauf so exorbitant ausschlagen das der Motorcontroller meint, im Rollbetrieb zwischendrin mal eben so die PWM Generierung abschalten zu müssen? Da ist doch was im argen...
Gruß Rolf

SlyD
29.08.2012, 20:52
Der PWM Wert ist 0 wenn TCCR1A auf 0 gesetzt wird.
Sobald in den PWM Variablen im Programm was anderes als 0 drinsteht, wird TCCR1A wieder auf den normalen Wert gesetzt (natürlich mit Verzögerung wegen Software Timer).
Das macht also keinen Unterschied!


Das bei Dir das Programm so seltsam reagiert wenn TCCR1A auf 0 gesetzt ist, liegt evtl. daran, dass der Overflow Interrupt dann etwas anders auftritt. Der wird ja nicht deaktiviert (weil er in der RP6Lib nicht genutzt wird).
TCCR1A auf 0 setzen trennt den Timer von den I/O Ports ab und der Timer wird in den
(EDIT: Natürlich nicht normal Modus sondern einer der anderen ich hatte vergessen das WGM13 ja im TCCR1B gesetzt ist)
konfiguriert.
Da in der RP6Lib diese Interruptvektoren nicht genutzt werden und auch nie geplant war diese jemals zu nutzen, hatte das da natürlich keine Relevanz.
EDIT:
Der Timer0 ist ja unabhängig vom Timer1, da TCCR1A zu setzten wirkt sich auf Timer0 natürlich nicht aus der läuft ungestört weiter. Wenn Du aber im Timer1 Interrupt das TCCR1A Register setzt wirkt sich das wohl anders aus.

Der Regler kann den Sollwert nur soweit senken wenn die Regelabweichung stark genug wird.
Der Stellwert sollte eigentlich nicht bis auf 0 runter gehen, aber da das Fahrzeug eine recht große Masse hat und auch erstmal abgebremst werden will wenn es gerade kurz beschleunigt hatte (plus Verzögerung wegen langsamer Änderung der PWM)... funktioniert im Fahrbetrieb aber gut genug. Kann man aber durchaus nochmal genauer untersuchen und optimieren.

Wenn das bei *Deinem* Programm aber auch nur einmal kurz auftritt kommt alles durcheinander wegen der Verzögerung / Änderung der Timereinstellung die dann dazwischen funkt.

Aber egal, einfach so anpassen wie Du schon gesagt hast dann sollte es laufen.

MfG,
SlyD

radbruch
29.08.2012, 21:05
Also, wenn ich das richtig sehe, dann ändert TCCR1A = 0 nicht die Frequenz, denn dann ist nur noch WGM13 gesetzt und das bedeutet Mode 8.

Zu langsam, das hat SlyD inzwischen auch schon bemerkt.

SlyD
29.08.2012, 21:14
P.S.: Das sollte auch so sein, denn sonst würden sich meine Servos nicht drehen, wenn der Antrieb steht...

Ja wie in meinem zweiten EDIT zu lesen, ist hier ja die Situation so, das im Timer1 Interrupt, die Einstellungen von Timer1 geändert werden. Das war vorher ja aber nicht so, da wurde im davon völlig unabhängigen Timer0 die Einstellung vom Timer1 geändert. Müsste man mal testen wie sich das auswirkt.

EDIT 33435: Immer diese ganze Beitragseditiererei, welch Verwirrung ;)
Man sollte eine Funktion im Forum haben die einem mitteilt das jemand gerade seinen Beitrag editiert während man eine Antwort schreibt ;)

radbruch
29.08.2012, 21:30
Sorry. Ich musste das wieder entfernen, weil ich nicht nachweisen kann, dass die mit der OVL-ISR angesteuerten Servos sich auch mit aktiven Antrieben richtig verhalten. Ansonsten hat die Edit-Funktion auch meine WGM13-Recherche unnötig gemacht:

"(EDIT: Natürlich nicht normal Modus sondern einer der anderen ich hatte vergessen das WGM13 ja im TCCR1B gesetzt ist)"

P.S.: Es ist für mich ein schmaler Grad zwischen "Helfen" und "Sinn des Projekts". Deshalb bin ich in diesem Thread etwas zögerlich.

RolfD
29.08.2012, 21:40
*lach .. @SlyD.. naja bisher kriegen wir es ja hin uns auch trotz Edits zu verständigen.
@Radbruch ... dadurch das Mode 8 in TCCR1B erhalten wird, laufen deine Servos auch beim abschalten des TCCR1A = 0 .. Richtig, seh ich auch so. Ein glücklicher Zufall.
Denn ob das ne schöne Methode mit TCCR1A = 0 wärend einer Fahrt ist.. da kann man sicher drüber streiten. Ich bin aber kein Experte für Motor-Regelungen.
Nun gut es funktioniert aber und nun auch mit Timer1. Für alle die einen freien Timer0 brauchen eine gute Nachricht. Danke noch mal.
LG Rolf

PS: @Radbruch, Sinn des Projekts... ist hier nicht RTOS sondern Timer0 bzw. einen Timer in der RP6Lib frei zu kriegen und das wird auch für andere interssant sein. Da lege ich in meiner Darstellung des Problems auch Wert und Gewicht drauf. Es wäre Schade wenn das "Glaubensfragen" sind.. es geht für mich rein um Aufgabenstellungen und bestmögliche Lösungen.

Nachtrag: Evtl. muss man die Funktion vom "Bremspedal TCCR1A" mit einer Variable nachbilden wenn man nicht möchte, das TCCR1A=0 beschrieben wird. Meine Lösung, die Zuweisungen zu entfernen führt bei der RP6Lib dazu, das nach einem Motorbefehl nicht mehr abgebremst wird. Dazu eine Var myTCCR1A deklarieren und an allen Fundstellen ausser im Init ersetzen. Oder man benutzt #define CHANGE_DIRECTION_FAST und verzichtet gänzlich auf das Bremspedal (Warnung bezüglich Lebensdauer der Zahnräder beachten, für rumprobieren ist das aber ok).

SlyD
30.08.2012, 10:18
Timer0 bzw. einen Timer in der RP6Lib frei zu kriegen und das wird auch für andere interssant sein.

Yep, dem stimme ich zu. Wäre sicherlich eine gute Sache.

MfG,
SlyD