Hallo zusammen, ich habe gerade den Timer5 meines Arduino Megas zum laufen bekommen. Ich wollte mich bei euch nochmal erkundigen, ob der Weg wie ich ihn konfiguriert habe richtig ist oder wie es besser geht. Zu dem habe ich im Datenblatt gesehen, dass man für die 16 Bit über einen Temp zugriff arbeiten sollte (1). Wie funktioniert das in C? Zudem habe ich mir die Frage gestellt, wie der Vergleichswert am besten im Code beschrieben werden soll. Ich habe euch mal meinen Code für eine Phasen-/Frequenz Korrekte PWM angehängt. Freue mich auf Verbesserungsvorschläge und Kritik. Viele Grüße ****** Code funktioniert. PWM Frequenz ist exakt 8000 Hz wie zuvor berechnet. ***** void setup() { pinMode(46, OUTPUT); noInterrupts(); // disable all interrupts TCCR5A = 0b11000000; // set COM5A1, COM5A0 and WGM50 to 1 TCCR5B = 0b00010001; // set prescaler to 1 and set PWM-Mode ICR5H = 0b00000011; // set top value to 1000 ICR5L =0b11101000; // set top value to 1000 uint16_t vglA = 500; //Vergleichswert OCR5AH = (vglA >> 8); OCR5AL = (vglA & 0x00FF); interrupts(); // enable all interrupts } void loop() { //loop zur Visualisierung am Oszi int i; for (i=0;i<1000;i++) { uint16_t vglA = i; //Vergleichswert A OCR5AH = (vglA >> 8); OCR5AL = (vglA & 0x00FF); delay(100); if (i ==999) { i = 0; } } } (1) The Input Capture Register is 16-bit in size. To ensure that both the high and low bytes are read simultaneously when the CPU accesses these registers, the access is performed using an 8-bit temporary High Byte Register (TEMP). This temporary register is shared by all the other 16-bit registers)
Hallo, sieht noch etwas umständlich aus. :-) Die 16 Bit Register muss man nicht in High und Low Byte zerlegen. Die kann man direkt beschreiben. Das macht der Compiler für einen. Zudem das hier auch etwas sinnfrei ist, wenn du dir einmal in Ruhe überlegst was im Einzelnen passiert mit diesen 2 Zeilen.
1 | uint16_t vglA = 500; |
2 | OCR5AH = (vglA >> 8); Ergebnis ist ? |
3 | OCR5AL = (vglA & 0x00FF); Ergebnis ist ? |
Nochwas zum Timer. So ein Timer läuft ständig ohne jede weitere Zuwendung. Also parallel zum Hauptprogramm. Das heißt du stellst einmal mit dem TOP Wert die Frequenz ein und mit dem Comparewert die Pulsweite und schaltest mit dem Prescaler das Teil ein. Das bedeutet du musst im Hauptprogramm nicht ständig den Comparewert neu setzen. Es sei denn du möchtest ihn ändern. Aber jedesmal auf den gleichen Wert macht keinen Sinn, er vergisst ihn nicht. :-) Bei mir würde das so aussehen in Klarschreibweise der Registerzuweisung. Dann klemmste dein Oszi an Pin 46. Zusätzliches (1<<COM5A0) negiert das PWM Signal.
1 | /*
|
2 | Timer 5: Phase and Frequency Correct, Mode 8
|
3 | TOP: ICR5
|
4 | Pulsweite: OCR5A (<= TOP)
|
5 | Schaltpin: 46 (OC5A bzw. PL3) nicht invertiert
|
6 | */
|
7 | |
8 | |
9 | const byte pin_PWM = 46; |
10 | |
11 | |
12 | void setup() { |
13 | |
14 | pinMode(pin_PWM, OUTPUT); |
15 | set_Timer5(); |
16 | |
17 | }
|
18 | |
19 | |
20 | void loop() { |
21 | |
22 | } // loop Ende |
23 | |
24 | |
25 | // ****** Funktionen ******* //
|
26 | |
27 | void set_Timer5() // Mode 8 |
28 | {
|
29 | cli(); // Interrupts ausschalten |
30 | TCCR5A = 0; // Reset |
31 | TCCR5B = 0; // Reset |
32 | TIMSK5 = 0; // Reset |
33 | TCNT5 = 0; // Start 0 |
34 | ICR5 = 1000; // TOP |
35 | OCR5A = 244; // Duty Cycle |
36 | TCCR5A = (1<<COM5A1); // nicht invertiert |
37 | TCCR5B = (1<<WGM53) | (1<<CS50); // Prescaler 1 |
38 | sei(); // Interrupts einschalten |
39 | }
|
Hallo, jetzt habe ich den Sinn des loop Codes gerafft. Du willst das sich Duty Cycle verändert. Okay. Geht auch einfacher. Ich greife zwar schon vor, aber du möchtest das hier machen
1 | void loop() { |
2 | |
3 | // zur Visualisierung am Oszi
|
4 | |
5 | for (byte i=0; i<245 ;i++) { |
6 | OCR5AH = 0; |
7 | OCR5AL = i; |
8 | delay(10); |
9 | }
|
10 | |
11 | }
|
12 | |
13 | und das kann man auch so schreiben |
14 | |
15 | [c] |
16 | for (byte i=0; i<245 ;i++) { |
17 | OCR5A = i; |
18 | delay(10); |
19 | }
|
Perfekt vielen Dank dir. Das ganze wird eine unterlagerte Stromregelung für einen bzw. zwei Dc Motoren. Gibt es eine Möglichkeit den adc exakt zur Pwmmitte zu triggern? Kenn es so aus meiner Master Arbeit die übersensorlose Regelung von Snychronmaschinen ging.
> den adc exakt zur Pwmmitte zu triggern
Exakt? Wenn man die Sample&Hold-Zeit vernachlässigt, sollte das mit der
Phase-Correct-PWM gehen, ADC auf 'Auto-Trigger Timer/Counter1-Overflow';
aber eben nur mit Timer1, mit Timer5 schafft man es nicht mehr ganz so
exakt, zumindest nicht so einfach.
Aber ich habe schon richtig gelesen, dass es nur einen adc gibt beim mega gibt? Mein Vorhaben kann somit gar nicht funktionieren, da ich ja bei beiden Motoren den strom zur pwm mitte abtasten möchte oder? Viele Grüße
Richtig, nur ein ADC, welcher sich auf mehrere Eingänge schalten lässt. Ich kenne mich mit dieser Motorregelungsgeschichte nicht aus, aber könnte man nicht abwechselnd bei jeweils jeder zweiten PWM-Phase messen?
Ne dann bist du zu lange Blind. Also man könnte es ausprobieren aber ich denke ich werde bei einem motor tpwmmitte-x abtasten und bei dem anderen t tpwmmitte +× abtasten und den Fehler herausrechnen.
> Ne dann bist du zu lange Blind.
Wie gesagt, ich kenne mich nicht aus; wundere mich aber, so ein Motor
ist doch Mechanik, und bei den genannten 8000 Hz wäre die "blinde Zeit"
doch nur 250 us, das Nachregeln geht doch auch kaum schneller.
Ich sehe das Problem auch nicht sofern ich einen konstanten Strom regeln möchte eher sobald man relativ steile gradienten Fährt bzw. den Regler relativ schnell auslegt. Viele Grüße sofern ich alles implementiert habe poste ich mal den Code. Falls jemand noch etwas weiß gerne melden
PS: Auch der ADC selbst ist ja nicht schneller.
Hallo, ich habe das mal mit overflow und compare match ISR probiert. In der ISR einen pin toggeln lassen. Mit compare match muss man kleine compare werte setzen damit es ca. mittig wird. Mit overflow ISR klappt das eigentlich sehr gut. Das hängt Naturgemäß etwas hinterher. Laut meiner Messung 30µs. Davon ziehen wir ca. 4µs ab die digitalWrite benötigt. Also haste pi mal daumen 26µs Verzögerung. Also 26µs über der Mitte der Pulsbreite. Stört das?
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.