NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster

Thank you Tim for explaining me so clearly. You have helped a lot and made think about other options.

Certainly not the author's fault, but FYI I attempted to use this as a drop-in replacement for tone in my application and caused a small fire... (I'm driving an inductor/oscillator pretty hard). Not sure if the duty cycle was higher, or it just kept the pin high for too long for some other reason.
The only other library i'm using in this sketch is debounce, I don't think there are any timer conflicts there

outlookhazy:
Certainly not the author's fault, but FYI I attempted to use this as a drop-in replacement for tone in my application and caused a small fire... (I'm driving an inductor/oscillator pretty hard). Not sure if the duty cycle was higher, or it just kept the pin high for too long for some other reason.
The only other library i'm using in this sketch is debounce, I don't think there are any timer conflicts there

A timer conflict wouldn't cause it and even if the pin was kept high for a long time it wouldn't cause a fire at 5 volts. Something else is wrong, it's not the software.

Tim

You may be intersted in a problem I have encountered when using TimerFreeTone on a DUE;

http://forum.arduino.cc/index.php?topic=442298.msg3044752#msg3044752

I dont think the problem is with TimerFreeTone, but something unique to the DUE, whereby the timing (TimerFreeTone or bitbanging) gets messed up depending on where the code ends up in memory.

srnet:
You may be intersted in a problem I have encountered when using TimerFreeTone on a DUE;

Odd Problems with Audio Tone Generation on DUE - Arduino Due - Arduino Forum

I dont think the problem is with TimerFreeTone, but something unique to the DUE, whereby the timing (TimerFreeTone or bitbanging) gets messed up depending on where the code ends up in memory.

All TimerFreeTone is does is set a pin high, delay, set pin low, delay, repeat until duration is met. This would also be the same with the code you wrote on your own. Therefore, there must be something happening with the delayMicroseconds() function on the Due.

While TimerFreeTone doesn't use a timer interrupt, other code could be which could cause problems with the delayMicroseconds() function. For example, Serial.write() uses interrupts which could throw off the delayMicroseconds() function, which in turn would mess up TimerFreeTone.

I believe you've answered your own question. Serial.write() effects the timer functions on the DUE for a few ms as it writes data to the serial port. So, if you must use a Serial.write(), add a delay after so it doesn't mess with the frequency you're trying to generate with TimerFreeTone.

The other solution is to use one of the timers on the DUE to replace TimerFreeTone. While TimerFreeTone will work on the DUE, there's far better and more accurate ways of doing it on the DUE.

Tim

PLAYBACK of RAW wave data

Im playing around with your Newtone lib, and I want to playback a raw sound file (1 second) loaded in the flash mem of the nano.

My problem is in what format do I have to provide the sound data that it plays correctly

(The origin is a wav file which I converted to raw 8 bit data with the correct sample rate 2 kHz).

In your comments of the toneAC thread I read, that it is easy to playback raw sound data.

I would be glad if you or some else could give me a hint how to do it.

(I can not use a media player because I want to modify the frequency during runtime)

2knuckels:
PLAYBACK of RAW wave data

Im playing around with your Newtone lib, and I want to playback a raw sound file (1 second) loaded in the flash mem of the nano.

My problem is in what format do I have to provide the sound data that it plays correctly

(The origin is a wav file which I converted to raw 8 bit data with the correct sample rate 2 kHz).

In your comments of the toneAC thread I read, that it is easy to playback raw sound data.

I would be glad if you or some else could give me a hint how to do it.

(I can not use a media player because I want to modify the frequency during runtime)

