Go Down

Topic: Arduino 8ohm Small Piezo Speaker: Can you play two Tones at once? Like chords? (Read 4 times) previous topic - next topic

hooj

Arduino 8ohm Small Piezo Speaker: Can you play two Tones at once? Like chords?

Is it possible to do this with just one speaker?

Grumpy_Mike

Quote
Is it possible to do this with just one speaker?

Yes, you can have many ones from one speaker look at this project of mine:-
http://vimeo.com/38466551

johnwasser

This third-party Tone library can play simultaneous square waves on multiple pins:

http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation

You can connect resistors between the multiple pins and a single speaker to get all tones out of one speaker.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Nick Gammon


Yes, you can have many ones from one speaker look at this project of mine:-


Well, Mike, you can tell you are an engineer. That box looks fantastic. My projects on the other hand look a complete mess. :)
http://www.gammon.com.au/electronics

steinie44

@johnwasser, I have looked at this site several times and I can not find anything about playing simultaneous tones. Where is it?
Do you think it will play DTMF tones?

johnwasser

On the ATmega328 there are two spare timers so you should be able to play DTMF.

Code: [Select]

/*
1209 Hz 1336 Hz 1477 Hz 1633 Hz
697 Hz 1 2 3 A
770 Hz 4 5 6 B
852 Hz 7 8 9 C
941 Hz * 0 # D
*/
#include <Tone.h>

Tone RowTone, ColumnTone;
const int RowTonePin = 13;
const int ColumnTonePin = 12;
const int ToneDuration = 100;  //  Play each tone 100 mSec.

void setup() {
  RowTone.begin(RowTonePin);
  ColumnTone.begin(ColumnTonePin);
}

void loop() {
    DTMF("8675309");
   delay(1000);
}

void DTMF(char * keys) {
    char key;
    while (key = *keys++) {
         switch (key) {
         case '0':
               RowTone.play(941, ToneDuration);
               ColumnTone.play(1336, ToneDuration);
                break;

         case '1':
               RowTone.play(697, ToneDuration);
               ColumnTone.play(1209, ToneDuration);
                break;

         case '2':
.
.
.
       } // end switch
       while (RowTone.playing() || ColumnTone.playing()) {
            // Do Nothing
       }
   } // end while
}
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

CrossRoads

You can also use blink without delay style code to output multiple tones on multiple pins that you mix externally. Look at my post "piano tones micros" for code & schematic.
http://forum.arduino.cc/index.php?topic=179761.0
Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

steinie44

Lots of compile errors
Arduino: 1.5.5-r2 (Windows 8), Board: "Arduino Uno"

C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp: In member function 'void Tone::begin(uint8_t)':
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:121: error: 'bitWrite' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:123: error: 'digitalPinToPort' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:123: error: 'portOutputRegister' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:124: error: 'digitalPinToBitMask' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp: In member function 'void Tone::play(uint16_t, uint32_t)':
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:198: error: 'OUTPUT' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:198: error: 'pinMode' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:294: error: 'bitWrite' was not declared in this scope
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp: In member function 'void Tone::stop()':
C:\Users\Jim\Documents\Arduino\libraries\Tone\Tone.cpp:361: error: 'digitalWrite' was not declared in this scope

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
tried
#include"Arduino.h"

installed library using Sketch, Import Library, Add Library
closed IDE and opened it again.

Am I missing something?


johnwasser

Arduino 1.5.x is for the Arduino DUE.  If you are using an Arduino UNO you should be using Arduino 1.0.5.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

steinie44

I got it working now. Also made my own sketch for two tones using blink without delay routine. Got a wave file of a phone number off the internet. When I play the wave file into the phone mic it will dial the number. The tone examples will not dial. They need to be sine waves to work. Looking for a down and dirty way to convert square to sine wave. Any ideas?


dshores16

steinie44, I am getting similar compile errors as you. What did you do to get it to work? I am using an arduino Uno and Arduino 1.0.5 on windows 7

dshores16

I found someone that uses the built in libraries with some crazy timer manipulation to get the job done.
http://www.jeremyblum.com/2010/09/05/driving-5-speakers-simultaneously-with-an-arduino/

below is the code changed to just play two tones, though I'm sure someone else could manipulate it better. Let me know if you do!

Code: [Select]
//** ReacXion Source Code **//
//** www.jeremyblum.com **//

/* Timer reload value, globally available */
unsigned int tcnt2;

/* Toggle HIGH or LOW digital write */
int toggle1 = 0;
int toggle2 = 0;


/* Keep track of when each note needs to be switched */
int count1 = 0;
int count2 = 0;


/* Frequency Output Pins */
#define FREQ1 9
#define FREQ2 10


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


}

/* Install the Interrupt Service Routine (ISR) for Timer2.  */
ISR(TIMER2_OVF_vect) {
/* Reload the timer */
TCNT2 = tcnt2;

count1++; count2++;

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

void loop()
{
//Do whatever else you want to do with your arduino!
}

steinie44

@dshores16 I changed the Tone.cpp library with Wordpad. The <-------------------- show the two lines changed.

Code: [Select]

*************************************************/

#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <Arduino.h>  //  <wiring.h> <-----------------------------------------
// #include <pins_arduino.h> <---------------------------------------------
#include "Tone.h"

#if defined(__AVR_ATmega8__)
#define TCCR2A TCCR2
#define TCCR2B TCCR2
#define COM2A1 COM21
#define COM2A0 COM20
#define OCR2A OCR2
#define TIMSK2 TIMSK
#define OCIE2A OCIE2
#define TIMER2_COMPA_vect TIMER2_COMP_vect
#define TIMSK1 TIMSK
#endif


Go Up