Go Down

Topic: Timer 2 15 khz frequenz mit variabler duty cycle (Read 5370 times) previous topic - next topic

murdok1980

Will nich das ihr mich auslacht :)
Code: [Select]

const byte OUTPUT_PIN2 = 6;
const byte OUTPUT_PIN3 = 7;

void setup()
{

  pinMode (OUTPUT_PIN2, OUTPUT);
  pinMode (OUTPUT_PIN3, OUTPUT);

  digitalWrite(OUTPUT_PIN2, LOW);
  digitalWrite(OUTPUT_PIN3, HIGH);
 
  pinMode(11, OUTPUT);//OCR2A


TCCR2A = (1<<WGM21) | (1<<WGM20)| (1<<COM1A1) ;
TCCR2B = (1<<CS20);


}  // end of setup

void loop() {

  OCR2A = 255;
 

}

Hier passt die Frequenz aber nicht

murdok1980

@Serenifly
Ich brauch ja auch nur noch einen zusätzlichen Ausgang. Das würde reichen. 2x PWM mit Timer1 und einer mit Timer2. So dass ich insgesamt drei H-Brücken ansteuern kann.

Doc_Arduino

#17
Feb 09, 2016, 09:02 pm Last Edit: Feb 09, 2016, 09:05 pm by Doc_Arduino
Hallo,

na gut, lass ich gelten. Sind aber "Schusselfehler" drin. Die Bits passen aber nicht zum Timer 2.
Bsp.
COM1A1   ist für Timer 1
WGM13   ist auch für Timer 1 und gibts beim Timer 2 nicht
ICR1  ist auch für Timer 1, kann man beim Timer 2 nicht ändern
Und andere Bits werden überhaupt nicht gesetzt.
Hast du überhaupt jemals versucht ins Datenblatt zu schauen?
Eigentlich ist der Versuch ungültig.  ;)
Aber jeder fängt mal an.
Will dich aber nicht länger auf die Folter spannen. Den Pin auf 11 anpassen darfste selbst ...

15kHz sind aber wie schon erwähnt so nicht möglich.

Code: [Select]
/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.7
 Arduino Mega2560
 
 Timer 2: Fast-PWM, Mode 3
 TOP:  0xFF     (Takt-Frequenz)
 Pulsweite: OCR2A  (<= TOP)
 Schaltpin: 10   (OC2A bzw. PB4) nicht invertiert
*/

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   // setzt das angegebene Bit auf 1
#endif

const byte _PWMpin = 10;   // OC2A bzw. PB4 nicht invertiert, IRFxxxx Mosfet o.ä.
const byte _Poti = A0;     // Potentiometer

void setup()  {
  Serial.begin(9600);
  
  digitalWrite(_PWMpin, LOW);    // OC2A bzw. PB4 nicht invertiert
  pinMode(_PWMpin, OUTPUT);      
  
  set_Timer2();
  
}

  
void loop() {          
  
  int value = analogRead(_Poti)/4;  
  
  if (value == 0)  {
    digitalWrite(_PWMpin, LOW);   // PWM 0%
  }
  else  {
    sbi(TCCR2A, COM2A1);
    OCR2A = value;                // PWM x%
  }
  
  //Serial.print(F("PWM Wert: ")); Serial.println(value);
  //delay(1000);
  
                              
}   // loop Ende


// ****** Funktionen ******* //
    
void set_Timer2()       // Fast-PWM, Mode 3
{
  cli();         // Interrupts ausschalten
  TCCR2A = 0;    // Reset TCCR1A Register
  TCCR2B = 0;    // Reset TCCR1B Register
  TIMSK2 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT2  = 0;    // Reset Start-Counter
  TCCR2A = (1<<COM2A1) | (1<<WGM21) | (1<<WGM20);  // non invert, set Mode 3
  TCCR2B = (1<<CS21);                              // Prescaler 8 >> 7,8kHz
  OCR2A = 0;     // Pulsweite, < 255 (2^8)
  sei();         // Interrupts einschalten
}  // end Funktion



Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

übrigens, Timer 2 mit seinen zwei Pins funktioniert auch.

Code: [Select]
/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.7
 Arduino Mega2560
 
 Timer 2: Fast-PWM, Mode 3
 TOP:  0xFF     (Takt-Frequenz)
 Pulsweite: OCR2A, OCR2B  (<= TOP)
 Schaltpin: 10   (OC2A bzw. PB4) nicht invertiert
 Schaltpin:  9   (OC2B bzw. PH6) nicht invertiert
*/

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   // setzt das angegebene Bit auf 1
#endif

const byte _PWMpinA = 10;  // OC2A bzw. PB4 nicht invertiert, IRFxxxx Mosfet o.ä.
const byte _PWMpinB =  9;  // OC2B bzw. PH6 nicht invertiert, IRFxxxx Mosfet o.ä.
const byte _Poti = A0;     // Potentiometer

