Ability to output PWM at two different frequencies/duty cycles at the same time

I am very new to this forum and this is my first post. I apologize in advance if I am posting in the incorrect area.

My project consists of operating two different devices at the same time that each require different frequencies and duty cycles. I am using Arduino Uno and Nano. There was a very helpful library called TimerOne of which I am trying to make use of. I can get my devices to work as they should independently but when I try to operate both devices at the same time, the setting of one frequency is overriding the prior device frequency. I do understand that the pins I am using in the sample below are sharing the same timer and therefore will be using the same frequency settings. I have tried using pin 6 or 11 as well so that I am using a different timer but to no avail.

I’ve searched many threads but have not found reference to what I am trying to do. Is it possible? Any thoughts would be greatly appreciated.

#include <TimerOne.h>

const int pulsePin = 9;
const int fanPin = 10;
int inputDutyCycle = 0;
unsigned long period;            //microseconds
bool highHeat = true;

void setup(void)
{
 Serial.begin(9600);
 setFan(60, 5);                //Initialize fan
 delay(5000);
}

void loop(void)
{
 if (highHeat == true)
 {
   setHeat(16, 50);            //16Hz @ 50% duty cycle for high heat
   setFan(60, 8);              //60Hz @ 8% duty cycle for high fan
 }
 else
 {
   setHeat(7, 10);             //7Hz @ 10% duty cycle for idle
   setFan(60, 7);              //60Hz @ 7% duty cycle for idle
 }
 delay(5000);                  // pause 5 seconds to see change from high to idle  
 highHeat = !highHeat;         // toggle between high heat and idle
}

void setHeat(int heatFreqHz, int heatPercentDutyCycle)
{
 period = 1000000/heatFreqHz;
 Timer1.initialize(period);
 inputDutyCycle = map(heatPercentDutyCycle, 0, 100, 0, 1023);   // map percentage to range of 0 - 1023
 Timer1.pwm(pulsePin, inputDutyCycle);                          //Duty cycle is a value between 0 1023
 Serial.print("HEAT Period is 1000000/");
 Serial.print(heatFreqHz);
 Serial.print("Hz = ");
 Serial.print(period);
 Serial.print(" Duty cycle of ");
 Serial.print(heatPercentDutyCycle);
 Serial.print("% - ");
 Serial.println(inputDutyCycle);
}

void setFan(int fanFreqHz, int fanPercentDutyCycle)
{
 period = 1000000/fanFreqHz;
 Timer1.initialize(period);
 inputDutyCycle = map(fanPercentDutyCycle, 0, 100, 0, 1023);   // map percentage to range of 0 - 1023
 Timer1.pwm(fanPin, inputDutyCycle);                           //Duty cycle is a value between 0 1023
 Serial.print("FAN - Period is 1000000/");
 Serial.print(fanFreqHz);
 Serial.print("Hz = ");
 Serial.print(period);
 Serial.print(" Duty cycle of ");
 Serial.print(fanPercentDutyCycle);
 Serial.print("% - ");
 Serial.println(inputDutyCycle);
}

I have been able to accomplish what I need to do by using two nano's and keeping in sync by setting a pin to HIGH when in the high cycle and the other nano reading that pin to keep the other side in sync. I would really like to accomplish this on one board though.

Smilies in your post are why you should use code tags... Please go edit and fix your post. And if you don't know how... do go and read the sticky which you should have done already.

That would also told you other things we need, for starters an explanation of what this code does and how it's different from what you want it to do.

One issue I see skimming that code is that you're trying to initialise TimerOne to two different periods. That won't work.

You can definitely do this with timer interrupts using just Timer1, but I don't know if that library supports it. There are two timer overflow interrupts available, one of each for each frequency. You'll have to do some calculations with the prescaler to get to reasonable numbers. At 1/256 you have a 16 µs resolution, should be a good starting point. You'd be setting the timer overflows every time to the current value + the time (number of counts) until the next change (so keep track of whether it's a high or low part of the cycle). I'm doing something very similar with my AC control library (phase cutting - based on peak detection rather than zero crossing; when you understand how that one works you will be able to quite easily adapt it for your use).

Your low frequencies also make it possible to use the micros() or even the millis() counters, so without the use of that timer library, as long as you also get rid of the delay() calls and be careful about the printing.

You can use two timers (T1 and T2), each for a specific frequency.

Thank you Shannon. I have added code tags to make my post easier to read. Your comments regarding my post etiquette is greatly appreciated. I'm learning...

I do understand that I cannot change the frequency in for two distinct pins using one timer. That is exactly the problem I was running into.

Your comments regarding timer interrupts hit the nail on the head. After doing further research, that is exactly what I need to do. Your example code is greatly appreciated as well. I'll be using timer 1 and timer 2 as suggested above.

Your guidance has been greatly appreciated.

Mind that timer2 is 8-bit and timer1 is 16-bit. So you have to treat them differently - less resolution possible with timer2.

Thank you wvmarle. Just realized I called you Shannon in the prior post. I appreciate your input.

No worries :slight_smile:

efleming:
I do understand that I cannot change the frequency in for two distinct pins using one timer. That is exactly the problem I was running into.

As I said in #2 in fact you CAN do this - but it's not simple, and you'll have to get down and dirty with processor registers.