Pages: [1] 2 3 4   Go Down
Author Topic: toneAC v1.2 - Twice the volume, higher quality, higher frequency, etc.  (Read 13867 times)
0 Members and 1 Guest are viewing this topic.
Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

toneAC Library Project Homepage

Advantages over the standard tone library:
  • Nearly twice the volume (because it uses two out of phase pins in push/pull fashion)
  • Higher quality (less clicking)
  • Capability of producing higher frequencies (even if running at a lower clock speed)
  • Nearly 1.5k smaller compiled code
  • Bug fixes (standard tone library can generate some odd and unpredictable results)
  • Can set not only the frequency but also the sound volume
  • Less stress on the speaker so it will last longer and sound better

Download:
toneAC v1.2

New in v1.2:
Fixed a counter error which went "over the top" and caused periods of silence (thanks Krodal). For advanced users needing tight code, the TONEAC_TINY switch in toneAC.h activates a version of toneAC() that saves 110 bytes. With TONEAC_TINY, the syntax is toneAC(frequency, length) while playing the note at full volume forever in the background. Added support for the ATmega 640, 644, 1281, 1284P and 2561 microcontrollers.

Connection:
Connection is very similar to a piezo or standard speaker.  Except, instead of connecting one speaker wire to ground you connect both speaker wires to Arduino pins.  The pins you connect to are specific, as toneAC lets the ATmega microcontroller do all the pin timing and switching.  This is important due to the high switching speed possible with toneAC and to make sure the pins are alyways perfectly out of phase with each other (push/pull).  See the below list for which pins to use for different Arduinos.  Just as usual when connecting a speaker, make sure you add an inline 100 ohm resistor between one of the pins and the speaker wire.
  • Pins  9 & 10 - ATmega328, ATmega128, ATmega640, ATmega8, Uno, Leonardo, etc.
  • Pins 11 & 12 - ATmega2560/2561, ATmega1280/1281, Mega
  • Pins 12 & 13 - ATmega1284P, ATmega644
  • Pins 14 & 15 - Teensy 2.0
  • Pins 25 & 26 - Teensy++ 2.0

Example sketch:
Code: (Example toneAC sketch)
#include <toneAC.h>

void setup() {} // Nothing to setup, just start playing!

void loop() {
  for (unsigned long freq = 125; freq <= 15000; freq += 10) {  
    toneAC(freq); // Play the frequency (125 Hz to 15 kHz in 10 Hz steps).
    delay(1);     // Wait 1 ms so you can hear it.
  }
  toneAC(); // Turn off toneAC, can also use noToneAC().

  while(1); // Stop (so it doesn't repeat forever driving you crazy--you're welcome).
}

Version History:
01/16/2013 v1.1 - Option to play notes in background, returning control back to your sketch for processing while note plays (similar to the way the tone library works). Volume is now linear and in the range from 0-10. Now uses prescaler 256 instead of 64 for frequencies below 123 Hz so it can go down to 1 Hz no matter what speed the CPU is clocked at (helpful if using toneAC to control a two-pin dual LED).
01/11/2013 v1.0 - Initial release.

Enjoy!

Tim
« Last Edit: January 27, 2013, 03:51:00 pm by teckel » Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Disadvantages of using toneAC compared to the standard tone library:

  • You must use certain pins (9 & 10 on Uno, 11 & 12 on Mega).
  • Uses two pins instead of one.
  • Tone duration doesn't run as an interrupt, just a simple delay(). This actually may be an advantage to some for simplicity sake.

But, if you're flexible with your pin choices, this is a great upgrade. It also uses timer 1 instead of timer 2, which may free up a conflict you have with the tone library. It also exclusively uses port registers for the fastest and smallest code possible.

Tim
Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very cool keep up the good work!
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Montreal
Offline Offline
Faraday Member
**
Karma: 27
Posts: 2572
Per aspera ad astra.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I 'd be cautious to drive high capacitance load like piezo w/o current limiting resistors. Though volume 'd be limited back to 1 pin level.
 Don't want to discourage an author, just something to think about, may be put some kind of warning in library header, that reliability of IC could be affected. .
