Skip to content

Instantly share code, notes, and snippets.

@sciguy14
Created September 25, 2016 11:55
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save sciguy14/549aef385414c381ceb9c49d85be3367 to your computer and use it in GitHub Desktop.
Using Interrupts to Drive Multiple Speakers Simultaneously from an Arduino
//** Arduino - Drive Multiple Speakers with Interrupts **//
//** http://www.jeremyblum.com/2010/09/05/driving-5-speakers-simultaneously-with-an-arduino/ **//
/* Timer reload value, globally available */
unsigned int tcnt2;
/* Toggle HIGH or LOW digital write */
int toggle1 = 0;
int toggle2 = 0;
int toggle3 = 0;
int toggle4 = 0;
int toggle5 = 0;
/* Keep track of when each note needs to be switched */
int count1 = 0;
int count2 = 0;
int count3 = 0;
int count4 = 0;
int count5 = 0;
/* Frequency Output Pins */
#define FREQ1 9
#define FREQ2 10
#define FREQ3 11
#define FREQ4 12
#define FREQ5 13
//Setup Function will run once at initialization
void setup()
{
/* First disable the timer overflow interrupt*/
TIMSK2 &= ~(1<<TOIE2);
/* Configure timer2 in normal mode (no PWM) */
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
/* Select clock source: internal I/O clock */
ASSR &= ~(1<<AS2);
/* Disable Compare Match A interrupt (only overflow) */
TIMSK2 &= ~(1<<OCIE2A);
/* Configure the prescaler to CPU clock divided by 128 */
TCCR2B |= (1<<CS22) | (1<<CS20); // Set bits
TCCR2B &= ~(1<<CS21); // Clear bit
/* We need to calculate a proper value to load the counter.
* The following loads the value 248 into the Timer 2 counter
* The math behind this is:
* (Desired period) = 64us.
* (CPU frequency) / (prescaler value) = 125000 Hz -> 8us.
* (desired period) / 8us = 8.
* MAX(uint8) - 8 = 248;
*/
/* Save value globally for later reload in ISR */
tcnt2 = 248;
/* Finally load end enable the timer */
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
//Configure I/O Pin Directions
pinMode(FREQ1, OUTPUT);
pinMode(FREQ2, OUTPUT);
pinMode(FREQ3, OUTPUT);
pinMode(FREQ4, OUTPUT);
pinMode(FREQ5, OUTPUT);
}
/* Install the Interrupt Service Routine (ISR) for Timer2. */
ISR(TIMER2_OVF_vect)
{
/* Reload the timer */
TCNT2 = tcnt2;
count1++; count2++; count3++; count4++; count5++;
if (count1 == 60)
{
digitalWrite(FREQ1, toggle1 == 0 ? HIGH : LOW);
toggle1 = ~toggle1;
count1 = 0;
}
if (count2 == 53)
{
digitalWrite(FREQ2, toggle2 == 0 ? HIGH : LOW);
toggle2 = ~toggle2;
count2 = 0;
}
if (count3 == 47)
{
digitalWrite(FREQ3, toggle3 == 0 ? HIGH : LOW);
toggle3 = ~toggle3;
count3 = 0;
}
if (count4 == 40)
{
digitalWrite(FREQ4, toggle4 == 0 ? HIGH : LOW);
toggle4 = ~toggle4;
count4 = 0;
}
if (count5 == 35)
{
digitalWrite(FREQ5, toggle5 == 0 ? HIGH : LOW);
toggle5 = ~toggle5;
count5 = 0;
}
}
void loop()
{
//Do whatever else you want to do with your arduino!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment