Arduino Forum

Development => Other Software Development => Topic started by: teckel on Jan 21, 2013, 06:09 am

Title: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Jan 21, 2013, 06:09 am
Why another tone library?
I'd already written a highly optimized toneAC library (https://bitbucket.org/teckel12/arduino-new-tone/wiki/Home) 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?


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 (https://bitbucket.org/teckel12/arduino-new-tone/downloads)

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 (https://bitbucket.org/teckel12/arduino-toneac/wiki/Home) as well.

Example sketch
Code: [Select]

#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
Title: Re: NewTone Library - Plug-in replacement for the standard Tone library
Post by: Osgeld on Jan 21, 2013, 07:28 am
does it work with mega?
Title: Re: NewTone Library - Plug-in replacement for the standard Tone library
Post by: teckel on Jan 21, 2013, 07:52 am

does it work with mega?


Yup, should work with all ATmega microcontrollers.  Tested on my Uno and Teensy 2.0, which are totally different.  Doesn't hard code port register values so it should work on all platforms.  I use the same technique with NewPing (http://code.google.com/p/arduino-new-ping/) and compatibility is universal for any ATmega microcontroller.  Will be simple to confirm it works.

Tim
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: sldiesel on Mar 30, 2013, 10:45 pm
Hi have been trying to adapt to use it on Timer "4" on the mega
As i can not use it on Timer 1 as it then conflicts width my PWM signals on the MEGA 2560  ;-(
I am trying to drive a speedometer
as you see i have just tryed to change the 1 to 4 not sure i know what i am doing
Any reply greatly appriciatet ;-)

I have changed here

NewTone.h

#define TIMSK4 TIMSK //#define TIMSK1 TIMSK

NewTone.cpp

ICR4    = top;                     // Set the top.
  if (TCNT4 > top) TCNT4 = top;      // Counter over the top, put within range.
  TCCR4B  = _BV(WGM40)  | prescaler; // Set PWM, phase and frequency corrected (ICR1) and prescaler.
  TCCR4A  = _BV(COM4B0);
  TIMSK4 |= _BV(OCIE4A);             // Activate the timer interrupt.

TIMSK4 &= ~_BV(OCIE4A);   // Remove the timer interrupt.
  TCCR4B  = _BV(CS40);      // Default clock prescaler of 8.
  TCCR4A  = _BV(WGM40);     // Set to defaults so PWM can work like normal (PWM, phase corrected, 8bit).

ISR(TIMER4_COMPA_vect) { // Timer interrupt vector.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Apr 11, 2013, 11:58 pm

Hi have been trying to adapt to use it on Timer "4" on the mega
As i can not use it on Timer 1 as it then conflicts width my PWM signals on the MEGA 2560  ;-(
I am trying to drive a speedometer
as you see i have just tryed to change the 1 to 4 not sure i know what i am doing
Any reply greatly appriciatet ;-)

I have changed here

NewTone.h

#define TIMSK4 TIMSK //#define TIMSK1 TIMSK

NewTone.cpp

ICR4    = top;                     // Set the top.
 if (TCNT4 > top) TCNT4 = top;      // Counter over the top, put within range.
 TCCR4B  = _BV(WGM40)  | prescaler; // Set PWM, phase and frequency corrected (ICR1) and prescaler.
 TCCR4A  = _BV(COM4B0);
 TIMSK4 |= _BV(OCIE4A);             // Activate the timer interrupt.

TIMSK4 &= ~_BV(OCIE4A);   // Remove the timer interrupt.
 TCCR4B  = _BV(CS40);      // Default clock prescaler of 8.
 TCCR4A  = _BV(WGM40);     // Set to defaults so PWM can work like normal (PWM, phase corrected, 8bit).

ISR(TIMER4_COMPA_vect) { // Timer interrupt vector.



It doesn't just conflict with the PWM signals, it replaces them.  It's by design.  Instead, why not just use PWM for timer 4 for whatever else you're doing?

One of the main purposes of NewTone is to use a different timer than the standard tone library.

In any case, I don't really know the ATmega2560 to know off the top of my head if there's any differences between timer 1 and timer 4.  Are they identical?  For example, if timer 4 doesn't have all the features of timer 1, it won't work.  It doesn't appear it's identical as it has 3 pins tied to timer 4 while timer 1 only has 2.

Without diving into the ATmega2560 technical documentation, I'll be hard-pressed to help.

Instead, I would suggest using my ToneAC library (https://code.google.com/p/arduino-tone-ac/downloads/list) (there's an alternate version which uses timer 2).  It's superior to NewTone anyway and is already written to use timer 2 and can be assigned to any pins.

Tim
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: sldiesel on Apr 12, 2013, 10:40 pm
Hi Thanks for you reply
but i have solved it

Width great help from this Forum :-)

http://arduino.cc/forum/index.php/topic,157602.0.html

Thanks
Ole
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: TheKitty on Apr 15, 2013, 04:48 am
this could be awesome if the library was also Due compatible
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Apr 15, 2013, 04:53 pm

this could be awesome if the library was also Due compatible


I don't find the Due relevant, so I don't consider support for it.  Also, as NewTone uses port registers and direct timer calls, it doesn't really work well for the Due which is totally different than the ATmega.

Tim
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: TheKitty on May 14, 2013, 06:10 pm

I don't find the Due relevant, so I don't consider support for it. 


Supposedly it is the future as they did not stick with a compatible processor.  Many have written suitable timer control libraries so the work would not be from datasheet scratch.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: infantilo on Jul 04, 2013, 12:22 pm
Hi,
i've some problems using the cool NewTone Library together with RCSwitch-Library (using interrupt on pin 2)

I can play sound several times correctly (always using the same function), and than it suddenly stopps playing any sound, while everything else is working fine.
Shure both libs use timers and this will harm the sound quality, but why isn't it working any more?
PLZ gibe advice what i'm doing wrong or if there's an workaround.

i'm still on arduino 1.0.1 and i'm using an arduino nano V3. The code isn't pretty..sorry for that.

MANY MANY thanks for your replys

Code: [Select]

#include <RemoteReceiver.h>
#include <RemoteTransmitter.h>
#include <NewRemoteReceiver.h>
#include <InterruptChain.h>
#include <SerialCommand.h>

#include <NewTone.h>

int *currentMelody;
int *currentMelodyDurations;
int currentMelodyPosition = 0;
int currentMelodyLength = 0;
int pace = 1150; // music speed

int melodyBeep[] = {NOTE_C5, NOTE_C6};
int noteDurationsBeep[] = {8, 16};
int melodyBeepLength = 2;

int melodyUp[] = {NOTE_C4, NOTE_D4, NOTE_G4};
int noteDurationsUp[] = {4, 8, 16}; 
int melodyUpLength = 3;

int melodyDown[] = {NOTE_G4, NOTE_D4, NOTE_C4};
int noteDurationsDown[] = {4, 8, 16}; 
int melodyDownLength = 3;

int melodyAlarm[] = {NOTE_C6, NOTE_G6, NOTE_C6, NOTE_G5, NOTE_C7, NOTE_C6};
int noteDurationsAlarm[] = {16, 16, 8, 8, 4, 8}; 
int melodyAlarmLength = 6;

// pin for the piezzo buzzer
const int BuzzerPin = 3;
 
// set the pin where the RF transmitter is connected to
const int transmitterPin = 4;

//duration of a RF command
const unsigned int period = 326;

boolean playsound = false;
boolean playloop = false;

// amount of identical codes to receiver before trigger showCode function
int CodeRepetitions = 5;

SerialCommand SCmd;   // initialise the SerialCommand object

void setup() {
  // Initialise the serial port
  Serial.begin(9600);
  Serial.println("HomeSecurityRFbridge running on Arduino Nano V3.0");
  // Initialize receiver on interrupt 0 (= digital pin 2), calls the callback "showCode"
  // after CodeRepetitions (3) identical codes have been received in a row. (thus, keep the button pressed
  // for a moment)


  // And once more, interrupt -1 to indicate you will call the interrupt handler with InterruptChain

  // Interrupt -1 to indicate you will call the interrupt handler with InterruptChain
  RemoteReceiver::init(-1, 2, showOldCode);

  // Again, interrupt -1 to indicate you will call the interrupt handler with InterruptChain
  NewRemoteReceiver::init(-1, 2, showNewCode);


  // On interrupt, call the interrupt handlers of remote and sensor receivers
  InterruptChain::addInterruptCallback(0, RemoteReceiver::interruptHandler);
  InterruptChain::addInterruptCallback(0, NewRemoteReceiver::interruptHandler);


// Serial.print("Setting up callbacks for SerialCommands...");
  // Setup callbacks for SerialCommand commands
  //Serial.print("hello [optional arg] (replys welcome string or RE:arg) ");
  SCmd.addCommand("hello",SayHello);     // Echos the string argument back
  //Serial.print("|P [arg1] [arg2] (processes two arg commands) ");
  SCmd.addCommand("P",process_command);  // Converts two arguments to integers and echos them back
  //Serial.print("|S [arg] (sends arg) ");
  SCmd.addCommand("S",process_switch_command);  // Converts two arguments to integers and echos them back
  SCmd.addCommand("BU",BeepUp);  // Converts two arguments to integers and echos them back
  SCmd.addCommand("BD",BeepDown);  // Converts two arguments to integers and echos them back
  SCmd.addCommand("STOP",StopAudio);  // Converts two arguments to integers and echos them back
  SCmd.addCommand("BEEP",Beep);  // Converts two arguments to integers and echos them back
  SCmd.addCommand("ALARM",Alarm);  // Converts two arguments to integers and echos them back
  SCmd.setDefaultHandler(unrecognized);  // Handler for command that isn't matched  (says "What?")
  //Serial.println("...ok");

}

void loop() {
  while (playsound && currentMelodyPosition<currentMelodyLength) {
      int duration = pace/currentMelodyDurations[currentMelodyPosition];//Adjust duration with the pace of music
      NewTone(BuzzerPin,currentMelody[currentMelodyPosition],duration);
      int time = millis() + duration*1.2;
      while (millis()<time) {
        SCmd.readSerial();     // We don't do much, just process serial commands
      }
      currentMelodyPosition++;
      if (playloop && currentMelodyPosition==currentMelodyLength) {
          currentMelodyPosition=0;
      }
  }
  SCmd.readSerial();     // We don't do much, just process serial commands
}


void BeepUp() {
  currentMelody = &melodyUp[0];
  currentMelodyDurations = &noteDurationsUp[0];
  currentMelodyLength = melodyUpLength;
  currentMelodyPosition = 0;
  playsound = true;
  playloop = false;
  //tone(BuzzerPin,NOTE_C5,1000/2);
}

void BeepDown() {
  currentMelody = &melodyDown[0];
  currentMelodyDurations = &noteDurationsDown[0];
  currentMelodyLength = melodyDownLength;
  currentMelodyPosition = 0;
  playsound = true;
  playloop = false;
//  tone(BuzzerPin,NOTE_C1,1000/2);
}

void Beep() {
  currentMelody = &melodyBeep[0];
  currentMelodyDurations = &noteDurationsBeep[0];
  currentMelodyLength = melodyBeepLength;
  currentMelodyPosition = 0;
  playsound = true;
  playloop = false;
//  tone(BuzzerPin,NOTE_C3,1000/2);
}

void Alarm() {
  currentMelody = &melodyAlarm[0];
  currentMelodyDurations = noteDurationsAlarm;
  currentMelodyLength = melodyAlarmLength;
  currentMelodyPosition = 0;
  playsound = true;
  playloop = true;
}

void StopAudio() {
  playsound = false;
  playloop = false;
  currentMelodyLength = 0;
  currentMelodyPosition = 0;
  noNewTone(BuzzerPin);
}


// shows the received code sent from an old-style remote switch
void showOldCode(unsigned long receivedCode, unsigned int period) {
  // Print the received code.
  Serial.print("@OC,C:");
  Serial.print(receivedCode);
  Serial.print(",P:");
  Serial.print(period);
  Serial.println("#");
}

// Shows the received code sent from an new-style remote switch
void showNewCode(NewRemoteCode receivedCode) {
  // Print the received code.
  Serial.print("@NC,A:");
  Serial.print(receivedCode.address);

  if (receivedCode.groupBit) {
    Serial.print(",G:");
  }
  else {
    Serial.print(",U");
    Serial.print(receivedCode.unit);
  }

  switch (receivedCode.switchType) {
  case 0:
    Serial.print(",S:0");
    break;
  case 1:
    Serial.print(",S:1");
    break;
  case 2:
    Serial.print(",D:");
    Serial.print(receivedCode.dimLevel);
    break;
  }

  Serial.print(",P:");
  Serial.print(receivedCode.period);
  Serial.println("#");
}




// process the HELLO command from USB
void SayHello()
{
  char *arg; 
  arg = SCmd.next();    // Get the next argument from the SerialCommand object buffer
  if (arg != NULL)      // As long as it existed, take it
  {
    Serial.print("RE:");
    Serial.println(arg);
  }
  else {
    Serial.println("HomeSecurityRFbridge running on Arduino Nano V3.0");
  }
}


// process the serial data from USB
void process_command()   
{
  long aNumber; 
  char *arg;

  //Serial.println("arduino is in process_command");
  arg = SCmd.next();
  if (arg != NULL)
  {
    aNumber=atoi(arg);    // Converts a char string to an integer
    //Serial.print("First argument was: ");
    //Serial.println(aNumber);
  }
  else {
    //Serial.println("No arguments");
  }

  arg = SCmd.next();
  if (arg != NULL)
  {
    aNumber=atol(arg);
    //Serial.print("Second argument was: ");
    //Serial.println(aNumber);
  }
  else {
    //Serial.println("No second argument");
  }

}


// process the switch command from USB
void process_switch_command()   
{
  unsigned long CodeToSend; 
  char *arg1;
  int PeriodToSend; 
  char *arg2;

  //Serial.println("arduino is in process_switch_command");
  arg1 = SCmd.next();
  if (arg1 != NULL)
  {
    CodeToSend=atol(arg1);    // Converts a char string to an integer
    //Serial.print("code to send: ");
    //Serial.println(CodeToSend);

    arg2 = SCmd.next();
    if (arg2 != NULL)
    {
      PeriodToSend=atol(arg2);
      //Serial.print("period: ");
      //Serial.println(PeriodToSend);
    }
    else {
      //Serial.println("using standard period");
      PeriodToSend = period;
    }
    send_switch(CodeToSend,PeriodToSend);
  }
  else {
    //Serial.println("No arguments -> no send!");
  }



}


// This gets set as the default handler, and gets called when no other command matches.
void unrecognized(const char *command) {
  Serial.println("What?");
}





void send_switch(unsigned long CodeToSend, unsigned int PeriodToSend)   
{
  // Disable the receiver; otherwise it might pick up the retransmit as well.
  RemoteReceiver::disable();

  // Need interrupts for delay()
  interrupts();

  // Retransmit the signal 8 times ( == 2^3) on pin 11. Note: no object was created!
  RemoteTransmitter::sendCode(transmitterPin, CodeToSend, PeriodToSend, 3);

  RemoteReceiver::enable();
}
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: RoyDene on Sep 21, 2013, 09:01 pm
Hi,

I am trying to generate a freq of 1hz till 600khz. I think toneAC can do it but what is the max freq that newtone can generate?

Also can it be used on a Arduino Nano?

Thanks

Roy
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: effedebe on Oct 24, 2013, 12:08 am
Hi,

This new tone lib is very cool

Thanks a lot !

Here below a sample of french movie picture melody.



Code: [Select]

#define o3C 262
#define o3Cd 277
#define o3D 294
#define o3Dd 311
#define o3E 330
#define o3F 349
#define o3Fd 370
#define o3G 392
#define o3Gd 415
#define o3A 440
#define o3Ad 466
#define o3B 494
#define o4C 523
#define o4Cd 554
#define o4D 587
#define o4Dd 622
#define o4E 659
#define o4F 698
#define o4Fd 740
#define o4G 784
#define o4Gd 830
#define o4A 880
#define o4Ad 932
#define o4B 988
#define ooo 0

#include <NewTone.h>
#define TONE_PIN 12
int tempo = 650;

// freq,duration, etc ..
int measures[] =
{
o3A,4,o3A,4,o3A,4,o3A,4,
o3A,8,o3Gd,8,o3A,8,o3B,8,o4C,2,
o3B,8,o4D,8,o4C,3,o3B,8,o3A,8,o3Gd,8,
o3A,8,o4E,8,o4C,8,o4E,8,o3A,8,o3E,8,o3Fd,8,o3Gd,8,
o3A,4,o3A,4,o3A,4,o3A,4,
o3A,8,o3Gd,8,o3A,8,o3B,8,o4C,2,
o3B,8,o4D,8,o4C,3,o3B,8,o3A,8,o3Gd,8,
o3A,8,o4E,8,o4C,8,o4E,8,o3A,2,
o4D,4,o4D,4,o4D,4,o4D,4,
o4D,8,o4Cd,8,o4D,8,o4E,8,o4F,2,
o4C,4,o4C,4,o4C,4,o4C,4,
o4C,8,o3B,8,o4C,8,o4D,8,o4E,2,
o3Ad,4,o3Ad,4,o3Ad,4,o3Ad,4,
o3Ad,8,o3A,8,o3B,8,o4C,8,o4D,8,o4C,8,o3B,8,o4D,8,
o3A,8,o3E,8,o3Fd,8,o3Gd,8,o3A,8,o4E,8,o4C,8,o4E,8,
o3A,2,ooo,4
};

void setup() {}

void loop()
{
for (int i = 0; i < sizeof(measures)/2; i=i+2)
{
if (measures[i]>0) NewTone(TONE_PIN, measures[i], tempo/measures[i+1]);
delay(tempo/measures[i+1] * 1.333);
}
noNewTone(TONE_PIN);

}


I would like to made some music to my robot, but I can't use virtualwire lib with new tone lib because timers is sames for both libraries.
I've found another servo lib than original who have same problem. This is fixed.
( it is sofware servo: http://playground.arduino.cc/ComponentLib/Servo)

But not with virtual wire.

Virtual wire use timer1 (16 bits resolution). NewTone lib too.

some informations found about timers here:
http://letsmakerobots.com/node/28278

It is possible to unusable or change timer ?

thx
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Nov 14, 2014, 08:55 pm
Try my toneAC2 (https://code.google.com/p/arduino-tone-ac/) library if you want to use timer 2.  Also, the standard tone library also uses timer 2.  I wrote NewTone and toneAC to use timer 1 if you were having a timer 2 conflict with something else.  If timer 1 is your conflict, use the standard tone library or toneAC2.

Tim
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: HankB on Dec 24, 2014, 06:49 am
Hi Tim,
Thanks for your work on the various tone libraries. I'm presently building a device that uses one to drive a speaker to play music. I have a question about usage of timers and outputs. I'd like to keep the possibility open to produce two channels of output (concurrently.) In other words I'd like to play the main melody on one digital output and harmony on another digital output. I also prefer to stick with one output/channel. Is there a tone library or combination of libraries that can do this?

Thanks!
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: coopecb1 on Aug 28, 2015, 11:40 pm
Brilliant! Solves the < 31 Hz problem of the original.

My application: use with a micro-stepping motor driver that has step and direction inputs. This makes variable speed control very easy.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: Zainwan on Sep 04, 2015, 04:39 pm
Hi,

Does this library works together with addressable LED strips (NeoPixel library)?
Because to get the tight timing needed by the LED strips interrupts are disabled while sending the data.
So the original Tone() library doesnt work for me. Wondering if newTone Library works?
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: mcmahonrw on Aug 20, 2016, 03:02 am
Any plans for supporting ATtiny85 (Adafruit Trinket)?
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Aug 22, 2016, 11:40 pm
Any plans for supporting ATtiny85 (Adafruit Trinket)?
Not sure if it would be possible do to the use of timers.  But, I do know that my TimerFreeTone (https://bitbucket.org/teckel12/arduino-timer-free-tone/wiki/Home) library is compatible with the ATtiny 85 (and just about any other platform as it doesn't use timers).

Tim

Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: HoracioDos on Nov 28, 2016, 10:57 pm
Hi!

I'm very new to Arduino and electronics. I'm building a capacitive touch morse keyer and I need to generate a 800 to 1200 Hz tone. I still don't know for sure if a sine wave is needed or a square wave is good enough to TX with a simple LPF.

Does the NewTone() make a square wave output like tone()?

I have found that NewTone(pin, freq) makes a little noise when it's ended with noNewTone(), but if I set a duration, the tone ends clean.

I would like to code something like this example, but with a fixed duration. Do you have other library that I could use?

Thanks in advance.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Nov 28, 2016, 11:26 pm
Hi!

I'm very new to Arduino and electronics. I'm building a capacitive touch morse keyer and I need to generate a 800 to 1200 Hz tone. I still don't know for sure if a sine wave is needed or a square wave is good enough to TX with a simple LPF.

Does the NewTone() make a square wave output like tone()?

I have found that NewTone(pin, freq) makes a little noise when it's ended with noNewTone(), but if I set a duration, the tone ends clean.

I would like to code something like this example, but with a fixed duration. Do you have other library that I could use?

Thanks in advance.
Yes, NewTone creates a square wave.  The Arduino can't output a sine wave.  If you need a sine wave, I would suggest using a Teensy 3.2

If you end a tone early it may stop in the middle of the high state.  If it ends on it's own, it always finishes the high state before ending. 

I don't understand your last question.  You want to code something like what example?  NewTone does do a fixed duration so I'm confused.

Tim
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: HoracioDos on Nov 29, 2016, 12:00 am
Hello Tim!

Thanks for your quick answer.

I have attached in the previous post an example from make magazine that creates a sine wave that never ends. I'm trying to merge your library and this example to generate a sine wave with a fixed duration. As I dont want to abuse of your time ¿Do you know or have something already made that I can use?

For example teensy 3.2 could be an option.

Again Thanks!
H
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Nov 29, 2016, 12:10 am
Hello Tim!

Thanks for your quick answer.

I have attached in the previous post an example from make magazine that creates a sine wave that never ends. I'm trying to merge your library and this example to generate a sine wave with a fixed duration. As I dont want to abuse of your time ¿Do you know or have something already made that I can use?

For example teensy 3.2 could be an option.

Again Thanks!
H
Just so you know, this doesn't generate a sine wave.  It creates a simulated sine wave.  You could create a sketch that would modify this SineWave sketch and create a function that would play a simulated sine wave at a preset frequency.  But, it will still be a simulated sine wave, not an actual sine wave.

Keep in mind that a digital pin can only be on or off.  So, no matter the code, that's all it can output.  This SineWave sketch doesn't actually produce anything close to an actual sine wave.  In other words, if you really need a sine wave, this SineWave sketch isn't going to do it for you.

Tim
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: HoracioDos on Nov 29, 2016, 01:07 am
Thank you Tim for explaining me so clearly. You have helped a lot and made think about other options.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: outlookhazy on Dec 07, 2016, 11:24 pm
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 (http://playground.arduino.cc/Code/Debounce?a), I don't think there are any timer conflicts there
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Dec 08, 2016, 12:51 am
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 (http://playground.arduino.cc/Code/Debounce?a), 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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: srnet on Dec 17, 2016, 03:13 pm
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.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Dec 19, 2016, 04:29 pm
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.
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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: 2knuckels on Mar 24, 2018, 01:26 pm
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)
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Mar 26, 2018, 10:51 pm
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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: 2knuckels on Mar 27, 2018, 11:44 am
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.
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: Vantuil on Jan 11, 2019, 06:07 pm
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?


Why another tone library?
I'd already written a highly optimized toneAC library (https://bitbucket.org/teckel12/arduino-new-tone/wiki/Home) 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 (https://bitbucket.org/teckel12/arduino-new-tone/downloads)

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 (https://bitbucket.org/teckel12/arduino-toneac/wiki/Home) as well.

Example sketch
Code: [Select]

#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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Jan 13, 2019, 10:04 pm
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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: iliaka on Jan 27, 2019, 11:45 pm
Dear Tim,
In advance, English is not my native language  :smiley-sad:

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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Jan 28, 2019, 09:53 pm
Dear Tim,
In advance, English is not my native language  :smiley-sad:

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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: maurif2 on Jul 21, 2019, 11:30 am
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

Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: teckel on Jul 21, 2019, 03:32 pm
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
Title: Re: NewTone Library - Plug-in replacement for Tone library - Better, smaller, faster
Post by: maurif2 on Jul 21, 2019, 05:06 pm
Thank a lot for the answer!

I will read the documentation.