PWM (Part 3)

Part 1234

We previously used OCR2A register for storing the upper counting limit for the base frequency of the generated wave. OCR2B is the second register related to timer 2, which is compared to TCNT2 for triggering specific events. In our case, we will not trigger the OC2B because it is physically one pin (PIND3 actually).

Instead, we will use the interrupt generated by the event for switching any pin on and off at our convenience.

ISR(TIMER2_COMPB_vect)
/* Invoked when TCNT2 reaches OCR2B */
{
	if(TCNT2

Setting OCR2B value is very simple. It will be a fraction of the full counting range that we computed before. The on/off ratio, so as to say the duty cycle may range from 0 to 100%.

It turns out that 0% may generate an error do the fact that the ratio is at the denominator of the equation which sets OCR2B. So that I decided to add two special cases for 0 and 100% duty cycles: the interrupt shall be disabled in both cases and Arduino will generate a flat signal at 0 and 5V.

void PlainPWM::SetDutyCycle(uint8_t dutyCycle)
/* Set duty cycle */
{
	if (dutyCycle == 0) {
		TIMSK2 = 0x00; /* Disable timer2 interrupt on match B */
		PORT(*_port) &= ~(0x01 << _pin);
	}
	else if (dutyCycle == 100) {
		TIMSK2 = 0x00; /* Disable timer2 interrupt on match B */
		PORT(*_port) |= (0x01 << _pin);
	}
	else {
		TIMSK2 |= (0x01 << OCIE2B); /* Enable timer2 interrupt on match B */
		OCR2B = uint8_t((_upperCount * dutyCycle) / 100.0);
	}
};

Next post on same subject

Leave a Reply

You must be logged in to post a comment.