void setup()  {
  Serial.begin(9600);
 
  digitalWrite(_PWMpinA, LOW);    // OC2A
  pinMode(_PWMpinA, OUTPUT);   
  digitalWrite(_PWMpinB, LOW);    // OC2B
  pinMode(_PWMpinB, OUTPUT);     
 
  set_Timer2();
 
}

 
void loop() {           
 
  int value = analogRead(_Poti)/4; 
 
  OCR2A = value;                // PWM x%
  OCR2B = value/2;              // 1/2 PWM von OCR2A
 
  //Serial.print(F("PWM Wert: ")); Serial.println(value);
  //delay(1000);
 
                             
}   // loop Ende


// ****** Funktionen ******* //
   
void set_Timer2()       // Fast-PWM, Mode 3
{
  cli();         // Interrupts ausschalten
  TCCR2A = 0;    // Reset TCCR1A Register
  TCCR2B = 0;    // Reset TCCR1B Register
  TIMSK2 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT2  = 0;    // Reset Start-Counter
  TCCR2A = (1<<COM2A1) | (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);  // non invert, set Mode 3
  TCCR2B = (1<<CS21);                              // Prescaler 8 >> 7,8kHz
  OCR2A = 0;     // Pulsweite, < 255 (2^8)
  OCR2B = 0;     // Pulsweite, < 255 (2^8)
  sei();         // Interrupts einschalten
}  // end Funktion



Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Quote
ICR1  ist auch für Timer 1, kann man beim Timer 2 nicht ändern
ICR gibt es bei Timer2 nicht, weil Timer2 keine Input Capture Einheit hat

Das Register ist eigentlich dazu da externe Ereignisse zu erfassen. Hier wird es "missbraucht"

Doc_Arduino

Hallo,

jetzt hab ich nochmal trial & error gemacht, wegen Timer 2 Mode 7.
Steht nämlich laut meinem Verständnis so nicht komplett im Datenblatt.
Schon alleine die Taktberechnungsformel fehlt.
Auf Grund meiner Erkenntnisse von Timer 1 konnte es aber nicht viel anders sein.
Wenn OCR2A demnach TOP ist, muß OCR2B für die Pulsweite übrig bleiben. :)
Und siehe da, mit OCR2A = 128 erhält man einen Takt von 15,5kHz
Takt = µC Takt / Prescaler / (OCR2A+1)
Natürlich zwangsweise einhergehend mit reduzierter PWM Auflösung. In dem Fall nur noch 2^7.

Code: [Select]
/*
 Doc_Arduino - german Arduino Forum
 IDE 1.6.7
 Arduino Mega2560
 
 Timer 2: Fast-PWM, Mode 7
 TOP:  OCR2A     (Takt-Frequenz)
 Pulsweite: OCR2B  (<= TOP)
 Schaltpin:  9   (OC2B bzw. PH6) nicht invertiert
*/

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   // setzt das angegebene Bit auf 1
#endif

const byte _PWMpinB =  9;  // OC2B bzw. PH6 nicht invertiert, IRFxxxx Mosfet o.ä.
const byte _Poti = A0;     // Potentiometer

void setup()  {
  Serial.begin(9600);
  
  digitalWrite(_PWMpinB, LOW);    // OC2B
  pinMode(_PWMpinB, OUTPUT);      
  
  set_Timer2();
}

  
void loop() {          
  
  int value = analogRead(_Poti)/8;  // <= TOP beachten !!!

  OCR2B = value;         // PWM x%  // <= TOP beachten !!!
  
  //Serial.print(F("PWM Wert: ")); Serial.println(value);
  //delay(1000);
                    
}   // loop Ende


// ****** Funktionen ******* //
    
void set_Timer2()       // Fast-PWM, Mode 7
{
  cli();         // Interrupts ausschalten
  TCCR2A = 0;    // Reset TCCR1A Register
  TCCR2B = 0;    // Reset TCCR1B Register
  TIMSK2 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT2  = 0;    // Reset Start-Counter
  TCCR2A = (1<<COM2B1) | (1<<WGM21) | (1<<WGM20);  // non invert, set Mode 7
  TCCR2B = (1<<CS21) | (1<<WGM22);                 // Prescaler 8
  OCR2A = 128;   // TOP, zusammen mit Prescaler 8 >> 15,5kHz
  OCR2B = 0;     // Pulsweite, <= TOP
  sei();         // Interrupts einschalten
}  // end Funktion





Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

ICR gibt es bei Timer2 nicht, weil Timer2 keine Input Capture Einheit hat

Das Register ist eigentlich dazu da externe Ereignisse zu erfassen. Hier wird es "missbraucht"
Hallo,

meinte ich eigentlich, gibts nicht bei Timer 2. Nur blöd ausgedrückt.
Was meinst du mit missbraucht? Wenns das nicht gibt.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

murdok1980

