Timer 2 15 khz frequenz mit variabler duty cycle

Ich bräuchte am Pin 11 eine Frequenz vom 15,6 khz mit variabler duty cycle. Das alles mit dem Timer 2 die 8bit reichen mir. Mit dem Timer 1 hab ich das schon für 2 Kanäle erreicht. Hab dafür ICR als Top Wert genommen und OCR1A und OCR1B als variable duty cycle.
Den Modus gibt es aber bei Timer 2 nicht und mit dem Togglen eines Pins kenn ich mich nicht so aus.
Ich brauch das für einen 3. PWM Kanal.
Kann mir jemand beim Bitsetzen in die Register helfen.
Nutze nen Arduino Nano.
Grüße
Andre

Hallo,

wenn du dein Wissen von Timer 1 auf Timer 2 überträgst, sollte das Ding laufen.
Blick ins Datenblatt ist nicht ausreichend? Ab Kapitel 20 im Datenblatt.

Wobei die Wunsch 15kHz wohl nicht möglich sind. Der Takt wird nur von den 16MHz µC und dem eingestellten Prescaler beeinflusst.

Ansonsten könnte man bestimmt noch "tricksen" indem man im Timer ISR x beliebige Pins je nach Timer Counter schalten läßt. Sowas in der Art wurde hier mal besprochen. Bitte mal lesen. Aus der Kalten heraus mach ich das auch nicht. ATMega und Timer (statt RTC und SQW bzw 32K) - Deutsch - Arduino Forum

Edit:
zeig mal bitte deinen bisherigen Code ( in </> Code Tags bitte oder .ino Datei ranhängen)

murdok1980:
Ich bräuchte am Pin 11 ...

Als ich einmal versucht habe, einen Code, der auf Pin 3 Timer-gesteuert arbeitete, auf einen anderen Pin „umzuziehen“, hat sich herausgestellt, dass es nicht funktionieren kann, weil sich dann die Bedeutung eines Registers ändert. Was vorher als „Output Compare“-Wert interpretiert wurde, wurde zu irgendeinem „Top-“ oder „Down-Wert“.

Seither weiß ich, dass Timerprogrammierung nicht ganz einfach ist und längst nicht alles auf allen Pins machbar ist. Und obwohl ich den betreffenden Teil des (ATmega328-) Datenblattes mehrmals konzentiert durchgelesen hatte, habe ich das Problem nicht selbst gefunden.

Der Code, von dem ich damals ausgegangen bin, basierte auf der Application Note auf dieser Seite.

