Forum: Mikrocontroller und Digitale Elektronik Timer 5 Konfig Mega 2560 Phase and Frequency Correct


von Michael (Gast)


Lesenswert?

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)

von Veit D. (devil-elec)


Lesenswert?

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
}

von Veit D. (devil-elec)


Lesenswert?

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
}

von Michael (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

> 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.

von Michael (Gast)


Lesenswert?

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

von S. Landolt (Gast)


Lesenswert?

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?

von Michael (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

> 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.

von Michael (Gast)


Lesenswert?

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

von S. Landolt (Gast)


Lesenswert?

PS:
Auch der ADC selbst ist ja nicht schneller.

von Veit D. (devil-elec)


Lesenswert?

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
Noch kein Account? Hier anmelden.