Timer0 being disabled

Hi everyone!
In the following code, I did not understand why Timer0 is being disabled. Can someone explain it to me. I want to use delay() and since timer0 is disabled, delay() is not working.

Hello
Post your sketch, well formated, with comments and in so called code tags "</>" to see how we can help.
Have a nice day and enjoy coding in C++.

The comment above the line where the timer 0 interrupt alludes to the reason:

//Disable Timer 1 interrupt to avoid any timing delays
  cbi (TIMSK0,TOIE0);              //disable Timer0 !!! delay() is now not available

If timer 0's interrupt was not disabled you'd have the chance of glitches in the sine wave ever 1.024mS as the processor is off doing T0 interrupt handling instead of updating the PWMs for the sine wave.

ooh okay. Is there a way to generate a delay of 1us in between the signals without using delay() (since Timer0 is disabled)

One microsecond? On an AVR at 16MHz a NOP (no-operation) take 62.5nS; if you inline 16 of them together you can generate a "delay" of 1uS. Something like:

__asm__ __volatile__(
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
  );

I feel like I and others just answered this question for you or someone else looking to do these exact same thing. Is this a school project or something?

Thanks a lot. I'll try this :slight_smile:

I tried this. Still can't generate a delay :frowning:

Can you show your code?

/*

  • DDS Sine Generator mit ATMEGS 328

  • Timer2 generates the 31250 KHz Clock Interrupt

  • Use Timer2 Interrupt to change duty cycle for the output PWM signals

  • D. Tolken

  • 120 degress out of phase signals for 3 phase BLDC motor controller

  • CPUT, South Africa

a Huge thumbs up and thanks must be given to Martin Nawrath for the developement of the original code to generate a sine wave using PWM and a LPF.

Link:

                                     http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/

*/

#include "avr/pgmspace.h" //Store data in flash (program) memory instead of SRAM

// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated

PROGMEM const uint16_t sine256[] = {

127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,

242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,

221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,

76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,

33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124

};

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) //define a bit to have the properties of a clear bit operator

#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator

int PWM1= 10;// PWM1 output, phase 1

int PWM2 = 9; //PWM2 ouput, phase 2

int PWM3 = 11; //PWM3 output, phase 3

int PWM4 = 2; // PWM phase 1 inverted

int PWM5 = 5; //PWM phase 2 inverted

int PWM6 = 12; //PWM phase 3 inverted

int offset_1 = 85; //offset 1 is 120 degrees out of phase with previous phase, Refer to PWM to sine.xls

int offset_2 = 170; //offset 2 is 120 degrees out of phase with offset 1. Refer to PWM to sine.xls

int program_exec_time = 6; //monitor how quickly the interrupt trigger

int ISR_exec_time = 7; //monitor how long the interrupt takes

double dfreq;

const double refclk=31376.6; // measured output frequency

// variables used inside interrupt service declared as voilatile

volatile byte current_count; // Keep track of where the current count is in sine 256 array

volatile byte ms4_delay; //variable used to generate a 4ms delay

volatile byte c4ms; // after every 4ms this variable is incremented, its used to create a delay of 1 second

volatile unsigned long phase_accumulator; // pahse accumulator

volatile unsigned long tword_m; // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.

void setup()

{

pinMode(PWM1, OUTPUT); //sets the digital pin as output

pinMode(PWM2, OUTPUT); //sets the digital pin as output

pinMode(PWM3, OUTPUT); //sets the digital pin as output

pinMode(PWM4, OUTPUT);

pinMode(PWM5, OUTPUT);

pinMode(PWM6, OUTPUT);

pinMode(program_exec_time, OUTPUT); //sets the digital pin as output

pinMode(3, OUTPUT); //sets the digital pin as output

sbi(PORTD,program_exec_time); //Sets the pin

Setup_timer1();

Setup_timer2();

Setup_timer3();

//Disable Timer 1 interrupt to avoid any timing delays

// cbi (TIMSK0,TOIE0); //disable Timer0 !!! delay() is now not available

sbi (TIMSK2,TOIE2); //enable Timer2 Interrupt

dfreq=50.0; //initial output frequency = 1000.o Hz

tword_m=pow(2,32)*dfreq/refclk; //calulate DDS new tuning word

}

void loop()