Logged

Connecticut, USA
Offline Offline
Full Member
***
Karma: 8
Posts: 180
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is great thanks alot for sharing.
**Also using your New Ping library, thanks for that too.  smiley-cool
Logged

It's all about the skills

Greenville, IL
Offline Offline
Edison Member
*
Karma: 15
Posts: 1328
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


  Another good library idea teckel! Your Karma points are way lower than your efforts should show!
Logged


Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Piezo elements are like capacitors, that is a problem for higher frequencies. For ultrasonic sound it is even very bad to use a square wave, because of the peak currents. So there should be a resistor of 220 ohm (or 100 ohm ?) to protect the outputs of the Arduino. Please add a warning about that to your library.

Tested with normal 8 ohm speaker with extra 120 ohm resistor:
- Arduino Uno, pin 9,10 : good.
- Arduino Mega 2560, pin 11,12 : good
- Arduino Leonardo, pin 9,10 : good
- ATmega8 16MHz, pin 9,10 : good

My conclusion:
- No nasty click at start and stop : Excellent. A very small click can be heard.
- Extra loud : Good
- Small, fast code : Excellent
- Flexibility : Not so good, fixed pins.
- Volume control : Good, I needed that. Working roughly, not a linear scale.
- Frequency range : The lowest frequency is not low enough for a slow blinking two-pin dual led.

If I select a ultrasonic frequency, I don't hear it, but a very small click can be heard when the sound is started and stopped.
Perhaps setting the pins floating (set as inputs) if not used could reduce that. But that will make the code larger.
The normal Arduino tone() library doesn't work for all frequencies with the ATmega8. I didn't test that for your toneAC library very well, but it sounds okay.

Its a very good library. Thank you.

PS: Do you know the Mozzi library ? http://sensorium.github.com/Mozzi/
« Last Edit: January 12, 2013, 08:57:11 pm by Krodal » Logged

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I 'd be cautious to drive high capacitance load like piezo w/o current limiting resistors. Though volume 'd be limited back to 1 pin level.
 Don't want to discourage an author, just something to think about, may be put some kind of warning in library header, that reliability of IC could be affected. .
I

I followed the lead of the Arduino.cc website and didn't add a resistor to the piezo circuit drawing. For an 8 Ohm speaker, a single 100 ohm resistor should be used, just like you would with one pin attached.  You don't add two resistors, just one.  Therefore, it's still twice as loud as using the tone library if you use the same resistor.

Also, isn't there normally a high resistance on a piezo and it's not till high frequencies where the resistance drops to even around 50 ohms?  I believe a resistor is only needed for very high frequencies.  Also, I believe when driving the piezo with an alternating current like toneAC it doesn't create the high capacitance load like you normally see when driving (charging) it in one direction.

Tim
« Last Edit: January 13, 2013, 03:52:16 am by teckel » Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Piezo elements are like capacitors, that is a problem for higher frequencies. For ultrasonic sound it is even very bad to use a square wave, because of the peak currents. So there should be a resistor of 220 ohm (or 100 ohm ?) to protect the outputs of the Arduino. Please add a warning about that to your library.

I believe a piezo only acts like a capacitor when "charged" in one direction (for example, with the tone library).  The deflection of the disc is what generates the current.  However, with toneAC it can't charge in this way as an alternating current is being sent.  Therefore, the piezo is never charged and never acts like a capacitor.  From my understanding of how a charge on a piezo works, supplying an alternating current eliminates the need for a resistor.  But, maybe I'm mistaken.

Tested with normal 8 ohm speaker with extra 120 ohm resistor:
- Arduino Uno, pin 9,10 : good.
- Arduino Mega 2560, pin 11,12 : good
- Arduino Leonardo, pin 9,10 : good
- ATmega8 16MHz, pin 9,10 : good

Nice!  Mega, Leonardo, and ATmega8 were my primary concerns.  I spent a lot of time sniffing around the Arduino code so I had hoped that I got everything correct.

