I'm creating PWM signals using CTC mode, but I need some help debugging

For a school project, we need to create 4 PWM signals with duty cycles between 0 - 100%
I was hoping to one day write a Software PWM library for the arduino, so I figured this would be a nice project to get started.
This is just a simple arduino program, not a library (although I do know how to write one).

I wrote a short program that will create a PWM signal on one pin, and from this program I wrote another program that should (but doesn't) create a PWM signal on 4 pins.

The first program:

#define SERVO_PIN 8
#define POT_PIN 0

unsigned int potValue[1];

void setup()
{
  pinMode(SERVO_PIN, OUTPUT);
  
  Serial.begin(9600);
  
  //Prepare the timer:
  noInterrupts(); //disable global interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  ICR1 = 40000; //set CTC refresh rate to 50 Hz
  
  //TCCR1A doesn't have any settings to be set
  TCCR1B |= _BV(WGM13) | _BV(WGM12) | _BV(CS11);
  //Timer counter interrupt mask register must be set to activate interrupts
  TIMSK1 |= _BV(ICIE1) | _BV(OCIE1A); //Interrupt when OCR1A has a compare match
  
  interrupts(); //re-enable interrupts
}

ISR(TIMER1_CAPT_vect)
{
  digitalWrite(SERVO_PIN, HIGH);
}

ISR(TIMER1_COMPA_vect)
{
  digitalWrite(SERVO_PIN, LOW);
  OCR1A = potValue[0];
}


void loop()
{
  potValue[0] = map(analogRead(POT_PIN), 0, 1023, 2600, 3400);
  Serial.println(OCR1A);
}

The second (problem) code:

volatile uint16_t timingValue[4] = {0,2000,500,600}; //zero initialize
static int PWMpinnen[4] = {8,9,10,11};

volatile unsigned int valueCheck;

void setup(){
  
  Serial.begin(9600);
  
  for (int i = 0; i < 4; i++){
    pinMode(PWMpinnen[i], OUTPUT);
  }
  
  noInterrupts(); //disable all interupts
  //clear the timer registers
  TCCR1A = 0;
  TCCR1B = 0;
  
  ICR1 = 40000; //Clear the timer at a frequency of 50Hz
  
  //TCCR1A doesn't have any settings needing to be set
  TCCR1B |= _BV(WGM12) | _BV(WGM11) | _BV(CS11); //Set timer to CTC mode (WGM12 && WGM11) and set prescaler to 8 (CS11)
  //interrupt register for timer1
  TIMSK1 |= _BV(ICIE1) | _BV(OCIE1A); //Enable interrupt on timer compare with OCR1A or TCNT1 == ICR1
  
  interrupts(); //re-enable all interrupts
}


ISR(TIMER1_CAPT_vect){
  OCR1A = ICR1 + 1; //added to make sure there's always one timingValue[] smaller than OCR1A
  for (int i = 0; i < 4; i++)
  {
    if (timingValue[i] == 0)
    {
      digitalWrite(PWMpinnen[i], LOW); //if duty cycle is 0%, write LOW to corresponding pin
    }
    else if (timingValue[i] == ICR1)
    {
      digitalWrite(PWMpinnen[i], HIGH); //if duty cycle is 100%, write HIGH to corresponding pin
    }
    else 
    {
      digitalWrite(PWMpinnen[i], HIGH); //write HIGH to the corresponding pin for now
      if (timingValue[i] < OCR1A){ //find the smallest timingValue that != 0
        OCR1A = timingValue[i];
        
      }
    }
  }  
   
}

ISR(TIMER1_COMPA_vect){
  volatile int oldOCR1A = OCR1A; //remember the current OCR1A value
  OCR1A = ICR1 + 3; // set a temporary value for OCR1A
  
  for (int i = 0; i < 4; i++)
  {
    if (timingValue[i] > oldOCR1A) //if the time hasn't come to set the pin to low yet
    {
      if (timingValue[i] < OCR1A) //find the lowest value that is still greater than the last OCR1A
      {
        OCR1A = timingValue[i];
        valueCheck = timingValue[i];
      }
    }
    else //if the timingValue is smaller or equal to the current OCR1A
    {
      digitalWrite(PWMpinnen[i], LOW); //write LOW, if the timingValue is smaller than the current OCR1A
    }
  }
  
}

void loop(){
  timingValue[0] = map(analogRead(0), 0, 1023, 2600, 3400); //trying to control a servo attached to pin 8
  
  Serial.println(valueCheck);
}

The first code can be used to control a servo on pin 8, while the second code can not control a servo on any pin.

I have tried debugging this issue for a while now, and it seems as if OCR1A isn't getting updated properly.

  • I tried printing the value of OCR1A. The result was that the first value was 0, and the following values were all 40003
  • I tried writing the value of OCR1A to a variable "valueCheck". The result was a value between 2600 and 3400 that corresponded to the position of my potmeter, but this value wouldn't change if I turned the potmeter. It would yield a different value if I restarted the arduino, though
  • I tried the same thing again, but this time I would write the value of timingValue[ i ] (or timingValue[0], since the other values are overwritten). This yielded the same result as the previous test. I would get an initial value between 2600 and 3400, but this wouldn't change until I resetted the arduino

Testing the first program seemingly proves that OCR1A may be adjusted inside an interrupt, so I don't understand why it won't update in the second program. I've experimented with making certain volatile or not, but this just yielded the same results.

I know there are other Waveform Generation Modes to create a PWM signal, but I'd like to continue working with this one. If I can learn why this method isn't working, or how to solve this issue, I will feel like I've learned another valuable programming lesson.

Thanks for reading up this far. If I've forgotten any details, I'll add them, or you can ask me about them and I will add them as a result.
Also, if there's something else wrong (coding style, code, whatever), please let me know, I want to learn from my mistakes.