toneAC v1.2 - Twice the volume, higher quality, higher frequency, etc.

countofangels:
First of all this library is awesome, and I'm very pleased that I found it. Registered just for this.

Secondly though, I'm running into trouble because of the 9 & 10 pin requirements. (Arduino Uno)

Is there a way someone could point in the right direction to modify the library to use pins 5 & 6? (or other PWM pins in general?) Or perhaps I misunderstand and the relevant timer is ONLY accessible on 9 & 10.

Any reason we couldn't use Timer 0 or Timer 2, per: Arduino Playground - TimerPWMCheatsheet

Alternately, I think it'd be an excellent addition to the library to be able to set options to switch between all possible PWM pins, just to give a little bit more flexibility.

The library uses timer 1, which are hard-coded to the PWM pins 9 & 10 on the Arduino Uno. It's not that my library hard-codes this, this is how the ATmega microcontroller is designed. While it's possible to have the timer interrupt run a small routine that would allow you to use different pins, the speed and accuracy would suffer. This isn't a big deal if you're doing human-audible frequencies as the Arduino would be plenty fast to do this. But, toneAC is designed to do frequencies well beyond even typically ultrasonic range (like 1 MHz) and do so with precise accuracy.

If it was just about flexibility, I would have written the library that way from the beginning (I basically already did when I wrote the NewTone library, which is based on toneAC but allows you to specify a pin). There's no way to keep the speed and accuracy while allowing you to select the pins.

Further, typically the only reason why you wouldn't want to use the timer 1 PWM pins is because you have a conflict with timer 1, not because you can't just move pins around. So, the real issue isn't that you use other pins, it's that you need it to use a different timer. The problem with doing that is that you'll get just as many people complain about using a different timer as it conflicts with a different set of libraries. Timer 0 is basically off-limits because that would mess with the ATmega's internal timers (millis, micros). Timer 2 would be possible, but more complicated as not all ATmega's have a timer 2 (Leonardo, Teensy 2.0) and they would use timer 4 instead.

So, switching over to use timer 2&4 instead of timer 1 would solve a problem for 10%, but create a problem for 10%, in other words a wash. Adding both timer 1 and timer 2/4 support would make the library more than twice the size, which would cause problems for some as it's small enough to be used on microcontrollers like the ATmega8 while the tone library won't fit.

In other words, we wouldn't really be solving anything by adding timer 2/4 support. We would for some, but we'd be creating problems for others.

I would think the only real option would be to rework toneAC and create a new library, say toneAC2 for example. It would simply be a timer 2/4 version of toneAC that would be fixed to the timer 2/4 PWM pins.

Now that I say this, and think about it for a minute, maybe it's not possible. Timer 2 doesn't have a Phase and Frequency Corrected PWM mode, so I don't think you can do it exactly like toneAC. It would need to be a slower and less accurate way.

It's not really that big of a project to do, but I don't have the need for it, therefore not the desire either. If someone is versed in timer interrupts, it would be really easy to take my toneAC and NewTone libraries and make a toneAC2 library that would use timer 2/4 as well as allow you to specify the pins. If I get bored one night maybe I'll do it (probably a 2 hour job). I guess as a bonus I wouldn't need to create a new development page for it. I could just piggy-back it on the toneAC site as an alternative version that uses timer 2/4 and has flexible pin assignments. Ah crap, maybe I will just do it.

Tim

teckel:
Ah crap, maybe I will just do it.

Tim

Ah my name is Tim as well. :stuck_out_tongue:

So from one Tim to another: Thanks for the detailed information involved as to the concerns with the timers. It's helpful for me to learn more about this as a beginner to the Arduino world.

At the moment, I'm mostly trying to figure out how to use your library without conflicting with the SD library's use of the 10 pin as a selector (per: SD - Arduino Reference) Based on what I've read there, though it looks like I may be able to just use SD.begin() to select a different pin for card initiation, and as long as 10 remains an Output that shouldn't actually cause problems.

So actually, with a little reading, I think the library will work for my particular application as it is.

Though I still think it would be awesome to have versions of the library for each of the available timers, just for that extra flexibility. From the pretty robust response you've received on the library in only a couple weeks, I think it's clear that people are finding it useful.

Anyway! Thanks for your efforts.

countofangels:

teckel:
Ah crap, maybe I will just do it.

Tim

Ah my name is Tim as well. :stuck_out_tongue:

