trouble working a PWM tone generator

I’m trying to write a tone generator with some LED lighting using the PWM pins as my first Arduino project. I’ve got a pair of 8 to 1 muxes working and the lights match with the tones just fine, but the tone speeds for my playTone function keep coming out too short. I’ve been trying to debug this for a couple of hours now and I feel really retarded I can’t get it working yet. Anyone able to spot the error? I’m guessing it’s within the playTone function itself, but I’m not really positive.

int s1 = {7, 8, 9}; //select lines for first mux, the tone light selector
int s2 = {4, 5, 6}; //select lines for second mux, the rhythm light selector
int speakerOut1 = 11; //sets up first audio channel
int lightOut = 3; //sets up the LED channel

//int pulseWidth = {7644, 7215, 6810, 6428, 6067, 5726, 5405, 5102, 4815, 4545, 4290, 4049, 3822, 3607, 3405, 3214, 3033, 2863, 2702, 2551, 2407, 2272, 2145, 2024, 1911, 1803, 1702, 1607, 1516, 1431, 1351, 1275};
int pulseWidth = {3822, 3405, 3033, 2863, 2551, 2272, 2024, 1911};
int bincodes = {000, 1, 10, 11, 100, 101, 110, 111};

int tempo = 100; //tempo in BPM
long beat = (60 * 1000 * 1000)/tempo; //the length of one beat, in microseconds

void setup ()
{
for (int i = 0; i < 3; i++)
{
pinMode(s1*, OUTPUT);*
_ pinMode(s2*, OUTPUT);_
_
}_
_
pinMode(speakerOut1, OUTPUT);_
_
pinMode(lightOut, OUTPUT);_
_
}_
void lightsoff()
_
{_
_
digitalWrite(lightOut, LOW);_
_
}_
void playTone(int x, int t) //when passed an int, plays the tone corresponding to that number. tone values are stored
_
{ //in the pulseWidth array as pulse widths, not frequencies! 7644 = C3*_
long elapsed_time = 0;
long duration = beat / t; //duration of the desired note in microseconds
if (x >= 0)
* {*
* while (elapsed_time < duration)
_
{_
_
digitalWrite(speakerOut1, HIGH);_
_
delayMicroseconds(pulseWidth/2);_
_
digitalWrite(speakerOut1, LOW);_
_
delayMicroseconds(pulseWidth/2);_
elapsed_time += (pulseWidth);
_
}_
_
}_
_
}_
void toneOff() //silences the tone channel
_
{_
_
digitalWrite(speakerOut1, LOW); _
_
}_
void light(int x) //when passed a decimal value, lights the appropriate LED
_
{_
_
lightsoff();_
_
int y = bincodes;_
_
int a0 = y & 0x01;_
_
int a1 = (y >> 1) & 0x01;_
_
int a2 = (y >> 2) & 0x01;_
_
digitalWrite(s1[0], a0);_
_
digitalWrite(s2[0], a0);_
_
digitalWrite(s1[1], a1);_
_
digitalWrite(s2[1], a1);_
_
digitalWrite(s1[2], a2);_
_
digitalWrite(s2[2], a2);_
_
digitalWrite(lightOut, HIGH);_
_
}_
void loop()
_
{_
_
toneOff();_
_
lightsoff();_
_
for (int i = 0; i <= 7; i++)_
_
{_
_
light(i);_
_
playTone(i, 4); _
_
lightsoff();_
_
}_
_
delay (1000);_
_
}*_

oh and what I meant to include about playTone was that the variables passed should be in the form (int x, int t) representing the pitch and duration of the notes. I wanted it to be so that when t = 1 the note is a whole note, t = 4 means the note is a quarter note, etc. pitch 0 is C3 (at least so I think). i'm just going for the major scale tones right now since having things in 8's are so easy to work with (especially when you have 8 to 1 muxes).

A tip that may help you when you are at a loss to see what is going wrong is to use the Serial library functions to print the intermediate results of your calculations so you can visualize what is actually happening to the variables in your functions.

If you haven't used the serial library before, there's lots of info available including this beginners guide: http://www.ladyada.net/learn/arduino/lesson4.html

Printing the value of duration before the while loop in playTone and printing elapsed_time in the loop will help you verify if playTone is functioning as you want it. Do be aware that calls to serial will throw your timings off, so once you verify your logic is correct you need to remove the functions to get the real time durations correct.

This technique is something of a last resort, its usually more efficient to stop and think about what the program is doing rather then throwing in lots of print statements. But it can be a great help when you are really stuck.

Good luck with your debugging

That's exactly what I needed. Seems the initial "beat" value was going out of bounds and I was having negative durations :P. The initialization line for "beat" broke when I wrote it all out as a math formula. It fixed when I changed it to the following:

long beat = 60000000/tempo; //the length of one beat, in microseconds

I guess the Arduino's math operators aren't as flexible as I thought. Thanks for the help!

Glad you have it fixed.

The compiler does the cast to a long after it has done 16 bit math on 16 bit integers, which is why it was going negative.

You should also be able to fix it by telling the compiler you want to do 32 bit math, setting any one of the values to long should to the trick:
long beat = (60 * 1000 * 1000)/(long)tempo;