timer not behaving as expected

I'm trying to implement my own (finer-grained) PWM

here's the code so far:

//=========
//timerTest
//=========

int counter = 0;

int pwm = 0;
int pwmMax = 20;

#define LEDPIN 10

boolean once = false;

void setup()
{
  
  //set pin as output
  //=================
  pinMode(LEDPIN, OUTPUT);

}

void mySetup(void)
{
  // stop interrupts
  //================
  cli();

  //set timer2 interrupts
  //=====================
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  
  // set compare match register
  // for number of increments
  //===========================
  OCR2A = 1;            // changing this seems to have no effect

  // turn on CTC mode
  //=================
  TCCR2A |= _BV(WGM21);

  // Set prescaler
  //==============
  TCCR2B |= _BV(CS20);

  // enable timer compare interrupt
  //===============================
  TIMSK2 |= (1 << OCIE2A);

  //allow interrupts
  //================
  sei();
}

ISR(TIMER2_COMPA_vect)
{
  counter++;
  if (counter > pwmMax)
  {
   counter = 0;
  
   if (counter < pwm && pwm > 0)
      digitalWrite(LEDPIN, HIGH);
  }
  
  if (counter >= pwm)
    digitalWrite(LEDPIN, LOW);  
}

void loop()
{
  int i;

  if (!once)
  {
    mySetup();
    once = true;
  }  
  
  for (i=0; i<pwmMax; i++)
  {
    pwm++;
    delay(2000);
  }
  for (i=0; i<pwmMax; i++)
  {
    pwm--;
    delay(2000);
  }
}

it almost works in that it does spit out a PWM signal on the required pin
but ...
a) it seems to effect how delay(2000) works - far less than two seconds
b) altering the line with OCR2A= seems to make no difference

what I want to achieve is
a) prescaler of 1
b) PWM frequency > 1 kHz
c) range of 0 - 1023 or better still 0-2048

what did I miss?

cheers
Mike

variables in an interrupt routine should be volatile ?

what did I miss?

Declaring pwm to be volatile? pwm is used by the ISR and loop(), so it needs to be volatile.

Agreed that you need "volatile".

I don't see a problem with how you've programmed the timer, and changing OCR2A should certainly affect the frequency of the interrupts. However, with a prescaler of 1 and OCR2A = 1, there isn't enough time to service each timer interrupt. Try prescaler = 128 or something, so you can verify that everything else is working.

jremington:
Agreed that you need "volatile".

I don't see a problem with how you've programmed the timer, and changing OCR2A should certainly affect the frequency of the interrupts. However, with a prescaler of 1 and OCR2A = 1, there isn't enough time to service each timer interrupt. Try prescaler = 128 or something, so you can verify that everything else is working.

ah that makes sense
I changed to volatile and it didn't make any difference
I'll try your suggestion
trouble is I think it'll slow everything down too much :frowning:

The pwm cycle time will be limited by the time it takes to service the timer interrupt. The minimum interrupt service time has been measured (or estimated) for typical gcc C/C++ code, but I don't recall what it is. Why not roll your own PWM using TIMER1, which is a 16 bit timer (but treated as 8 bit by the standard Arduino PWM software)?

The suggestion to set the prescaler to 128 was just to slow things down to the point where you can check basic functionality.