My conclusion:
- No nasty click at start and stop : Excellent. A very small click can be heard.
- Extra loud : Good
- Small, fast code : Excellent
- Flexibility : Not so good, fixed pins.

The reason it doesn't have any nasty clicking and noise like you get with the tone library is because I'm letting the ATmega do it's own PWM thing instead of faking it like the tone library does.  The tone library just sets up a timed event and then the library twiddles the bits.  It works, but not perfectly.  This is why I have toneAC fixed to the PWM pins.  It would be simple to allow any pins to be used, but the the accuracy wouldn't be perfect (which is required to keep things perfectly out of phase).  There would also be a little more to do than with the tone library because two pins would need to be toggled instead of one.  Also, as you get into ultrasonic frequencies, there's just not enough processing power on the poor little ATmega to do everything.

- Volume control : Good, I needed that. Working roughly, not a linear scale.

Very true, the volume is not at all linear.  It simply uses the duty cycle which is not linear for audio.  I didn't want to hold up the library being released to sort this out.  But, it's something I'm still looking into.  What I'm thinking is measuring SPL of every duty level and then creating a table of 10 duty cycles (1=min, 10=max) that are linear for volume.

- Frequency range : The lowest frequency is not low enough for a slow blinking two-pin dual led.

I've got it running here with no problem.  For v1.0 of toneAC a 16 MHz ATmega will be able to go down to 2 Hz.  My development v1.1 now goes down to 1 Hz (changed to prescaler 256).  Here's the sketch I used:

Code:
#include <toneAC.h>

void setup() {}

void loop() {
  int pot = analogRead(A0);
  int freq = map(pot, 0, 1023, 3, 30);
  toneAC(freq);
  delay(334);
}

If I select a ultrasonic frequency, I don't hear it, but a very small click can be heard when the sound is started and stopped.
Perhaps setting the pins floating (set as inputs) if not used could reduce that. But that will make the code larger.
The normal Arduino tone() library doesn't work for all frequencies with the ATmega8. I didn't test that for your toneAC library very well, but it sounds okay.

When I do this, I don't hear a click.  Then again, I used an ultrasonic (40 kHz) piezo and not a speaker.  I'm not so worried about small clicks on start/stop (this is kind of expected).  The clicking while playing a constant note or notes is what I have a problem with.

PS: Do you know the Mozzi library ? http://sensorium.github.com/Mozzi/

Not till now.  But, doing that kind of thing should be easy with toneAC.  Just convert a WAV or MP3 file to something like 8-16 kHz mono and save as RAW.  Then load it into a sktech and play the sequence.  Maybe I'll do a dog bark example or something.

Tim
« Last Edit: January 13, 2013, 12:31:48 pm by teckel » Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As far as I know, a piezo element is always like a capacitor.
If you have a capacitance meter, try your ultrasonic piezo. It could easily be 100nF.
If the capacitance meter uses a DC signal to measure, just add a capacitor in series with the piezo. It won't make any difference.

I used a ultrasonic piezo with a square AC wave (just like toneAC) and my high speed H-bridge driver ic got very hot and got blown.
I learned that 120dB ultrasonic piezo drivers don't use a square wave because of the capacitance. They use some kind of (simulated) sine wave.

If the starting frequency could be 1Hz for a Arduino Uno at 16MHz, that would be very nice.

Can you make a very low volume ?
It is as with the PWM for leds. To get a led dimmed so that it is almost not visible, the pwm should be between 1/1000 or 1/10000.

What about H-bridge drivers for more output power. What kind of driver ic would match your library for a few different applications ?
« Last Edit: January 13, 2013, 08:21:56 am by Krodal » Logged

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I did some testing on different acoustic transducers.  First, for my ultrasonic transducers I could not get them to draw more than 7 mA no matter the frequency (even the harmonic peak).  I have one "piezo" that seems to work more like a regular speaker at 16 ohms.  That unit can draw up to 33 mA without a resistor.  My guess is that it's not a piezo as my true piezo transducers have a resistance in the mega ohms as they should.

