11 years, 9 months ago.

How do I control two different loudspeakers with two separate pwm ports?

I'm trying to get one speaker to play the melody of a song and another speaker to play the bass of a song. I've managed to get the melody itself to work well but when I add in another loudspeaker I encounter a couple of problems.

The first one is; when using my function to play a note I need to use a wait for the duration of the note. I don't know how to make the program do something else while it is also waiting, ie, I can't make the melody speaker play a tune over the top of a single bass note due to the program waiting for the bass note to finish.

This means I am unable to set a duration for one speaker in the function so I have to jiggle the durations around, leaving the bass on (setting the frequency to a note) then leaving it while I play the melody until I need to change the bass note or turn the bass off.

While doing this, I encountered the second problem. I believe it's do with how pwm actually works. If I have something like this:

#include "mbed.h"
PwmOut loudspeaker1(p21);
PwmOut loudspeaker2(p22);

int main(){
loudspeaker1.period(1/523.25); //note c 
loudspeaker1 = 0.5;
wait(2);
loudspeaker1.period(1/587.33); //note d
loudspeaker1=0.5;
loudspeaker2.period(1/329.63); //low note e
loudspeaker2 = 0.5;
wait(2);
loudspeaker1 = 0;
loudspeaker2 = 0;
}

This should make loudspeaker1 a note c for 2 seconds then it should change to a note d while the loudspeaker2 goes to a low note e. This doesn't happen, instead loudspeaker1 is forced to go to a low note e at the same time loudspeaker2 goes to a low note e. They should then turn off after 2 seconds, which they do.

Why does this happen and how can I fix it?

Any help would be much appreciated, thanks.

2 Answers

11 years, 9 months ago.

Unfortunately all Pwm channels are linked to the same period so you cant do what you want to do.

if you want to use 1 channel asynchronously you will have to use a Timer, (interrupts could also work) something like this:

float channel1[5][2] = {{2, 1/523.25}, {/*add more notes n delays*/}};

Timer timer1;

int main(){
  timer1.start();
  int note1 = 0;

  loudspeaker1.period(channel1[note1][1]); //note d
  loudspeaker1 = 0.5;

  while(1){
    if(timer1.read() > channel1[note1][0]){
      timer1.reset();
      note1++;
      loudspeaker1.period(channel1[note1][1]); //note c 
    }
  }
}

Its just an example, I haven't ran or tested, and you need more variables to check how many notes there are ect, but hopefully you can get some ideas from it.

Accepted Answer

It is unfortunate that i can't get the two loudspeakers to play at different frequencies using the pwm channels although I believe you have solved the issue of using the waits so thank you.

posted by Daniel Bee 14 Mar 2013
11 years, 9 months ago.

In this PWM course is an example how to play a melody: http://mbed.org/media/uploads/robt/mbed_course_notes_-_pulse_width_modulation.pdf

I didn't have a problem playing a single melody, the problem was that I couldn't play two separate melodies with two pwm channels. The link did give me some insight on how to use the array for all my notes though, so thanks.

posted by Daniel Bee 14 Mar 2013