I am making a device that the main function is to output a PWM signal that is variable in range of 20-120Hz and duty cycle variable between 0-100%. I have a lot of other things going on in the program and cannot put it in my main loop function because it will be interrupted by other events. So my idea is to have the flashing in a timer interrupt. I can get it working when I just toggle the output, but when I try to incorporate the duty cycle it gets weird and out of sync. Does anyone have any ideas on how I could fix this?
Here is what I am doing right now, but I very well may be doing this completely wrong.
#define output 13
int frequency = 30;
double duty = 0.9;
volatile boolean state = LOW;
double onFreq, offFreq;
void setup()
{
pinMode(output, OUTPUT);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
calcFreqs();
TCNT1 = timer(onFreq); // preload timer 65536-16MHz/256/Frequency
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
}
ISR(TIMER1_OVF_vect)
{
if(state == HIGH)
TCNT1 = timer(offFreq);
else
TCNT1 = timer(onFreq);
digitalWrite(output, digitalRead(output)^1);
state = !state;
}
long int timer(double frequency)
{
return 65536-(16000000L/(256*frequency));
}
void calcFreqs()
{
onFreq = frequency*duty;
offFreq = frequency-onFreq;
}
void loop()
{
calcFreqs();
if(frequency == 120)
frequency = 20;
else
frequency++;
delay(500);
}