stealthmonkey99 / OctoPrint-PWMBuzzer

M300 gcode handler (PWM buzzer via GPIO) for OctoPrint
6 stars 0 forks source link

OctoPrint-PWMBuzzer

If your 3D printer doesn't have a speaker or natively support M300 commands for making beeps, this plugin is for you!

Inspired by @jneilliii's M300Player plugin: you can use a simple (and cheap) passive buzzer, attach it to your Raspberry Pi's GPIO pins, and route M300 commands through it using Pulse-Width Modulation (PWM).

Setup

Hardware Setup

To get started, simply connect your passive buzzer to a ground pin and the (+) side to a triggering GPIO pin, like GPIO16 (BCM). You can find more details online in various tutorials (example).

GPIO Wiring Diagram

Which Buzzer to Use?

I don't have a "recommended" buzzer or speaker - they are all going to sound uniquely awful. My key advice would be to not spend a lot of money on one if you don't already have something laying around. Some options I have verified work:

Larger speakers may require more than the 3.3V we're using from a GPIO pin as diagramed above. You might also experiment with amplifying, e.g. using 5V like I have seen others try.

Can I use the audio jack?

Sorry, no - this plugin only works over the GPIO pins so you will not be able to hear tones through speakers or headphones plugged into the audio jack. There is a software buzzer option that does play through your computer's audio jack, but this requires you to be actively logged into the OctoPrint client in your browser for the tones to be played.

Can I use the hardware timer for better quality sound?

Yes, you can now enable the hardware timer for PWM to improve the sound quality of the passive buzzer. This should help make your tones sound smoother and less crackly, but it does require you to use one of only 4 GPIO pins and manually configure a pwm dtoverlay in your /boot/config.txt file:

GPIO Pin # dtoverlay to configure
12 dtoverlay=pwm,pin=12,func=4
13 dtoverlay=pwm,pin=13,func=4
18 dtoverlay=pwm,pin=18,func=2
19 dtoverlay=pwm,pin=19,func=2

You'll need to provide the admin password to edit the configuration file with root privileges:

sudo nano /boot/config.txt

Add the dtoverlay in this file (see the table above) and save your changes with ctrl + x. If you already see a line like dtoverlay=pwm... in the file, you can comment it out with a # at the start of the line, then add your own dtoverlay to a new line.

After saving the configuration you'll want to go back to your OctoPrint client to configure the plugin. Select the 'Use hardware timer for PWM' option, choose the appropriate GPIO pin, save your settings, and reboot to start using these settings.

Plugin Setup

Install via the bundled Plugin Manager or manually using this URL:

https://github.com/stealthmonkey99/OctoPrint-PWMBuzzer/archive/main.zip

Configuration

Once you have connected your passive buzzer to your Raspberry Pi and installed the plugin, launch the plugin settings dialog in your OctoPrint client to configure it.

Configuration Panel

From here you can enable the passive buzzer and indicate which GPIO pin the (+) side is connected to. You may want to play around with the Duty Cycle setting to see what works best for your buzzer. These buzzers won't sound great but they'll get the job done!

Optionally, you might also choose to enable a software buzzer that simulates M300 commands in your web browser while you're actively connected to OctoPrint. This has not been tested in all browsers yet, but you're welcome to try it out.

Once you have chosen your buzzer configuration settings you can test them out (hardware and/or software) using the "Play Default Tone" button. You can also set a default frequency and duration to be played any time an M300 command is encountered without parameters.

TROUBLESHOOTING: if you're not hearing the tone play on your speaker, make sure another plugin isn't attempting to configure the same GPIO pin.

Don't forget to save your settings before you continue!

What is Duty Cycle?

PWM applies an electrical signal on-and-off repeatedly, and the duty cycle describes how long the signal is "on" per each repetition. It depends on your specific buzzer, but it may make yours sound slightly smoother at 50% (a square wave, equal parts "on" vs. "off") vs. a lower percentage. Then again, you may not notice any change in the sound quality of your buzzer as you adjust and try out different duty cycle values.

