Generate a High Frequency PWM

I want to create a high frequency (upto 80KHz) PWM signal for an induction heating application. I am unable to find how I can do that. I tried direct port manipulation but that still has delays and messes up the duty cycle and frequency. I am using the delayMicroseconds() function for my duty cycle.
What I want to do is to keep either tOn or tOff constant and then vary the other.
Can someone please tell me how to achieve this? BTW I have an Arduino UNO.

Show us what you tried, the entire sketch, in code tags please...

By the way, this thread is not about electronics, please send a mod a message to request a move to the programming forum.

This is an unusual requirement for PWM. Typically, the frequency would be fixed and the ratio of on to off time within the repeating period is called the duty cycle.

Can you please explain more about your application?

That is PPM, pulse position modulation. But yes, why?

You cannot create an 80kHz PWM signal by software with an UNO.
But you can use timer1 of the processor to create such a signal.

I think you'll need to read the timer sections of the chip's datasheet in detail for doing frequency modulation of a PWM pin reliably - the problem is when you shorten the cycle time there's a risk the counter becomes larger than the value of TOP and fails to wrap round until the timer itself wraps.

At 80kHz for a 16MHz processor you are talking about 200 system clocks per PWM cycle. But varying the pulse widths is going to vary that - might you need more than 256 cycles? That means using a 16 bit timer (timer1). Then the wrapping problem is a serious issue as a 16 bit timer wraps every 65536 clocks if you manage to skip past TOP by accident.

It would be much much easier to vary the duty cycle without changing the frequency.

1. The ATmega328P MCU of the UNO Board has hardware to genertae high frequency PWM signal using TCNT1 (Timer/Counter 1). The proposed 80 kHz signal will appear at DPin-9 of the UNO Board as per Fig-1. For test purpose, the duty cycle (ON-period) of the PWM signal ca be varied by rotating the Pot at 1-sec interval and the result will can be viewed as the increasing/decreasing brightness of LED1.

pwmAppOscTc1
pwmMode10Invert
Figure-1:

2. Upload the following skecth in UNO (untested).

void setup()  //generation of 80 kHz PWM signal using TCNT1
{
  Serial.begin(9600);
  pinMode(9, OUTPUT);   //DPin-9 will deliver PWM signal for Ch-A
  TCCR1A = 0b11100010;  //COM1A1 COM1A0 COM1B1 COM1B0 b4 b3 b2 WGM11 WGM10; Mode-10 PWM; inverting
  TCCR1B = 0b00010001; //b7 b6 b5 WGM13 WGM12 CS12 CS11 CS10; Mode-10 PWM; division factor = 1; clkTC1 = clkSYS/1
  ICR1 = 100;           //foc1A = 80 kHz; 
  //fDSPWM = (clkSYS/N)/(2*ICR1) = clkSYS/(2*N*ICR1) = clkSYS/(2*N*TOP)
  // 80*1000 = 16000000/(2*1*ICR1); ICR1 = 1600/16 = 100
  TCNT1 = 0x0000;       //initial count
}

void loop() //changing the duty cycle (ON-period) manually
{
  if (bitRead(TIFR1, OCF1A) == HIGH)//if TCNT1 matches with OCR1A;change duty cycle
  {
    bitSet(TIFR1, OCF1A);  //clear flag
    OCR1A = map(analogRead(A0), 0, 1023, 0, 95);//95 < ICR1 = 100 new value for new duty cycle
    Serial.println(OCR1A, DEC);  //shows the value written into OCR1 register
    delay(1000);  //test interval
  }
}

3. Slowly rotate Pot. Check that te brightness of LED1 changes. Check in the oscilloscope that the duty cycle of the PWM signal changes and the frequency is exactly 80 kHz.

4. Observe the OCR1 value in the Serial Monitor as the Pot is rotated. Check that the brightness decreases as the OCR1 value increases. Also, check that the new on-period is updated in 1-sec period. It agrees with Fig-1; where, the on-period reduces as the OCR1 value increases. Refer to Post-6 @MarkT and note that the value of OCR1 register (controls the duty cycle) is kept below the value of ICR1 register (controls the frequency at 80 kHz with value 100).

1 Like

I would try to use OC1B as output and OCR1A as TOP for the Timer1. Since output compare registers are buffered and update only at safe part of the cycle there is no risk of the "missed TOP" glitch.

@Smajdalf
If you are using OC1B as output and OCR1A to set frequency (TOP Parameter), then which register will control the duty cycle of the PWM signal in Mode-11?

OCR1B

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.