January 28, 2014
by lailai
|
Hi all,
I'm attempting to play sound (with the piezo buzzer) using the nerdkit. I wanted to play more than one tone at a time, so I used two timers set to interrupt. Each timer manages one pin, both pins are then hooked to a resistor and finally the piezo buzzer.
It works quite well, however there are shuttering present. It always shutters at the same time. The shuttering still happens without LCD updates, but at different times. If I change a little bit, the times when shuttering happens changes again.
Here is my code (with some parts like defining notes to frequencies stripped out):
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#define F_CPU 14745600
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#define DUR 25
#define A5 568
#define B5 506
#define S(s) lcd_write_string(PSTR(s));
void setup_timers (void) {
sei(); // Enable global interrupts
TCCR0A |= (1 << WGM01); // Configure timer 0 for CTC mode
TIMSK0 |= (1 << OCIE0A); // Enable CTC interrupt
TCCR0B &= 0; // disable clock
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
TCCR1B &= 0; // disable clock
}
void play_tone(uint16_t delay, uint16_t delay2, uint16_t duration) {
if(delay != 0){
OCR0A = delay / 4.31;
TCCR0B |= ((1 << CS01) | (1 << CS00));
}
if(delay2 != 0){
OCR1A = delay2 / 4.31;
TCCR1B |= ((1 << CS11) | (1 << CS10) | (1 << WGM12));
}
delay_ms(duration*10);
TCCR0B &= 0;
TCCR1B &= 0;
}
int main (void) {
DDRC |= (1 << PC4); // Set Piezo1 as output
DDRC |= (1 << PC5); // Set Piezo2 as output
setup_timers();
lcd_init();
lcd_clear_and_home();
S("This "); play_tone(G6, 0, DUR);
S("was "); play_tone(F6, 0, DUR);
S("a "); play_tone(E6, 0, DUR);
S("tri"); play_tone(E6, 0, DUR);
S("umph."); play_tone(F6, A4, DUR);
play_tone(0, D4, DUR);
play_tone(0, F4, DUR);
play_tone(0, D4, DUR);
play_tone(0, B4, DUR);
play_tone(0, D4, DUR);
play_tone(0, F4, DUR);
play_tone(0, D4, DUR);
play_tone(0, A4, DUR);
play_tone(0, D4, DUR);
play_tone(0, F4, DUR);
lcd_line_two(); S("I'm "); play_tone(0, D4, DUR);
S("mak"); play_tone(G6, B4, DUR);
S("ing "); play_tone(F6, D4, DUR);
S("a "); play_tone(E6, F4, DUR);
S("note "); play_tone(E6, D4, DUR);
lcd_line_three(); S("here, "); play_tone(E6, A4, DUR);
play_tone(F6, D4, DUR);
play_tone(0, F4, DUR);
play_tone(0, D4, DUR);
S("HUGE "); play_tone(D6, B4, DUR);
play_tone(0, D4, DUR);
S("SUC"); play_tone(E6, F4, DUR);
S("CESS. "); play_tone(A6, D4, DUR);
// etc etc etc
while(1){
}
}
ISR(TIMER0_COMPA_vect) {
PORTC ^= (1 << PC5); // Toggle the buzzer
}
ISR(TIMER1_COMPA_vect) {
PORTC ^= (1 << PC4); // Toggle the buzzer
}
Can I fix the shuttering? (maybe 0.1 to 0.15 seconds) Or is it interrupt clashes like I suspect?
NOTE: It happens without any LCD updates.
Thanks! |