Events

Here's where the magic happens... not only can your printer now handle M300 commands, but you can set up your OctoPrint instance to play music when certain events occur!

Events Panel

Next to each event you'll see a drop-down for selecting a preset or any .gcode files found in your local storage (not SD card) that contain M300 commands. Select whatever tune you'd like, then click "Try it" to play it. Keep in mind that you'll need to have saved your settings on the Configurations settings panel before trying to play these M300 commands.

NOTE: if you upload or save new .gcode files, you'll need to restart OctoPrint before they'll show up in the Events settings panel.

Composer

Feeling creative? Use the Composer settings panel to generate your own tunes for playback!

Composer Panel

Just press-and-hold any of the piano keys to hear them. When you release the key, it will save your "note" as generated Gcode. There are also some tools below the generated Gcode that you might find helpful:

Importing MIDI Files

NOTE: this feature is being newly introduced to version 1.1 of the plugin and is highly experimental. Try it out with your favorite MIDI files, but don't be too surprised if:

1) your imported tune sounds nothing like what you expected 1) your imported tune has the right melody but contains extra artifacts or unexpected tones 1) your file doesn't import at all

Feel free to file an issue if you encounter a reproducable problem, and be sure to include the file you're trying to import.

The MIDI file format provides a standard for sending data to MIDI devices, and is most often used for representing music by sending commands like "note on" and "note off". By importing a MIDI file, we can look for these music-related commands and turn them into M300 Gcode commands.

MIDI devices typically handle data for up to 16 channels. Often times authors will use different channels for each instrument (though this is not a strict requirement), so generally speaking you can consider each channel as being a separate instrument. As such, the plugin only supports importing a single channel at this time. After you select a file to import, you'll be shown a list of channels to pick from. If the MIDI file contains textual data or information about the suggested instrument to use for each channel, it will be displayed to help you in selecting the desired channel. If not, you may have to experiment and try importing different channels one at a time.

MIDI files can contain multiple tracks of data, and each track can include commands for multiple channels. Many times you will find that files utilize one track per channel (or sometimes one track for all channels), but occassionally you'll find data in multiple tracks for a given channel (e.g. left-hand vs. right-hand of a piano score). After you've selected a channel to import, you'll be shown a list of tracks associated with that channel. Pick one or more of the tracks and the data from all of your selected tracks will be merged during the import process.

The "Display Title" option just includes the MIDI file's name as an M117 command at the start of the generated Gcode. Similarly, if any of the MIDI tracks contain textual data these can be displayed as M117 commands with the "Display Track Text" option. Not all printers will have an LCD display or natively support M117 commands (check out my Status OLED plugin for a cheap alternative way to handle these), but it should be safe to include either way.

Since each channel often represents a single instrument, you might find that your desired channel doesn't start right away (e.g. if you select a melody channel that starts after an intro from other channels). "Ignore rest before first note in channel" allows you to skip the very first pause that would normally line the channel up with the others.

Most MIDI devices are polyphonic and support playing multiple notes at the same time, so imported files may contain data for notes that are started at the same time. M300 commands are monophonic as they are handled in serial and only support a single tone at one time. The "if chords are played" option lets you choose if the first or last note encountered should be given preference when generating tunes from the important data.

Finally, if you find the tune you generate is a little too slow (or too fast), you can use the "speed" slider to adjust the relative beats per minute (bpm) values when importing.

Try it out with this sample MIDI file:

https://github.com/stealthmonkey99/OctoPrint-PWMBuzzer/raw/main/assets/midi/plugins/pwmbuzzer/Twinkle.midi

Support & Contributing

This is my first OctoPrint plugin and it's still a bit experimental. Please feel free to open issues if you encounter any bugs. I'm also happy to take contributions if you'd like to open a pull request to make any changes.

I hope you find this useful and fun! If you like my plugin or want to support my random coding projects you can always Buy me a coffee

Enjoy!