-1

The op of pin 11 should be inverse of pin 3. I used digitalreadfast and digitalwritefast and used simple if else. But the delay is high as 10us. What should i do?

I found this code in forum but its form timer 1. I need it for timer 2.

void setup()
  {
  // Defining PB1 and PB2 as outputs by setting PORTB1 and PORTB2
  // Setting DDB1 and DDB2
  DDRB |= bit (DDB1) | bit (DDB2);

  // stop timer 1
  TCCR1A = 0;
  TCCR1B = 0;

  TCCR1A = bit (COM1B0) | bit (COM1B1)  // Set OC1B on Compare Match, clear
                                        // OC1B at BOTTOM (inverting mode)
         | bit (COM1A1)                 // Clear OC1A on Compare Match, set
                                        // OC1A at BOTTOM (non-inverting mode)
         | bit (WGM11);                 // Fast PWM, top at ICR1
  TCCR1B = bit (WGM12)  | bit (WGM13)   //       ditto
         | bit (CS11);                  // Start timer, prescaler of 8

  // Initialize OCR1A = 300 (pulse_width = 150us), OCR1B, and ICR1
  ICR1 = 0xFFFF;
  OCR1B = 299;
  OCR1A = ICR1 - OCR1B;

  }  // end of setup

void loop()
  {
  }
2
  • 3
    What should i do? ... use an inverter
    – jsotola
    Commented Mar 1 at 4:59
  • With fast PWM mode on timer2, pin 11 cannot be used. Only pin 3. See : forum.arduino.cc/t/atmega328p-timer2-fastpwm-mode/499500 . If you need the inverse of pin 3, then a simple inverter (say an transistor) can be used as @jsotola has suggested.
    – 6v6gt
    Commented Mar 1 at 8:58

2 Answers 2

3

You can't do it with Timer 2 without external hardware. This code will generate a 10 kHz signal on pin 3, however it uses both of the timer's registers to do that:

  • OCR2A is used to set the period (ie. the frequency)
  • OCR2B is used to set the duty cycle

const byte OUTPUT_PIN = 3;  // Timer 2 "B" output: OC2B

const byte n = 199;  // 10 kHz

void setup()
 {
  pinMode (OUTPUT_PIN, OUTPUT);

  TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on compare
  TCCR2B = bit (WGM22) | bit (CS21);         // fast PWM, prescaler of 8
  OCR2A =  n;                                // period
  OCR2B = ((n + 1) / 2) - 1;                 // 50% duty cycle
  }  // end of setup

void loop() { }
6
  • 1
    Note that a 50% duty cycle signal could be generated in CTC mode, with the outputs set to “toggle on compare match”. Commented Mar 1 at 13:19
  • 1
    and here, to complete the picture, is an NPN transistor configured as an inverter (NOT gate) tutorialspoint.com/build-an-inverter-with-a-transistor
    – 6v6gt
    Commented Mar 1 at 14:07
  • @EdgarBonet I tried at some length to get the inverted signal as well in various modes, but failed.
    – Nick Gammon
    Commented Mar 1 at 20:14
  • Did you try writing a “Force Output Compare” bit? Commented Mar 1 at 21:10
  • @EdgarBonet That doesn't seem to affect anything. According to the datasheet the effect only occurs when writing to that bit, not on an ongoing basis. In my testing, in CTC to OCR2A mode (010) the two outputs are out of phase, but not inverses of each other. In fact, they seem to be 50% out of phase with each other (for some reason). In mode 101 (PWM to OCR2A) I get no output (ie. 0V) on output B (D3).
    – Nick Gammon
    Commented Mar 2 at 0:22
2

As explained in Nick Gammon's answer, you cannot really generate two PWM signals at 10 kHz from Timer 2: the register OCR2A will be used to set the frequency, and you won't have independent control of the duty cycle of the OC2A output.

You can, however, make two 10 kHz complementary signals at 50% duty cycle. This is not really PWM (pulse width modulation), as you cannot actually modulate the pulse width. If this fits your needs, the solution is to configure the outputs in toggle mode. Writing the “force output compare B” bit creates an extra toggle of OC2B, which ensures that the outputs have then opposing phases. Here is the code to do that:

void setup() {
    TCCR2B = 0;           // stop Timer 2
    TCNT2  = 0;           // reset timer
    TCCR2A = _BV(COM2A0)  // toggle OC2A on compare match
           | _BV(COM2B0)  // toggle OC2B on compare match
           | _BV(WGM21);  // mode 2 = CTC, TOP = OCRA
    OCR2A  = 99;          // timer period = 100 * 2 * 8 / C_CPU
    OCR2B  = 99;          // toggle OC2A and OC2B simultaneously
    TCCR2B = _BV(CS21)    // clock @ F_CPU/8
           | _BV(FOC2B);  // force output compare B: invert OC2B signal
    DDRB  |= _BV(PB3);    // OC2A = PB3 = digital 11 as output
    DDRD  |= _BV(PD3);    // OC2B = PD3 = digital 3 as output
}

void loop(){}
2
  • Congratulations! You got it to work! As you say, you are limited to 50% duty cycle, still that is what the OP wanted - I think.
    – Nick Gammon
    Commented Mar 3 at 4:46
  • 1
    In case anyone is wondering, _BV and bit are virtually identical. In hardware/arduino/avr/cores/arduino/Arduino.h bit is defined as follows: #define bit(b) (1UL << (b)) and in hardware/tools/avr/avr/include/avr/sfr_defs.h _BV is defined as: #define _BV(bit) (1 << (bit)).
    – Nick Gammon
    Commented Mar 3 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.