Grundsätzlich wäre gut, wenn Du Deinen (aufgeräumten :wink: Code mal zeigen könntest.

Gruß

Gregor

Hallo,

das mit dem Pin 11 und Timer 2 haut auf dem Uno schon hin. Ist der hardware kodierte Timer 2 Pin OC2A.
Sollte auch für den Nano gültig sein, denke ich.

Ich hätte jetzt ein Bsp. fertig mit Mode 3 für den Timer 2. Aber wenn der TO keinen Code zeigt, gibts nichts.

Mode 7 bekomme ich noch nicht hin. Macht aber denke ich, mit weniger als 8Bit Auflösung auch keinen Sinn.
Wobei ich zugeben muß, dass die Registerbezeichnung beim Timer 2 im Datenblatt schon etwas anders ist. Die Namen wie im Datenblatt kennt der Compiler einfach nicht. Zum Bsp. OCRA. OCR2A und OCR2B gibt es, steht aber so nicht im Datenblatt. Weis noch nicht so recht was den Datenblatt Schreiberling dabei geritten hat.

Die einzige Stelle wo "OCRA" auftaucht ist in der Waveform Generation Tabelle. Überall anders steht die genaue Bezeichnung.

Doc_Arduino:
...
Wobei ich zugeben muß, dass die Registerbezeichnung beim Timer 2 im Datenblatt schon etwas anders ist. Die Namen wie im Datenblatt kennt der Compiler einfach nicht. Zum Bsp. OCRA. OCR2A und OCR2B gibt es, steht aber so nicht im Datenblatt. Weis noch nicht so recht was den Datenblatt Schreiberling dabei geritten hat.

Was meinst Du? In meiner Version des Datenblattes stehen einwandfreie Namen drin (http://test.szaktilla.de/shot.png). Ich habe da nur mal willkürlich ein paar Markierungen reingemalt.

Gruß

Gregor

Hallo,

ich rede vom Datenblatt von meinem Mega2560 im Kapitel 20 - Timer 2. Dabei interessiert mich die außere Pinbelegung noch nicht wirklich. Aus dem Kapitel möchte ich nur herauslesen welches Register was macht und wie ich es setzen muß.

Also kann man sagen das in der Tabelle mit OCRA eigentlich OCR2A gemeint ist?
Irgendeine Timer Nummer muß ja enthalten sein im Namen.

Was ich auch probiert hatte war mit dem digitalWrite(Pin, LOW);
Klappte aber nicht. Einmal 0 immer 0.
Dann habe ich nachgeschaut wie das in der wiring_analog gemacht wird.
Klappte aber mit auch nicht. Einmal 0 immer 0.

int value = analogRead(_Poti)/4;  
  
  if (value == 0)  {
    digitalWrite(_PWMpin, LOW);   // PWM 0% an Pin 10
  }
  else  {
    TCCR2A = (1<<COM2A1);
    OCR2A = value;                // PWM x% an Pin 10
  }

Mich wundert auch das "Arduino" zum jedesmal neu setzen der Register die Interrupts nicht ausschaltet.

Edit:
ähm ja, ich muß ja entweder das Register komplett neu setzen wie beim Timer setzen oder nur das eine Bit zwischendurch. Mein Fehler. Scheinbar wird mit digitalWrite der gesamte Timer zurückgesetzt. Oder so ähnlich.

Musst du do

Doc_Arduino:
Also kann man sagen das in der Tabelle mit OCRA eigentlich OCR2A gemeint ist?
Irgendeine Timer Nummer muß ja enthalten sein im Namen.

Ja. Ich das nie anders verstanden

Hallo,

bestimmt sollte da stehen OCRnA oder eben gleich OCR2A.
Ähnlich wie beim Timer 1. Da ist alles glas klar. :slight_smile:

Warum in der wiring_analog jedoch keine ISR's ausgeschalten werden müssen würde mich schon interessieren. :wink:

Doc_Arduino:
ähm ja, ich muß ja entweder das Register komplett neu setzen wie beim Timer setzen oder nur das eine Bit zwischendurch. Mein Fehler. Scheinbar wird mit digitalWrite der gesamte Timer zurückgesetzt. Oder so ähnlich.

Eigentlich sollte nur das entsprechende COMnA/B1 Bit gelöscht werden. Siehe turnOffPWM() in wiring_digital.c

z.B.:

		#if defined(TCCR2A) && defined(COM2A1)
		case  TIMER2A:  cbi(TCCR2A, COM2A1);    break;
		#endif
		#if defined(TCCR2A) && defined(COM2B1)
		case  TIMER2B:  cbi(TCCR2A, COM2B1);    break;
		#endif

Hallo,

ja, macht es auch. Ich hatte aber dummerweise nur immer das eine Bit in das komplette Register geschrieben. Die anderen gesetzten Bits damit gelöscht. :slight_smile:

Wenn ich nun sbi definiere, dann klappt auch nur das Bit setzen. :slight_smile:

sbi(TCCR2A, COM2A1);

Nur warum müssen dafür die Interrupts nicht ausgeschaltet werden? Soll man doch machen denke ich.

Den Teil für die PWM des Timers 1 setz ich dann gleich rein.

@ doc_arduino
Wie versprochen der Codeteil für die PWM an PIN 9 und 10.

TCCR1A = _BV(COM1A1) | _BV(COM1B1) ;      // Phase und Frequenz correct Modus. Nicht invertiert Modus
TCCR1B = _BV(WGM13) | _BV(CS10);           // Auswahl Modus 8 mit Teiler 1 zum CPU Takt
ICR1 = 512;// ICR1 = 512, Frequenz = 15,625kHz (16000000 Hz / ( 2 x Prescaler x 512 ))

und in die Register OCR1A und OCR1B schreib ich dann die entsprechende Werte die ich für die duty cycle brauch und steuer 2 H-Brücken Treiber an. Der Wert für die OCR1A und OCR1B Register kommt aus einem RC Empfänger, welchen ich am PIN 2 und 3 auslese.

Es soll ja nicht so aussehen als wöllte ich hier nur schnorren wollen.
So wie das Beispiel oben geht das beim Timer 2 ja nicht weil entsprechende Register fehlen aber eine etwa gleiche Funktion müsste gehen. Wie gesagt die 8Bit reichen mir aus.

Grüße Andre

Bei Timer2 geht das mit einem Pin. Aber nicht mit zwei. Der Vorteil von Timer1 ist eben das Input Capture Register. Das wird dann in dem Modus als TOP genommen, so dass man beide Output Compare Register frei hat.

Hallo,

deinen Versuchscode vom Timer 2 zeigste uns nicht? Bin heute aber streng. :slight_smile:

Will nich das ihr mich auslacht :slight_smile:

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

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

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

/*
 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

Hallo,

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

/*
 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

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"