Danke doc. Ich gelobe Besserung werd jetzt erstmal den code und das Datenblatt studieren um zu begreifen wie das funktioniert. Es nützt mir ja der code allein nichts wenn ich nicht kapiere was abläuft.
Grüße
Andre
Ich meld mich aber bestimmt noch mal. Das mit den 15khz teste ich natürlich auch.

murdok1980

@doc arduino
Mit anpassen des Pins meinst du diese constante hier const byte _PWMpinB = beliebiger PIN oder?

Serenifly

#24
Feb 09, 2016, 10:55 pm Last Edit: Feb 09, 2016, 10:57 pm by Serenifly
Beliebig nicht. Die PWM Pins sind fest. Zu jedem Timer gehören je nach Prozessor 2 oder 3 Pins. Und jeder Kanal A, B oder C (auf dem Mega) hat einen spezifischen Pin.

Doc_Arduino

#25
Feb 10, 2016, 10:54 am Last Edit: Feb 10, 2016, 12:29 pm by Doc_Arduino
Hallo,

wie schon Serenifly sagt, es handelt sich hier um die hardware kodierten Timer zugehörigen Pins. Die sind nicht änderbar. Deswegen habe ich im Code Kommentar auch den Atmel original Namen dahinter geschrieben. Zum Bsp. OC2A. Das ist eindeutig glasklar. Man muß dann nur die Pin-Nr. dafür suchen für seinen µC bzw. Arduinoboard. Ein User, auch hier im Forum, erstellt dazu schöne Pinouts.

http://www.pighixxx.com/test/pinoutspg/

http://www.pighixxx.com/test/portfolio-items/nano/?portfolioID=314

Beim Nano wäre OC2A an Arduino Pin 11. Es wurde hier nur das A vergessen. Am ICSP Header steht es richtig dran. Und OC2B wäre beim Nano Arduino Pin 3.

Zum Timer einstellen etwas generelles. Bsp. Timer 2. Ich habe das Datenblatt von meinem Mega2560 vor mir, die Kapitel Nummern sollten aber gleich sein. Du hast den Atmel 328P.

Man wählt den gewünschten Timer Mode.
Kapitel 20.10, Tabelle 20-8.
Setzt die dafür benötigten WGM Bits im entsprechenden Register.
Aus der Tabelle und der Mode Textbeschreibung geht dann noch hervor, welches Register für den Top-Wert zuständig ist und beeinflußt damit den Takt. Und es geht daraus noch hervor welches Register man für die Pulsweite nutzen kann/muß. Sollte aus den Bsp. deutlicher hervorgehen.

In der Tabelle fällt mir auch schon wieder ein Schreibfehler auf im Vergleich zur Timer 1 Beschreibung.
Statt WGM2, WGM1, WGM0 müßte entweder stehen
WGMn2, WGMn1, WGMn0 oder gleich WGM22, WGM21, WGM20
n ... steht immer für die Timer Nummer.
x ... steht immer für den Timer Kanal.
"Timer 2" muß wohl ein Lehrling bei Atmel geschrieben haben.  :-)
In der Timer 0 Beschreibung übrigens das gleiche.
Das darf dich nicht aus der Ruhe bringen.

Dann wählt man wie der zugehörige Timer Pin geschaltet werden soll. Ist natürlich vom gewählten Modus abhängig. Das wären die COM Bits. Tabellen 20-2 bis 20-7. Am Ende wählt man noch den gewünschten Prescaler mittels CS Bits. Tabelle 20-9.

Das war es dann im Grunde schon. Will man statt Timer Pins die Timer Interrupts nutzen, wird es nochmal spannender. Kapitel 14. allgemein, was es so gibt. Und Timer 2 speziell zur Freischaltung dieser 20.10.7

Das muß erstmal ausreichen. Lesen, verstehen, experimentieren. Dann wird das von ganz alleine.  :)



Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

gregorss

Zum Timer einstellen etwas generelles ...
Super Zusatzinfo! Karmamäßig!

Gruß

Gregor
Nicht lange fackeln, lass' Backen wackeln! (Seeed)

Doc_Arduino

Hallo,

Danke. Warum sollte man es neuen Arduino'lern schwerer machen als man es selbst hatte.
Den Rest muß man sich sowieso erarbeiten wenn man etwas ändern möchte.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

murdok1980

Was mich bis dato immer irretiert hat, dass man die Bits mit verschiedenen Schreibweisen setzen kann.
Muss man beim setzen der Bits eigentlich nur die 1er setzen, weil 0 automatisch drin steht?

Doc_Arduino

#29
Feb 10, 2016, 03:05 pm Last Edit: Feb 10, 2016, 03:06 pm by Doc_Arduino
Hallo,

ich lösche vorher die Register, obwohl die nach µC Reset eigentlich automatisch auf 0 stehen sollten.
Damit muß man nur noch gezielt seine Wunsch Bits setzen und ist besser lesbar.





Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up