So from one Tim to another: Thanks for the detailed information involved as to the concerns with the timers. It's helpful for me to learn more about this as a beginner to the Arduino world.

At the moment, I'm mostly trying to figure out how to use your library without conflicting with the SD library's use of the 10 pin as a selector (per: SD - Arduino Reference) Based on what I've read there, though it looks like I may be able to just use SD.begin() to select a different pin for card initiation, and as long as 10 remains an Output that shouldn't actually cause problems.

So actually, with a little reading, I think the library will work for my particular application as it is.

Though I still think it would be awesome to have versions of the library for each of the available timers, just for that extra flexibility. From the pretty robust response you've received on the library in only a couple weeks, I think it's clear that people are finding it useful.

Anyway! Thanks for your efforts.

If the conflict is with the SD library, it's easy to get around it as it doesn't need to use pin 10. toneAC sets pins 9 and 10 (on the Uno) to output the first time you run it. It also never changes them back to input either.

Tim

countofangels:
Though I still think it would be awesome to have versions of the library for each of the available timers, just for that extra flexibility. From the pretty robust response you've received on the library in only a couple weeks, I think it's clear that people are finding it useful.

I had some extra time so I spent an hour and built the toneAC2 library that uses timer 2 and allows you to use any two pins. It doesn't have the level of accuracy as toneAC nor the range. Also, we lose the volume control because timer 2 doesn't have all the features of timer 1. You're basically trading accuracy, range, and volume for flexible pin assignments.

What's kind of funny is that I wrote toneAC2 at work and I didn't have any Arduino's with me to test. So, I couldn't test it at all, didn't even compile it as I was just using note++ to edit the library. When I got home it had one little bug and then it compiled (needed to declare a variable outside a "for" loop). It compiled the second time and worked perfectly. I guess I've been doing low level port registers and timers too long.

I need to add Teensy and Leonardo support (ATmega32U4 needs to use timer 4 instead of timer 2) and test before I release it. But, that's simple so it should be uploaded this weekend. I'll post when it's available.

Tim

As promised, the pin flexible and timer 2 version of toneAC was released. You can download it from the toneAC development page here:

toneAC2 - v1.0

This is an alternate version of toneAC that uses timer 2 instead of timer 1 and allows for any two pins to be used. You should still try to use toneAC first, as it's more accurate, higher quality, allows for higher frequencies, and creates smaller code. However, if you're having a conflict with timer 1, or just can't use the PWM pins for timer 1, then toneAC2 may be your answer.

toneAC2 is a replacement to the standard tone library with the advantage of nearly twice the volume, 800 bytes smaller compiled code size, and less stress on the speaker. This alternate version uses timer 2 and allows for flexible pin assignment. The primary version (toneAC) allows for higher frequencies, higher quality, and even smaller code size. However, toneAC is fixed to using the PWM timer 1 pins unlike toneAC2 which can use any two pins. Both exclusively use port registers for the fast and smallest code possible.

Let me know if there's any problem. Oh, I didn't add Leonardo and Teensy 2.0 support. I forgot how different timer 4 was on those compared to timer 2. It seemed too much like work to make it compatible so I released it as-is.

Tim

I'm waiting for toneAC version 1.2.

Krodal:
I'm waiting for toneAC version 1.2.

Sorry about that, kind of forgot about releasing it. It's been packaged for distribution for 7 days but I was working with someone via PM to confirm compatibility. In any case, v1.2 is now online and ready to download.

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.

Tim

Library toneAC version 1.2 tested with Uno, Leonardo, Mega 2560, ATmega8 16MHz. Everything is okay.
Library toneAC version 1.2 with option TONEAC_TINY tested with ATmega8 16MHz. Also okay, 140 bytes smaller.

The TONEAC_TINY version has implications for the source code.
If I would use toneAC(1000,5); and switch to TONEAC_TINY, I must change that line. That is not obvious, since it is the same function "toneAC".
The second parameter changes from volume to duration.
Adding a second parameter (an unused volume byte) changes the size saving from 140 to 106.
I don't know what to think of it.

What about a ToneAC page in the Playground section ?

What about a ToneAC page in the Playground section ?

Good idea!

Krodal:
Library toneAC version 1.2 tested with Uno, Leonardo, Mega 2560, ATmega8 16MHz. Everything is okay.
Library toneAC version 1.2 with option TONEAC_TINY tested with ATmega8 16MHz. Also okay, 140 bytes smaller.