The sample NewTone library sketch (https://bitbucket.org/teckel12/arduino-new-tone/wiki/Home#!example) plays back a song. You would use a similar process to convert your raw sample to frequencies and build an array would you would then loop through.

Tim

Thank you for the quick reply.
So I am on the right way, ->
I only have to find the right delays, because the main frequencies I got with an FFT.
(15 Hz, 38 Hz, 79 Hz peak 2, 92 Hz peak 1, 115 Hz, 184 Hz, 267 Hz peak 3)
In case someone has already found the "melody" for the lightsaber "hum" it would be kind to post it.

Hello, I know it's an old topic, but I use the NewTone library a lot, the audio quality is flawless, I'm using it in a project with arduino nano, it's a variometer for flying, but I'm having a problem locking with it, I have only 1 pin available to turn on the speaker, so I did not use the toneAC, with the tone library works however the sound has a poor quality it gets distorted, I believe the problem is with TIMER 1, I would like to know if you have a way to modify the NewTone library to use TIMER 2, I believe this could solve the problem, is it possible?

teckel:
Why another tone library?
I'd already written a highly optimized toneAC library because I needed higher volume, volume control, higher frequency, and better quality. However, toneAC uses fixed timer 1 PWM pins so it's not as flexible. Making toneAC work like tone was simple and there would be several advantages over the tone library, so I spent an hour and made NewTone from the toneAC library.

What does it do better/differently?

  • About 1,200 bytes smaller code size than the Tone library.
  • Faster execution time.
  • Exclusive use of port registers for fastest and smallest code.
  • Higher quality sound output than tone library.
  • Uses timer 1 which may free up conflicts with the tone library.

How do I use it?
It's a plug-in replacement for the standard tone library. Add the include, use NewTone() instead of tone() and noNewTone() instead of noTone() to enjoy the benefits. If you're running out of program space or have a timer conflict with the tone library, this is the library for you. See the sketch below for an example.

Download: NewTone v1.0

If you're looking to save even more space and more features like almost twice as loud output and volume control, check out my toneAC library as well.

Example sketch

#include <NewTone.h>

#define TONE_PIN 2 // Pin you have speaker/piezo connected to (be sure to include a 100 ohm resistor).

// Melody (liberated from the toneMelody Arduino example sketch by Tom Igoe).
int melody[] = { 262, 196, 196, 220, 196, 0, 247, 262 };
int noteDurations[] = { 4, 8, 8, 4, 4, 4, 4, 4 };

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

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

delay(1000); // Wait a second.

for (int thisNote = 0; thisNote < 8; thisNote++) { // Loop through the notes in the array.
    int noteDuration = 1000/noteDurations[thisNote];
    NewTone(TONE_PIN, melody[thisNote], noteDuration); // Play thisNote for noteDuration.
    delay(noteDuration * 4 / 3); // Wait while the tone plays in the background, plus another 33% delay between notes.
  }

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




Tim

Vantuil:
Hello, I know it's an old topic, but I use the NewTone library a lot, the audio quality is flawless, I'm using it in a project with arduino nano, it's a variometer for flying, but I'm having a problem locking with it, I have only 1 pin available to turn on the speaker, so I did not use the toneAC, with the tone library works however the sound has a poor quality it gets distorted, I believe the problem is with TIMER 1, I would like to know if you have a way to modify the NewTone library to use TIMER 2, I believe this could solve the problem, is it possible?

I also have a tone library that doesn't use any timers at all (TimerFreeTone), for just such a situation.

Tim

Dear Tim,
In advance, English is not my native language :slightly_frowning_face:

First, thanks for sharing the NewTone-code.
One question you might be the perferct person for and you might be able an willing to help:

Do you know how to get a frequency in decimals? For instance 78,5Hz or 7,85Hz
As far as I see with NewTone I can use integer only.

Thanks,
Ed

iliaka:
Dear Tim,
In advance, English is not my native language :slightly_frowning_face:

First, thanks for sharing the NewTone-code.
One question you might be the perferct person for and you might be able an willing to help:

Do you know how to get a frequency in decimals? For instance 78,5Hz or 7,85Hz
As far as I see with NewTone I can use integer only.

Thanks,
Ed

Simple answer, you can't, as it's integer-based only.

Tim

Hi

I have used the library in Arduino, it works great.

Now I´m triying to use it in mbot graphical mode for Arduino.

This is the code generated by the app

#include <Arduino.h>
#include <Wire.h>
#include <SoftwareSerial.h>

#include <NewTone.h>
double angle_rad = PI/180.0;
double angle_deg = 180.0/PI;

void setup(){
pinMode(13, OUTPUT);
for(int i=0;i<3;++i)
{
NewTone(13, 262, 500);
delay(500*4/3);
_delay(1);
}
}

void loop(){
_loop();
}

void _delay(float seconds){
long endTime = millis() + seconds * 1000;
while(millis() < endTime)_loop();
}

void _loop(){
}

I dosent work I have this mesage

build3862878683788511907.tmp/NewTone.cpp:14: first defined here

Arduino\hardware\arduino\avr\libraries\NewTone/NewTone.cpp:14: multiple definition of `__vector_11'

Do you have any idea whats gooing on?

Thanks a lot

maurif2:
Hi

I have used the library in Arduino, it works great.

Now I´m triying to use it in mbot graphical mode for Arduino.

This is the code generated by the app

#include <Arduino.h>
#include <Wire.h>
#include <SoftwareSerial.h>

#include <NewTone.h>
double angle_rad = PI/180.0;
double angle_deg = 180.0/PI;

void setup(){
pinMode(13, OUTPUT);
for(int i=0;i<3;++i)
{
NewTone(13, 262, 500);
delay(500*4/3);
_delay(1);
}
}

void loop(){
_loop();
}

void _delay(float seconds){
long endTime = millis() + seconds * 1000;
while(millis() < endTime)_loop();
}

void _loop(){
}

I dosent work I have this mesage

build3862878683788511907.tmp/NewTone.cpp:14: first defined here

Arduino\hardware\arduino\avr\libraries\NewTone/NewTone.cpp:14: multiple definition of `__vector_11'

Do you have any idea whats gooing on?

Thanks a lot

Yes, I do have an idea on what is going on, the error says it: multiple definition of `__vector_11'

Have you visited the NewPing repo, which provides help on common issues? It's here:

https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home

Specifically, the above error (albeit a different number in your situation) is addressed. This is a classic Arduino error that means two libraries are attempting to use the same timer. It's not specific to NewPing at all. The solution is also given on the support page above.

Tim

Thank a lot for the answer!

I will read the documentation.

Hi !

As a newbie just started with Arduino programming, I am trying to get the NewTone library working.

Besides the standard 'Tone', I need a second independant tonegenerator. Was hoping to be able to use the NewTone for this (because it uses the second timer), but cannot get it compiling.

Getting a lot of compiler errors as below:

\libraries\NewTone\NewTone.cpp:15:27: error: 'CS10' was not declared in this scope
uint8_t prescaler = _BV(CS10); // Try using prescaler 1 first.
^
\hardware\teensy\avr\cores\teensy3/core_pins.h:47:22: note: in definition of macro '_BV'
#define _BV(n) (1<<(n))
^
\libraries\NewTone\NewTone.cpp:18:21: error: 'CS12' was not declared in this scope
prescaler = _BV(CS12); // Set the 256 prescaler bit.
^
\hardware\teensy\avr\cores\teensy3/core_pins.h:47:22: note: in definition of macro '_BV'
#define _BV(n) (1<<(n))
^
\libraries\NewTone\NewTone.cpp:31:3: error: 'ICR1' was not declared in this scope
ICR1 = top; // Set the top.
^
\libraries\NewTone\NewTone.cpp:32:7: error: 'TCNT1' was not declared in this scope
if (TCNT1 > top) TCNT1 = top; // Counter over the top, put within range.
^

  • Is this library compatible with the Teensy 3.2 ?
  • What am I doing wrong ?

Thanks !

fj3422:

  • Is this library compatible with the Teensy 3.2 ?
  • What am I doing wrong ?

Arduino libraries are typically designed for use ATMega processors unless otherwise noted. Also, any library that uses timers won't work with a Teensy. So no, it's not compatible with the ARM Teensy processor.

The Teensy 3.2 doesn't has totally different timers and far more sophisticated ones. You should investigate how to generate tones or music on the Teensy specifically, not look for an Arduino solution which will only work with Arduino processors.

Tim

Hello, I already use the NewTone.h library on arduino and it works perfectly, better than Tone.h (sincerely congratulations), but I'm migrating my project to Esp32 and it doesn't work, I took a look at the code and saw that it is small, but I don’t have enough knowledge to change, I would like to know if anyone could convert this library to work with Esp32 would be of great help to the whole community.

Thanks...

The tone libraries (all of them) are deeply dependent on some timer(s) on the chip, which vary greatly from one architecture to another, or even between different chips of the same CPU architecture. (eg due, ESP32, and ATmega328 have vastly different timers, but ATmega328 and ATmega4809 (Nano Every) also have significantly different timers.) That means two things:

  1. "tone" code written for a specific processor family (like newTone) has very little chance that it will compile at all for a different processor.

  2. The timer structure of a new processor may be so different that writing "tone" is "difficult" and never gets done (ie Due.)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.