Timer 1 behavior that i don't understand.

Hi! I am currently reading the ATMega328p datasheet and i’ve written the following code, it generates 2 different PWM frequencies on pins 10 and 9 (similar to the Fast PWM Mode with OCRA top example on https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM ,but using Timer 1 directly), one of the issues i’m facing it that if i delete the Serial.begin(9600) command , the code won’t work , considering that i’m not using Serial.begin(9600) for anything , what is the cause of this behavior?

int compareMatchReg;

void setup() {

DDRB |= (1 << PB1) | (1 << PB2) ;

Serial.begin(9600);
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;

compareMatchReg = 799 ;// preload timer
ICR1 = compareMatchReg;

OCR1BL = 0;
OCR1BH = 399;
//PIN9 2.4KHz OC1A
//PIN10 4.9KHz OC1B

TCCR1A |= (1<<WGM11) | (1<<COM1A1) | (1<<COM1B1); //| (1<<COM1A0) | (1<<COM1B0);
TCCR1B |= (1<<CS11) | (1<<WGM12) | (1<<WGM13); //

TIFR1 |= (1<<OCF1B) | (1<<TOV1);
TIMSK1 |= (1 << TOIE1) | (1 << OCIE1B); // enable timer overflow interrupt
interrupts(); // enable all interrupts
}

void loop() {

}

Your program is exhibiting strange behavior because you have enabled two timer interrupts, but there are no corresponding ISR’s. This causes jumps to a reset vector. Either don’t enable the interrupts, as you are not using them, or else use some dummy interrupt vectors.

TIMSK1 |= (1 << TOIE1) | (1 << OCIE1B);
ISR(TIMER1_COMPB_vect)
{}
ISR(TIMER1_OVF_vect)
{}

It’s unclear what is happening here, and I don’t think you are getting a value of OCR1B you want. The upper byte register overflows.

OCR1BL = 0;
  OCR1BH = 399;

The Arduino ide will take care of the high byte low byte 16 bit registers and just use
OCR1B = some value

it generates 2 different PWM frequencies on pins 10 and 9

Your code does not do that. The frequencies are the same as controlled by ICR1, but the duty cycles are different. I think that you want to have explict values for both OCR1A and OCR1B.

Hi again, i was using the wrong driver for my arduino, i corrected that and implemented the recommendations of cattledog, the code below generates 2 different PWM signals (on pins 9 and 10).

/*Arduino NANO (generic), ATMega328p old bootloader. 1/27/2020 */

const int led_pin = PB1; //Pin 9
const int led_pina = PB2; //Pin 10

void setup() {
// put your setup code here, to run once:

DDRB |= (1<<led_pina) | (1<<led_pin); // Set pins 9 and 10 as outputs.

/* Configure Timer 1 for Fast PWM mode,Top = ICR1 ,Clear OC1A/OC1B on compare match, set OC1A/OC1B at
BOTTOM (non-inverting mode) and no prescaling */

TCCR1A = 0;
TCCR1B = 0;

TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11) ;
TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS10);

/* fOCnxPWM = fclk_I/O /(N*(1 + TOP))
TOP = (fclk_I/O / N *fOCnxPWM) -1

Where fOCnxPWM = Desired frequency in Hz, N = prescaler and fclk_I/O = Clock frequency in Hz (in my case 16x10^6 Hz).

*/

ICR1 = 6000; /* Top for a frequency of 2666.2 Hz */
OCR1A =4000; /*Pin 9 Frequency = 1.33 KHz */
OCR1B =3000; /*Pin 10 Frequency = 2.66 KHz */

TIFR1 = 0;
TIMSK1 = 0;
TIMSK1 = (1 << OCIE1A); /* Enable the Timer/Counter1, Output Compare A Match Interrupt */

}

void loop() {}

ISR(TIMER1_COMPA_vect) {

/* Toggle OC1A (pin 9) on compare match */
DDRB ^= (1<<led_pin);

}

ICR1 = 6000; /* Top for a frequency of  2666.2 Hz */
OCR1A =4000; /*Pin 9 Frequency  =  1.33 KHz */
OCR1B =3000; /*Pin 10 Frequency =  2.66 KHz */
TIMSK1 = (1 << OCIE1A);  /* Enable the Timer/Counter1, Output Compare A Match Interrupt */

ISR(TIMER1_COMPA_vect) {
  /* Toggle OC1A (pin 9) on compare match */
  DDRB ^= (1<<led_pin); 
}

I understand that you are trying to generate half frequency by toggling the pin 9 mode between input and output on alternate cycles

Do you have oscilloscope traces for the output on pin 9? It’s not clear to me that by toggling the pinMode between input and output, while the hardware pwm is enabled is going to give you correct control over duty cycle. It’s also possible that you will get a short output pulse under the circumstance where the mode switches from output to input a few microseconds after the pin is driven high by the hardware output.

You may see more well defined behaviour if you toggle the pin in an overflow vector instead of compare match. The duty cycle will still need to be corrected to accomodate for the active and blank cycle.

I don’t have an available oscilloscope (maybe in the near future), i will post the results when i get one , the frequencies i indicated for pins 9 and 10 were measured using an UNI-T UT-210D multimeter, im using the PWM signals to control the inductor of the following boost converter.

I measured the frequency between nodes 1 and 2 . The inductor i’m using is the coil of a 12v car relay.

im using the PWM signals to control the inductor of the following boost converter.

If you are not using output from pins 9 and 10 at the same time, I think it is better to change the frequency of the desired output with ICR1. You can use a switch to select between output frequencies.