Timer1 turns off temporarily

Hey all. I've been working on this stroboscope project, using timer1 on the arduino nano. Anyways, when I try to divide the output frequency and set up timer1 to generate it, it turns off the output for around a second for no apparent reason. It doesn't do this every time, and sometimes it turns off longer than other times. The code:

volatile long previousMillis5 = 0;
volatile long previousMillis4 = 0;
volatile double strobe_frequency = 20;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), multiplyByTwo, RISING);
  attachInterrupt(digitalPinToInterrupt(3), divideByTwo, RISING);
}
volatile void multiplyByTwo() {
  if ((strobe_frequency * 2.0) < 31250 && previousMillis4 + 200 < millis()) { //software debounce
    strobe_frequency = strobe_frequency * 2.0;
    previousMillis4 = millis();
  }
}
volatile void divideByTwo() {
  if ((strobe_frequency / 2.0) > 1 && previousMillis5 + 200 < millis()) { //software debounce
    strobe_frequency = strobe_frequency / 2.0;
    previousMillis5 = millis();
  }
}
// the loop function runs over and over again forever
void loop() {
  generateFrequency(strobe_frequency, 0.01);
}

volatile void generateFrequency(double frequency, double dutyCycle) {
  pinMode(10, OUTPUT);
  frequency = round(frequency * 100.0) / 100.0;
  if (dutyCycle == 0) {
    return;
  }
  if (frequency > 0 && frequency < 123) { //256 prescaler
    long count = 16000000 / 256 / frequency;
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);
    OCR1B = (count * dutyCycle) - 1;
    ICR1 = count - 1; 
    TCCR1A = _BV(COM1B1) | _BV(WGM11);
    return;
  }
  if (frequency > 122 && frequency < 3907) { //8 prescaler
    long count = 16000000 / 8 / frequency;
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11);
    OCR1B = (count * dutyCycle) - 1;
    ICR1 = count - 1;
    TCCR1A = _BV(COM1B1) | _BV(WGM11);
    return;
  }
  if (frequency > 3906 && frequency < 31250) { //no prescaler
    long count = 16000000 / 1 / frequency;
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
    OCR1B = (count * dutyCycle) - 1;
    ICR1 = count - 1; 
    TCCR1A = _BV(COM1B1) | _BV(WGM11);
    return;
  }
}

Pulling pin 2 low doubles the frequency, and pulling pin 3 low divides it by two. I find dividing it by two to 80.00 from 160.00 Hz seems to produce this problem quite reliably.

I've tried just having a loop that changes the frequency to some pre set values, but that does not seem to cause this issue.

I think that the TCNT1 is greater than the new value set for ICR1, and the counter continues to max before resetting. Try to stop the timer and reset TCNT1 when you adjust frequency. 160-> 80 should be in in this block

if (frequency > 0 && frequency < 123) { //256 prescaler
    TCCR1B = 0;//stopTimer
    TCNT1 = 0;//reset counter
    long count = 16000000 / 256 / frequency;
    //TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);
    OCR1B = (count * dutyCycle) - 1;
    ICR1 = count - 1; 
    TCCR1A = _BV(COM1B1) | _BV(WGM11);
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);
    return;
  }

Thank you! that finally fixed it.

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