Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tone() causes division by zero and gets stuck in infinite loop if frequency is 0 #519

Closed
adriaanb opened this issue May 10, 2020 · 0 comments · Fixed by #520
Closed

tone() causes division by zero and gets stuck in infinite loop if frequency is 0 #519

adriaanb opened this issue May 10, 2020 · 0 comments · Fixed by #520

Comments

@adriaanb
Copy link
Contributor

adriaanb commented May 10, 2020

General description

On AVR chips, the tone() function allowed for the introduction of pauses by using a frequency of 0 (see toneMelody.ino example). While this leads to a division by 0 both in the AVR and SAMD implementations of that function, the SAMD platform appears to handle divisions by 0 differently. This causes the sketch to crash.

Expected behavior

The frequency of 0 should result in silence/produce a pause.

Actual behavior

Calling the tone() function with a frequency of 0 results in a crash.

Steps to reproduce

Run the toneMelody.ino example or any other sketch resulting in passing frequency 0 to the tone() function.

Additional information

Adafruit solves this by substituting a frequency of 1 for every instance 0 is passed, see Adafruit's version of ArduinoCore-samd Tone.cpp:

 //if it's a rest, set to 1Hz (below audio range)
 frequency = (frequency > 0 ? frequency : 1); 

This, however, only works for tones shorter than ~500 milliseconds. If the tone duration is longer than that, the sketch produces a high-pitched whine. Using libraries that rely on or interfere with timer interrupts (such as FastLED or the Servo library) can cause additional audio glitches if a frequency of 1 is being used.

Tested on Arduino Nano 33 IoT and Adafruit Metro M0 Express.

Workarounds

Choosing a frequency above, instead of below the audible range, seems to produce more reliable results. 30000 appears to be a number that causes the least noticeable audible artifacts, based on very rudimentary testing.

A better solution, however, is to use noTone() to introduce a pause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant