## Question about "differential drive" and piezo buzzer

computurwizard

Posts: 7
Joined: Sat Jun 23, 2012 11:18 am

### Question about "differential drive" and piezo buzzer

Under the description for the piezo buzzer, it says "For extra loudness, you can connect both pins to a microcontroller and swap which pin is high or low ('differential drive') for double the volume. "

Does that mean something like this would work?

TIA!

EDIT - Piezo can be found here: http://www.adafruit.com/products/160

Code: Select all

``````/*
Test of tone() using a simple piezo with a differential drive circuit
*/

const int piezopin1 = 7;
const int piezopin2 = 8;

// the setup routine runs once when you press reset:
void setup() {
pinMode(piezopin1, OUTPUT);
pinMode(piezopin2, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
tone(piezopin1, 2200);
digitalWrite(piezopin2, LOW);
delay(100);
noTone(piezopin1);
delay(100);
// Now swap pins
tone(piezopin2, 2200);
digitalWrite(piezopin1, LOW);
delay(100);
noTone(piezopin2);
delay(100);
}``````

mtbf0

Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

### Re: Question about "differential drive" and piezo buzzer

don't think that would work. the approach would involve connecting the two leads of the piezo buzzer to the two output compare pins of one of the arduino timers, setting one pin high and the other low then having them both toggle when the timer overflows. this is kind of a low level approach and not very arduinish. i think you can have a look at the code for the icetube kit for an example. as long as you don't use timer0 you can use this method on an arduino. it does require the use of two pwm pins, either 9 & 10 or 3 & 11.

Posts: 67339
Joined: Thu Feb 11, 2010 2:51 pm

### Re: Question about "differential drive" and piezo buzzer

Differential drive does mean "left-high-right-low / left-low-right-high". The idea is that you get twice the effective voltage swing.

If your output voltage is 5v, you start with the left pin at 5v and the right one at 0v. Then you go to the left pin being 0v and the right pin being 5v. For the first step, the left pin is 5v higher than the right pin. For the second, it's 5v lower. It's electrically equivalent to keeping the right pin at 0v and having the left pin swing from 5v to -5v.. a total swing of 10v.

Rather than hooking the piezo to the timer, you can bit-bang your tones with the delayMicroseconds() command:

Code: Select all

``````void diffDriveTone (period, duration) {
char phase = 0;
int i;

for (i=0 ; i < duration ; i+=period) {
digitalWrite( leftPin, phase & 1 );
phase++;
digitalWrite( rightPin, phase & 1 );
delayMicroseconds( period );
}
}

diffDriveTone( 2272, 1000000 );    // play 1sec of 440Hz A

``````
I can't make any promises about the musicality of it, but that's the general idea.

mtbf0

Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

### Re: Question about "differential drive" and piezo buzzer

using a timer allows for a non-blocking version. this one gives a tone near 500Hz using d5 and d6.

Code: Select all

``````void start_buzzer (void) {
DDRD |=  0x60;      // make sure pins 5 and 6 are outputs
PORTD  = (PORTD & ~0x60) | 0x40;  // pin 6 high, pin 5 low
TCCR0A  = (TCCR0A & 0x0f) | 0x50;  // pins 5 & 6 toggle on compare match
}

void stop_buzzer (void) {
TCCR0A &= 0x0f;  // stop toggle on compare match
}``````
yes, you must use pins 5 and 6. no, you can't change the frequency of the tone. this is the dead simplest approach, since it uses timer0 which is already running on an arduino. versions using timer1 or timer2 could offer a variable frequency.

EDIT: won't work on a mega or leonardo or anything not based on an atmegax8.

code is untested. gotta go to work.

Posts: 67339
Joined: Thu Feb 11, 2010 2:51 pm

### Re: Question about "differential drive" and piezo buzzer

Ooh.. nice code.

http://arduino.cc/en/Reference/DelayMicroseconds

mtbf0

Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

### Re: Question about "differential drive" and piezo buzzer

Code: Select all

``````#define LO 0
#define HI 1

void start_buzzer (int volume) {
DDRD |=  0x60;                       // make sure pins 5 and 6 are outputs
PORTD  = (PORTD & ~0x60) | 0x40;     // pin 6 high, pin 5 low
if (volume == HI)
TCCR0A  = (TCCR0A & 0x0f) | 0x50;  // pins 5 & 6 toggle on compare match
else
TCCR0A  = (TCCR0A & 0x0f) | 0x10;  // pin 6 toggles on compare match
}

void stop_buzzer (void) {
TCCR0A &= 0x0f;                      // stop toggle on compare match
}``````