-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Fix Piezo.prototype.note() #1324
Fix Piezo.prototype.note() #1324
Conversation
The `note()` method was passing a frequency (Hz) to the `tone()` method, which is expecting to receive a duty cycle (μs), leading to the wrong note being played. The solution is for `note()` to call `frequency()` instead, which will do the appropriate conversion. Since it took me a while to understand the relationships between `tone`, `frequency` and `note` I've added some documentation to those methods to clear things up for the next person. I've also made some unit tests more aggressive about checking that values are converted appropriately as they're passed around, and commented note-frequency-duty equivalencies to help the test read nicer.
@@ -781,10 +807,11 @@ exports["Piezo - I2C Backpack"] = { | |||
tone: function(test) { | |||
test.expect(3); | |||
|
|||
this.piezo.tone(262, 1000); | |||
// C4 = 262Hz = 1908μs duty cycle (half-period) | |||
this.piezo.tone(1908, 1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated this test because it could be misleading and imply that tone
was supposed to be called with a frequency (since 262Hz is a familiar frequency C4, used elsewhere in these tests).
😖 Seeing a flaky animation test failure on Travis again, and one failure I haven't seen before:
I don't repro locally, would appreciate thoughts on what went wrong here. |
@lyzadanger review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your work on this! I added a bunch of very fine-grained nit comments, but they are all optional from my point of view. I have not tested this on hardware; let me know if that level of review is needed—this is a code/API-level/test review only.
@@ -401,16 +401,37 @@ Piezo.ToSong = function(stringSong, beats) { | |||
return song; | |||
}; | |||
|
|||
/** | |||
* Play a note for a duration. | |||
* @param {string} note - see Piezo.Notes. Case-insensitive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a case-sensitivity test (i.e. invoke this method with a different case in the tests; tests—at least the ones you added—look like they're all lower-case)?
lib/piezo.js
Outdated
|
||
return this.tone(tone, duration); | ||
var frequency = Piezo.Parsers.hzFromInput(note); | ||
return this.frequency(frequency, duration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistically, this could all be done in one statement, e.g.:
return this.frequency(Piezo.Parsers.hzFromInput(note), duration);
as you do in frequency
, eliminating the need for the var
declaration and being consistent, but that's totally up to you.
* @param {number} tone - Given as a computed duty-cycle, | ||
* in microseconds. Larger values produce lower tones. | ||
* See https://en.wikipedia.org/wiki/Duty_cycle | ||
* @param {number} duration - in milliseconds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good commenting. Thank you!
test/piezo.js
Outdated
|
||
// note delegates to tone; | ||
// note delegates to frequncy, which delegates to tone; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
frequency
is misspelled but this is in an incredibly nitpicky comment. Only change it if you have other reason to edit the test file :)
lib/piezo.js
Outdated
/** | ||
* Play a note for a duration. | ||
* @param {string} note - see Piezo.Notes. Case-insensitive. | ||
* If an octave is not given, the configured default octave |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps extend this comment to explain what octave
means in this context (e.g. in the string value "a4"
, "a"
is the note and 4
is the octave)?
test/piezo.js
Outdated
var toneSpy = this.sandbox.spy(this.piezo, "tone"); | ||
var frequencySpy = this.sandbox.spy(this.piezo, "frequency"); | ||
|
||
// accepts octave. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly to comments for the note
attribute of the note
method...maybe drop in definition of difference between note
and octave
here?
Thank you for the review @lyzadanger! I'll push an update addressing your comments by this time tomorrow. I can test these changes locally with an Adafruit Circuit Playground board and Circuit Playground Firmata but I don't have access to any other hardware for testing. If you feel additional testing is required I'll need help with that. |
- Test that `note()` is case-insensitive - Better description of default octave - One-line Piezo.prototype.note - s/frequncy/frequency - Note tests demonstrate the difference between note letter and octave number better
Review feedback addressed. |
@islemaster Lookin' good! I'd love to see the fixup commits squashed when this merges but that's probably in @rwaldron 's purview... :) |
This commit applies upstream fix rwaldron#1324 for issue rwaldron#1323 to code-dot-org/johnny-five early, even though we're behind. This should merge trivially when we catch up. The `note()` method was passing a frequency (Hz) to the `tone()` method, which is expecting to receive a duty cycle (μs), leading to the wrong note being played. The solution is for `note()` to call `frequency()` instead, which will do the appropriate conversion. Since it took me a while to understand the relationships between `tone`, `frequency` and `note` I've added some documentation to those methods to clear things up for the next person. I've also made some unit tests more aggressive about checking that values are converted appropriately as they're passed around, and commented note-frequency-duty equivalencies to help the test read nicer. Includes squashed fixups: - Fix lint error. - Address review feedback: - Test that `note()` is case-insensitive - Better description of default octave - One-line Piezo.prototype.note - s/frequncy/frequency - Note tests demonstrate the difference between note letter and octave number better
Fixes #1323 - FYI @lyzadanger.
The
note()
method was passing a frequency (Hz) to thetone()
method, which is expecting to receive a duty cycle (μs), leading to the wrong note being played. The solution is fornote()
to callfrequency()
instead, which will do the appropriate conversion.Since it took me a while to understand the relationships between
tone
,frequency
andnote
I've added some documentation to those methods to clear things up for the next person. I've also made some unit tests more aggressive about checking that values are converted appropriately as they're passed around, and commented note-frequency-duty equivalencies to help the test read nicer.Question: How is the documentation at http://johnny-five.io/api/piezo/#api generated? The documentation forEDIT: Found the docs on the repository wiki and updated accordingly.tone
there was very helpful in understanding the intent of these methods, but it's also confusing because the first argument is misnamed in the signaturetone(frequency, duration)
. I couldn't find a way to update that from this repo.