{

while(1)

{

  sbi(PORTD,program_exec_time); //Sets the pin 

  if (c4ms > 250) // c4ms = 4ms, thus 4ms *250 = 1 second delay

   {                 

    c4ms=0;                          //Reset c4ms

// dfreq=analogRead(0); //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 1.023kHz

    cbi (TIMSK2,TOIE2);              //Disable Timer2 Interrupt

    tword_m=pow(2,32)*dfreq/refclk;  //Calulate DDS new tuning word

    sbi (TIMSK2,TOIE2);              //Enable Timer2 Interrupt 

  }

}

}

//Timer 0 setup

//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock

void Setup_timer3(void)

{

// Timer0 Clock Prescaler to : 1

sbi (TCCR3B, CS30);

cbi (TCCR3B, CS31);

cbi (TCCR3B, CS32);

// Timer0 PWM Mode set to Phase Correct PWM

cbi (TCCR3A, COM3A0);

sbi (TCCR3A, COM3A1);

cbi (TCCR3A, COM3B0);

sbi (TCCR3A, COM3B1);

// Mode 1 / Phase Crrect PWM

sbi (TCCR3A, WGM30);

cbi (TCCR3A, WGM31);

cbi (TCCR3B, WGM32);

//cbi (TCCR0B, WGM03);

}

//Timer 1 setup

//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock

// void Setup_timer0(void){

// cbi (TCCR0A, COM0A1);

// cbi (TCCR0A, COM0A0);

// cbi (TCCR0A, COM0B1);

// cbi (TCCR0A, COM0B0);

// cbi (TCCR0A, WGM00);

// cbi (TCCR1A, WGM01);

// sbi (TCCR0B, CS00);

// cbi (TCCR0B, CS01);

// cbi (TCCR0B, CS02);

// }

void Setup_timer1(void)

{

// Timer1 Clock Prescaler to : 1

sbi (TCCR1B, CS10);

cbi (TCCR1B, CS11);

cbi (TCCR1B, CS12);

// Timer1 PWM Mode set to Phase Correct PWM

cbi (TCCR1A, COM1A0);

sbi (TCCR1A, COM1A1);

cbi (TCCR1A, COM1B0);

sbi (TCCR1A, COM1B1);

// Mode 1 / Phase Correct PWM

sbi (TCCR1A, WGM10);

cbi (TCCR1A, WGM11);

cbi (TCCR1B, WGM12);

cbi (TCCR1B, WGM13);

}

//Timer 1 setup

//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock

void Setup_timer2()

{

// Timer2 Clock Prescaler to : 1

sbi (TCCR2B, CS20);

cbi (TCCR2B, CS21);

cbi (TCCR2B, CS22);

// Timer2 PWM Mode set to Phase Correct PWM

cbi (TCCR2A, COM2A0); // clear Compare Match

sbi (TCCR2A, COM2A1);

cbi (TCCR2A, COM2B0);

sbi (TCCR2A, COM2B1);

// Mode 1 / Phase Correct PWM

sbi (TCCR2A, WGM20);

cbi (TCCR2A, WGM21);

cbi (TCCR2B, WGM22);

}

//Timer2 Interrupt Service at 31372,550 KHz = 32uSec

//This is the timebase REFCLOCK for the DDS generator

//FOUT = (M (REFCLK)) / (2 exp 32)

//Runtime : 8 microseconds

ISR(TIMER2_OVF_vect)

{

cbi(PORTD,program_exec_time); //Clear the pin

sbi(PORTD,ISR_exec_time); // Sets the pin

phase_accumulator=phase_accumulator+tword_m; //Adds tuning M word to previoud phase accumulator. refer to DDS_calculator (from Martin Nawrath) for explination.

current_count=phase_accumulator >> 24; // use upper 8 bits of phase_accumulator as frequency information

OCR2A=pgm_read_byte_near(sine256 + current_count); // read value fron ROM sine table and send to PWM.. pin 10

OCR2B=pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_1)); // read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM1..pin9

OCR1A = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2..pin11

// //OCR1B = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2

asm volatile(

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

"nop\n\t"

);

OCR3B= 255-OCR2A; //pin2

OCR3A= 255-OCR2B; //pin5

OCR1B= 255-OCR1A; //pin12

//increment variable ms4_delay every 4mS/125 = milliseconds 32uS

if(ms4_delay++ == 125)

{

c4ms++;

ms4_delay=0; //reset count

}