The TONEAC_TINY version has implications for the source code.
If I would use toneAC(1000,5); and switch to TONEAC_TINY, I must change that line. That is not obvious, since it is the same function "toneAC".
The second parameter changes from volume to duration.
Adding a second parameter (an unused volume byte) changes the size saving from 140 to 106.
I don't know what to think of it.

It was an oversight not changing the function name for TONEAC_TINY. I now changed the function name to toneAC_tiny() when using the TINY code.

Adding the volume in for TINY code makes the TINY savings only 52 bytes on my 1.0.3 compile on Uno. If it's only 52 bytes of savings I should probably just remove the TINY code totally.

Krodal:
What about a ToneAC page in the Playground section ?

That's the plan, just haven't got to it yet.

Tim

Hi. Can you add ADSR with your library sir? :slight_smile:

http://en.flossmanuals.net/pure-data/audio-tutorials/envelope-generator/

xxryan1234:
Hi. Can you add ADSR with your library sir? :slight_smile:

http://en.flossmanuals.net/pure-data/audio-tutorials/envelope-generator/

Can't be done with toneAC as the ATmega controls all the switching. In order to do ADSR (Attack-Decay-Sustain-Release) we should first create a sine wave instead of a square wave. To do a sine wave, we need to interrupt the ATmega's PWM switching and adjust the duty, this takes valuable CPU cycles. Further, to do ADSR we would need to also adjust the amplitude while the note is being played, further using limited CPU cycles.

All of this "could" be done on the ATmega. But, I'm not sure what the frequency range would be. It would also be well outside the scope of the toneAC library as it would be quite large, slow (CPU intense), and limit the frequency range by a huge amount.

Further, to really do ADSR correctly, it would need to be able to output the release phase of the previous note as the current note was starting the attack phase. This really disqualifies the ATmega as an option.

You'd probably need a more powerful processor and one designed to output audio to really do what you're looking for effectively with any amount of fidelity.

Tim

Krodal:
What about a ToneAC page in the Playground section ?

toneAC in the playground:

http://playground.arduino.cc/Code/ToneAC

Tim

cr0sh:
I don't have the code handy - but waaaay back when I was kid, I remember playing around on my TRS-80 Color Computer with the PLAY command; there was a way, via using certain values (I think random notes played with very, very short durations) with a rapidly decreasing volume level (the CoCo had a 6 bit DAC - so there were 64 volume levels) - you could make an "explosion" or "gun" sound of sort...

Nice to see a CoCo reference here... I recently ported a 1983 Extended Color BASIC program I wrote on the CoCo over to Arduino C (line by line, as literally as possible) and I put in a placeholder for the CoCo's SOUND command. It only took tone and duration, though. There was no built in provision to do noise or volume.

But the Extended Basic PLAY command did allow volume and some great tricks could be done with it. I have been working on a PLAY command, and finding this thread is helpful as it sounds like it would be better to use than what I was working on.

Hi ,
I was trying to use the toneAC library to produce ultrasound in the 20kHz range. Firstly, the library works brilliantly and thank you for that :slight_smile: .
The only issue that i have been having is that sound isin't loud enough. I was using a standard 4 ohm buzzer and the sound output coming from it dosnt seem to be loud enough.

I tried using an Amp LM386 circuit to amplify the output .. described here http://web.mit.edu/6.s28/www/schematics/lm386.htm
But i then had to resort to use one of the 2 pins(9 or 10) which brought the clicking soung back. I have an Atmeg168.

Any you help me figure out how can i raise the output volume. I want t be able to detect the sound in a range of abt 10 m.

Lastly, Im fairly new to this :smiley:

duldul123:
Hi ,
I was trying to use the toneAC library to produce ultrasound in the 20kHz range. Firstly, the library works brilliantly and thank you for that :slight_smile: .
The only issue that i have been having is that sound isin't loud enough. I was using a standard 4 ohm buzzer and the sound output coming from it dosnt seem to be loud enough.

I tried using an Amp LM386 circuit to amplify the output .. described here http://web.mit.edu/6.s28/www/schematics/lm386.htm
But i then had to resort to use one of the 2 pins(9 or 10) which brought the clicking soung back. I have an Atmeg168.

Any you help me figure out how can i raise the output volume. I want t be able to detect the sound in a range of abt 10 m.

Lastly, Im fairly new to this :smiley:

