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); }