cbi(PORTD,ISR_exec_time); //Clear the pin

}

BTW I'm working on Arduino Mega 2560

Did you understand why it is not working in my code?

Please edit your post to put the code within code tags.

/*
 *
 * DDS Sine Generator mit ATMEGS 328
 * Timer2 generates the  31250 KHz Clock Interrupt
 * Use Timer2 Interrupt to change duty cycle for the output PWM signals
 * D. Tolken
 * 120 degress out of phase signals for 3 phase BLDC motor controller
 * CPUT, South Africa


a Huge thumbs up and thanks must be given to Martin Nawrath for the developement of the original code to generate a sine wave using PWM and a LPF.
Link:
                                         http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/
*/

#include "avr/pgmspace.h" //Store data in flash (program) memory instead of SRAM

// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM const uint16_t sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124

};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) //define a bit to have the properties of a clear bit operator
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator

int PWM1= 10;// PWM1 output, phase 1
int PWM2 = 9; //PWM2 ouput, phase 2
int PWM3 = 11; //PWM3 output, phase 3
int PWM4 = 2; // PWM phase 1 inverted
int PWM5 = 5; //PWM phase 2 inverted
int PWM6 = 12; //PWM phase 3 inverted

int offset_1 = 85; //offset 1 is 120 degrees out of phase with previous phase, Refer to PWM to sine.xls
int offset_2 = 170; //offset 2 is 120 degrees out of phase with offset 1. Refer to PWM to sine.xls
int program_exec_time = 6; //monitor how quickly the interrupt trigger
int ISR_exec_time = 7; //monitor how long the interrupt takes

double dfreq;
const double refclk=31376.6;      // measured output frequency

// variables used inside interrupt service declared as voilatile
volatile byte current_count;              // Keep track of where the current count is in sine 256 array
volatile byte ms4_delay;             //variable used to generate a 4ms delay
volatile byte c4ms;              // after every 4ms this variable is incremented, its used to create a delay of 1 second
volatile unsigned long phase_accumulator;   // pahse accumulator
volatile unsigned long tword_m;  // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.

void setup()
{
  pinMode(PWM1, OUTPUT);      //sets the digital pin as output
  pinMode(PWM2, OUTPUT);      //sets the digital pin as output
  pinMode(PWM3, OUTPUT);      //sets the digital pin as output
  pinMode(PWM4, OUTPUT);
  pinMode(PWM5, OUTPUT);
  pinMode(PWM6, OUTPUT);
  
  pinMode(program_exec_time, OUTPUT);      //sets the digital pin as output
  pinMode(3, OUTPUT);         //sets the digital pin as output
  sbi(PORTD,program_exec_time); //Sets the pin
  

  Setup_timer1();
  Setup_timer2();
  Setup_timer3();
  
  //Disable Timer 1 interrupt to avoid any timing delays
 // cbi (TIMSK0,TOIE0);              //disable Timer0 !!! delay() is now not available
 
  sbi (TIMSK2,TOIE2);              //enable Timer2 Interrupt

  dfreq=50.0;                    //initial output frequency = 1000.o Hz
  tword_m=pow(2,32)*dfreq/refclk;  //calulate DDS new tuning word 

}
void loop()
{
  while(1) 
  {
      sbi(PORTD,program_exec_time); //Sets the pin 
      if (c4ms > 250) // c4ms = 4ms, thus 4ms *250 = 1 second delay
       {                 
        c4ms=0;                          //Reset c4ms
//        dfreq=analogRead(0);             //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 1.023kHz
        cbi (TIMSK2,TOIE2);              //Disable Timer2 Interrupt
        tword_m=pow(2,32)*dfreq/refclk;  //Calulate DDS new tuning word
        sbi (TIMSK2,TOIE2);              //Enable Timer2 Interrupt 
      }
  }
}

//Timer 0 setup
//Set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer3(void)
{
  // Timer0 Clock Prescaler to : 1
  sbi (TCCR3B, CS30);
  cbi (TCCR3B, CS31);
  cbi (TCCR3B, CS32);
  
  // Timer0 PWM Mode set to Phase Correct PWM
  cbi (TCCR3A, COM3A0);
  sbi (TCCR3A, COM3A1);
  cbi (TCCR3A, COM3B0); 
  sbi (TCCR3A, COM3B1);

  // Mode 1 / Phase Crrect PWM
  sbi (TCCR3A, WGM30); 
  cbi (TCCR3A, WGM31);
  cbi (TCCR3B, WGM32);
  //cbi (TCCR0B, WGM03);
}


