Hi, I need to generate a PWM signal at 141 Hz.
I've found this code on the web (Thanks Jeson Pepas), I really can't understand the part regarding the TCCR and OCR registers.
All is working fine except that I need to generate a TONE and when I output a tone the pwm stops working.
My question is:
How can I output a PWM signal at 141 Hz just using the PWM outputs without using the OCR and TCCR registers?
THANKS
here you are the code I'm using:
// by jason pepas (jasonpepas@gmail.com)
// released under the GPLv2.
// min and max duty cycles which the actuator will respond to.
#define DUTY_MIN 15
#define DUTY_MAX 98
uint8_t duty_cycle = DUTY_MIN;
// min and max periods which the actuator will respond to.
#define PERIOD_MIN 106
#define PERIOD_MAX 115
uint8_t period = 110;
void setup()
{
pinMode(3, OUTPUT); // OC2B
// we are using waveform generator mode "7", which is fast pwm with TOP = OCRA.
// see the atmega168 datasheet page 157, table 17-8.
//TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
// actually, I want "inverting" mode, because I am now driving an n-channel mosfet.
TCCR2A = _BV(COM2B1) | _BV(COM2B0) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS22) | _BV(CS21) | _BV(CS20);
OCR2A = period; // sets TOP (thus, frequency). 111 should be just over 140hz.
OCR2B = (uint8_t)(period * (duty_cycle / 100.0)); // sets duty cycle.
}
boolean walk_duty = true;
boolean duty_climbing = true;
boolean walk_period = false;
boolean period_climbing = false;
void loop()
{
if (walk_duty == true)
{
if (duty_cycle < DUTY_MIN) duty_cycle = DUTY_MIN;
if (duty_cycle > DUTY_MAX) duty_cycle = DUTY_MAX;
if (duty_cycle == DUTY_MAX)
{
duty_climbing = false;
}
if (duty_cycle == DUTY_MIN)
{
duty_climbing = true;
}
if (duty_climbing == true)
{
duty_cycle++;
}
else // (duty_climbing == false)
{
duty_cycle--;
}
OCR2A = period;
OCR2B = (uint8_t)(period * (duty_cycle / 100.0)); // sets duty cycle.
}
if (walk_period == true)
{
if (period < PERIOD_MIN) period = PERIOD_MIN;
if (period > PERIOD_MAX) period = PERIOD_MAX;
if (period == PERIOD_MAX)
{
period_climbing = false;
}
if (period == PERIOD_MIN)
{
period_climbing = true;
}
if (period_climbing == true)
{
period++;
}
else // (period_climbing == false)
{
period--;
}
OCR2A = period;
OCR2B = (uint8_t)(period * (duty_cycle / 100.0)); // sets duty cycle.
}
delay(20);
}