Because of this, I've changed my circuit drawing to include a 100 ohm resistor as it doesn't make much of a difference and it seems that maybe some that claim are piezo are not really piezo.  With that said, I'm still not certain that driving a true piezo transducer even at ultrasonic levels requires a resistor when using an alternating current.  From what I've read, the capacitance charging only occurs under a DC load, and that charged is discharged when the polarity is reversed (such as in an AC system).  Still more testing to confirm this.

For the time being, you should connect a piezo or speaker exactly as you have in the past, a decision on AC connection will need more research.  Still toneAC is twice as loud, even when you use or don't use a resistor as you would normally.

Progress on v1.1 of toneAC is coming along.  Two major changes that are being tested are a linear volume and a tone length value that works in the background like the tone library.  We should see v1.1 released sometime this week.

Tim
« Last Edit: January 14, 2013, 02:50:16 am by teckel » Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Added background playback (timer interrupt controlled) and linear volume to my development version of toneAC.  I'll be testing it on Tuesday.  Expect a new release probably on Tuesday or Wednesday.

Tim
Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

While not written to do this, toneAC works well controlling a two-pin dual LED.  With this and a potentiometer, the sketch below will flash the LED alternating between the two LED colors.  This is happening in the background with control returning to your sketch to do other things as noted in the sketch.  Every half second it will look at the pot and change the LED flashing speed.  This sketch is designed to work with toneAC v1.1 that will be released once I get home

Code:
// ---------------------------------------------------------------------------
// Connect a two-pin dual LED to the following pins with inline 220 ohm resistor.
//   Pins  9 & 10 - ATmega328, ATmega128, ATmega8, Uno, Leonardo, etc.
//   Pins 11 & 12 - ATmega2560, ATmega1280, Mega
//   Pins 14 & 15 - Teensy 2.0
//   Pins 25 & 26 - Teensy++ 2.0
// Connect the center lead of a potentiometer to analog pin A0 and the other two leads to +5V and ground.
// ---------------------------------------------------------------------------

#include <toneAC.h>

unsigned long timestamp = 0; // Stores when the next time the routine is set to run.

void setup() {}

void loop() {
  if (millis() > timestamp) { // Is it time yet?
    timestamp += 500;         // Set the next time routine will run. 500 ms because the lowest frequency is 2 Hz, which is a half second.
    int pot = analogRead(A0);            // Read the potentiometer connected to analog pin A0.
    int freq = map(pot, 0, 1023, 2, 40); // Convert pot analog values to a range from 2 to 40 Hz.
    toneAC(freq, 10, 0, true);           // Set the frequency and have it run forever in the background (next event should take over in 500 ms).
  }
  /* Do a bunch of other stuff here, it won't affect toneAC doing its thing. */
}

Because toneAC is designed to be used for audio, duty has been purposed for linear volume control instead of fading the LED from one color to the other evenly.  Basically, duty is linear for audio but not for lighting an LED.  If there's a desire for linear LED duty control, making a few tweaks to the toneAC library or making a different library designed just for controlling a two color LED would be in order.  The above sketch is a teaser that may help someone with a project.

Tim
« Last Edit: January 15, 2013, 08:19:37 pm by teckel » Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Toledo, OH
Offline Offline
God Member
*****
Karma: 35
Posts: 508
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

New in v1.1
Option to play notes in background, returning control back to your sketch for processing while note plays (similar to the way the tone library works). Volume is now linear and in the range from 0-10. Now uses prescaler 256 instead of 64 for frequencies below 122 Hz so it can go down to 1 Hz no matter what speed the CPU is clocked at (helpful if using toneAC to control a two-pin dual LED).

Download:
toneAC v1.1

Tim
Logged

Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm still testing it, but I think I found an error.

Code:
int f;

while(1)
{
  f = random( 50, 120);
  toneAC(f, 5, 0, true);
  delay(100);
  noToneAC();    // reset registers
}

The example is okay with the noToneAC() to reset the registers.
Try to remove the noToneAC(), that results in gaps in the sound.
Perhaps the counter has to roll-over ?
Logged

Pages: [1] 2 3 4   Go Up
Jump to: