Real Speaker (not Piezo)

Thanks, Osgeld!

I decided to try using multiple Arduino pins to direct more current through the speaker. Since it didn't need any more parts, I was able to implement this idea quickly (and without spending another $10 on an unpowered 1.5W speaker).

With four pins on each side high/low (eight total), it seems to work. Of course, it uses up a lot of pins, and the volume still isn't great (0.2 W max out of 1.5 W possible for the speaker), but it was really easy.

I see how to use a capacitor and either four SCRs or four transistors to get the same power with just three Arduino pins. But I don't have the parts right now.

For the benefit of anybody else looking for easy ways to get decent (not great) volume out of an Arduino with a small speaker and minimal extra parts, I'll sketch out my calculations and some code below.

  • A single pin is limited to 40 mA current on the Arduino. Groups of pins are also limited, but importantly the ground pin itself is limited to 200 mA current. So that's basically the upper bound.

  • With a single pin and 40 mA current through an 8 Ohm speaker, the power into the speaker is P = I^2 R ~= 0.013 W. To get this current, a resistor with value (5 V / 0.04 A) - 8 Ohms = 117 Ohms is needed in series with the speaker.

  • With four pins and 160 mA current through the same speaker, the power is 0.20 W --- still well below the max of 1.5 W, but 16 times more than before. A 23.25 Ohm resistor is needed.

  • The circuit connects pins 3,4,5,6 to each other, and pins 8,9,10,11 to each other. To avoid any short circuits, it is important to switch every pin in the group simultaneously---so you can't use digitalWrite() one pin at a time. Here is some sample code:

Initialization:
PORTB |= B1111; // PORTB references pins 8 through 13, B1111 represents 1111 in binary, thus this command turns on pins 8,9,10,11

Basic loop:
PORTB ^= B1111; // toggle the state of pins 8-13
PORTD ^= B111100; // PORTD references pins 0 through 7 (0 and 1 are for TX and RX, so I start with 2)
delayMicroseconds(1500);

By alternating between having 8-11 HIGH, 3-6 LOW; and 8-11 LOW, 3-6 HIGH, this code generates square waves. (It is important to alternate back and forth for volume, so the speaker is pushed in both directions.)

Using 5 pins would in theory increase the power another 50%, while pushing the Arduino's current to its absolute maximum. The appropriate resistance to add is 17 Ohms. But I ran out of low-value resistors, and couldn't get the effective resistance any lower than 23 Ohms.