//Timer 1 setup
//Set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock

// void Setup_timer0(void){
//  cbi  (TCCR0A, COM0A1);
//  cbi  (TCCR0A, COM0A0);
//  cbi  (TCCR0A, COM0B1);
//  cbi  (TCCR0A, COM0B0);

//  cbi (TCCR0A, WGM00); 
//  cbi (TCCR1A, WGM01);

//   sbi (TCCR0B, CS00);
//   cbi (TCCR0B, CS01);
//   cbi (TCCR0B, CS02);
// }

void Setup_timer1(void)
{
  // Timer1 Clock Prescaler to : 1
  sbi (TCCR1B, CS10);
  cbi (TCCR1B, CS11);
  cbi (TCCR1B, CS12);
  
  // Timer1 PWM Mode set to Phase Correct PWM
  cbi (TCCR1A, COM1A0);
  sbi (TCCR1A, COM1A1);
  cbi (TCCR1A, COM1B0); 
  sbi (TCCR1A, COM1B1);

  // Mode 1 / Phase Correct PWM
  sbi (TCCR1A, WGM10); 
  cbi (TCCR1A, WGM11);
  cbi (TCCR1B, WGM12);
  cbi (TCCR1B, WGM13);
}

//Timer 1 setup
//Set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer2() 
{
  // Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

  // Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0);  // clear Compare Match
  sbi (TCCR2A, COM2A1);
  cbi (TCCR2A, COM2B0); 
  sbi (TCCR2A, COM2B1);
  
  // Mode 1  / Phase Correct PWM
  sbi (TCCR2A, WGM20);  
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);
}


//Timer2 Interrupt Service at 31372,550 KHz = 32uSec
//This is the timebase REFCLOCK for the DDS generator
//FOUT = (M (REFCLK)) / (2 exp 32)
//Runtime : 8 microseconds
ISR(TIMER2_OVF_vect)
{
  cbi(PORTD,program_exec_time); //Clear the pin
  sbi(PORTD,ISR_exec_time);          // Sets the pin

  phase_accumulator=phase_accumulator+tword_m; //Adds tuning M word to previoud phase accumulator. refer to DDS_calculator (from Martin Nawrath) for explination.
  current_count=phase_accumulator >> 24;     // use upper 8 bits of phase_accumulator as frequency information                      
  
  OCR2A=pgm_read_byte_near(sine256 + current_count); // read value fron ROM sine table and send to PWM.. pin 10
  OCR2B=pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_1)); // read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM1..pin9
  
  OCR1A = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2..pin11
  
//   //OCR1B = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2
 
 __asm__ __volatile__(
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
  );


  OCR3B= 255-OCR2A; //pin2
  OCR3A= 255-OCR2B; //pin5
  OCR1B= 255-OCR1A; //pin12

  //increment variable ms4_delay every 4mS/125 =  milliseconds 32uS
  if(ms4_delay++ == 125) 
  {  
    c4ms++;
    ms4_delay=0; //reset count
   }   

 cbi(PORTD,ISR_exec_time);            //Clear the pin
}

I have uploaded the code correctly. Did you find the code?

What is this running on? The comment suggest a '328 but when I attempt to compile I get a failure because of the references to TCCR3A etc. Is it a Mega2560?

I am running this on a mega 2560. Please don't ind the comment

It's hard to tell where the 1uS should be happening when looking at the PWMs so I added a couple of lines to the code:

In setup():

.
.
.
    pinMode(8,OUTPUT);
.
.
.

and in ISR(TIMER2_OVF_vect):

.
.
.
    PORTH |= 0b00100000;    //<-- added
  __asm__ __volatile__(
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
  );
  PORTH &= 0b11011111;    //<-- added
.
.
.

and triggered of pin 8 (which is PH5 on the Mega).

I see a pulse happening every 32uS which is 1.31uS wide. If I comment out 5 of the NOPs -- to offset the delay added by the PORTH operations, I see a 1uS wide pulse.

Try adding the same and commenting out 5 of the NOPs and see if that helps.

It may be that the compiler optimizes out the NOPs if it doesn't appear they're used for anything.

Thanks a lot. Will try this :slight_smile:

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