Humans can't hear well in the 20kHz range. Also, many transducers don't produce much at that frequency either. You would need an ultrasonic transducer designed for that range as well as a SPL meter to actually measure the sound output in that frequency range. Basically, you need a different transducer and a different way to measure the volume (not your ears).

As far as the transducer, something like the PROWAVE - 250ST180 would work well, that's what I use. Keep in mind, when you're creating a 20-25kHz sound, humans can't hear it at all. So, while it may be able to output 105dB you won't be able to hear it at all.

To measure the volume at ultrasonic frequencies, you'll need a SPL meter. Depending on your age and how many concerts you've gone to, the max you may be able to hear is probably in the 15kHz to 17kHz range. Here's a Digital Sound Level Meter. But, you can get older models on eBay for cheaper.

Hope that helps!

Tim

Hey Thanks for that... im using ultrasound to transfer a code to a phone... So i actually do want to make sue humans cant here it.... 20k is used because the phone microphone has a die out beyond 22k... i been recording the ultrasound and using a fourier transform library on the phone that give be a power output. So i can measure if the sound is being generated. I will try using the transducer you'v mentioned.

Coming back to the amplifier question, how do i connect it to an amplifier. For the time being i am using an 8w 8 ohm buzzer that i got from a set of altec lansing speakers..

duldul123:
Hey Thanks for that... im using ultrasound to transfer a code to a phone... So i actually do want to make sue humans cant here it.... 20k is used because the phone microphone has a die out beyond 22k... i been recording the ultrasound and using a fourier transform library on the phone that give be a power output. So i can measure if the sound is being generated. I will try using the transducer you'v mentioned.

Coming back to the amplifier question, how do i connect it to an amplifier. For the time being i am using an 8w 8 ohm buzzer that i got from a set of altec lansing speakers..

You can't make it 20kHz and expect humans to hear it. We can't hear sounds generated at that frequency, it's at the very outer edge of what even a baby can hear, and even then it would be EXTREMELY soft. Adults max out more in the 15kHz range. Here's a website for you to test the maximum frequency you can hear.

Therefore, it doesn't matter how big the amplifier is, you're not going to hear a 20kHz signal.

Tim

Thanks tim.

Also.. I do not want to hear the sound. Infact i want to make sure that it cant be head hence i am using this frequency. The only reason i need the amplifier is so that i can increase the volume up to a point that the phone can read it . do a fourier transform and then try and distinguish a particular frequency from another and noise... I can presently do that with a standard audio amplifier circuit but the "Volume" or db value of those frequencies is not high to distinguish them from noise enough beyond a certain distance(1 Meter in the present case) i want to extend it till about 5 M.

So can you suggest how can i connect the two outputs from the Arduino to an amplifier circuit?

duldul123:
Thanks tim.

Also.. I do not want to hear the sound. Infact i want to make sure that it cant be head hence i am using this frequency. The only reason i need the amplifier is so that i can increase the volume up to a point that the phone can read it . do a fourier transform and then try and distinguish a particular frequency from another and noise... I can presently do that with a standard audio amplifier circuit but the "Volume" or db value of those frequencies is not high to distinguish them from noise enough beyond a certain distance(1 Meter in the present case) i want to extend it till about 5 M.

So can you suggest how can i connect the two outputs from the Arduino to an amplifier circuit?

I think it would be easier and cheaper to use a transducer that's designed to output ultrasonic frequencies like the PROWAVE - 250ST180. Also, you would need mic that's also tailored for ultrasonic frequencies. The fall-off from most standard transducers and mics are both quite high beyond 17kHz. In other words, if you want to transmit and receive at ultrasonic frequencies you should be using drivers and mics that are designed for those frequencies.

Also, making an amp for an alternating signal like with toneAC would be a challenge. You can't just use two 2N2222 transistors as you also need to alternate the ground as well, which flips between the two. Not that it's impossible, just much more complex than a typical simple transistor circuit. Keep in mind that toneAC is designed to be like a voltage amplifier without needing an actual circuit. In essence, it doubles the voltage, which increases the volume.

It would be much easier to just use a single transistor as an amp and keep the polarity always the same by using toneAC to drive just one pin instead of both. In other words, just use half of the output of toneAC. The frequency will be the same, and you'll get no volume benefit as it's not doubling the voltage. But, you don't care about that if you're going to connect the output to a transistor tied to a larger voltage.

Tim