bobcousins:
As promised here is a sketch using timers for PWM, with different frequencies. You can have 4 different frequencies, because there are 4 timer channels used. Each timer channel can have two outputs, A and B, each with their own duty cycles.
There are a total of 9 timer channels, so in theory you could have 9 different frequencies, but not all the output pins may be mapped in convenient locations, or at all. You would also need to do all the setup code yourself, as they are not handled by analogWrite, or possibly edit variant.cpp.
// --------------------------------------------
//
// PWM with timers demo
//
// Bob Cousins, August 2014
// --------------------------------------------
typedef struct {
Tc *pTC; // TC0, TC1, or TC2
byte channel; // 0-2
byte output; // 0 = A, 1 = B
} tTimerInfo;
tTimerInfo timerLookup [] =
{
{NULL,0,0}, // 0
{NULL,0,0},
{TC0,0,0}, // pin 2 = TIOA0
{TC2,1,0}, // pin 3 = TIOA7
{TC2,0,1}, // pin 4 = TIOB6
{TC2,0,0}, // pin 5 = TIOA6
{NULL,0,0},
{NULL,0,0},
{NULL,0,0},
{NULL,0,0},
{TC2,1,1}, // pin 10 = TIOB7
{TC2,2,0}, // pin 11 = TIOA8
{TC2,2,1}, // pin 12 = TIOB8
{TC0,0,1} // pin 13 = TIOB0
};
/**
- \brief set a pin for PWM using a timer channel
- \param pin pin to use (0-13 only!)
- \param frequency the frequency
- \param dutyCyle duty cycle 0-255
- \return this function returns a count, which is the effective PWM resolution. Returns 0 if pin is not valid
*/
uint32_t setupTimerPwm (byte pin, uint32_t frequency, unsigned dutyCycle)
{
uint32_t count = VARIANT_MCK/2/frequency;
tTimerInfo *pTimer = &timerLookup[pin];
if (pTimer != NULL)
{
TC_SetRC (pTimer->pTC, pTimer->channel, count);
if (pTimer->output == 0)
TC_SetRA (pTimer->pTC, pTimer->channel, count * dutyCycle / 256);
else
TC_SetRB (pTimer->pTC, pTimer->channel, count * dutyCycle / 256);
return count;
}
else
return 0;
}
void setup() {
// put your setup code here, to run once:
// use the Arduino lib to do initial setup
analogWrite (2, 128);
analogWrite (13, 128);
analogWrite (5, 128);
analogWrite (4, 128);
analogWrite (3, 128);
analogWrite (10, 128);
analogWrite (11, 128);
analogWrite (12, 128);
// pins 2 and 3 share the same timer so must have same frequency
setupTimerPwm (2, 2000, 128);
setupTimerPwm (13, 2000, 64);
// pins 5 and 4 share the same timer
setupTimerPwm (5, 3000, 128);
setupTimerPwm (4, 3000, 64);
// pins 3 and 10 share the same timer
setupTimerPwm (3, 4000, 128);
setupTimerPwm (10, 4000, 64);
// pins 11 and 12 share the same timer
setupTimerPwm (11, 5000, 128);
setupTimerPwm (12, 5000, 64);
}
void loop() {
// put your main code here, to run repeatedly:
}
Scope traces, showing pins 2, 5, 3 and 11 respectively (these are the 'A' outputs) :
[](https://flic.kr/p/owM6rm)[demo2](https://flic.kr/p/owM6rm) by [donotdespisethesnake](https://www.flickr.com/people//), on Flickr
If you find the advice "read the source code" offensive, I'm sorry, but please don't send me PMs to complain. It really is Good Advice [Learn to Read the Source, Luke!](http://blog.codinghorror.com/learn-to-read-the-source-luke/). If you don't want to read source code, consider a different hobby/profession!
And if you are using Arduino, you already have it's source code on your computer, so don't say you don't have it. It is really worth studying if you want to learn how it works.
Especially made an account to thank you! 