Beeper sounds wrong

Hello, I’ve been trying to implement a couple of M300 tones for when the print starts and ends.

Basically, I take a MIDI file and run it through a converter to get the M300 values.

I can preview the result in the converter and it sounds fine. It also sounds fine when tested with Marlin firmware. But when I try to play the same tones (same gcode) using Klipper they sound completely different. The timing appears to be correct but the pitch is totally wrong. I don’t expect it to be pitch-perfect, but at least as good as the demo linked below.

I’ve set up the M300 macro according to sample_macros.cfg:

[gcode_macro M300]
gcode:
    {% set S = params.S|default(1000)|int %} # Use a default 1kHz tone if S is omitted.
    {% set P = params.P|default(100)|int %}  # Use a 10ms duration is P is omitted.
    SET_PIN PIN=BEEPER_pin VALUE=0.5 CYCLE_TIME={ 1.0/S if S > 0 else 1 }
    G4 P{P}
    SET_PIN PIN=BEEPER_pin VALUE=0

This is the converter I’m using https://alexyu132.github.io/midi-m300/
Github: https://github.com/alexyu132/midi-m300
Demo: https://www.youtube.com/watch?v=gurSmmTxVug

just for info, for the beeper_pin u set it to use soft_pwm right? (#hardware_pwm: False well default should be false)

i guess it might be the limitation of soft_pwm. i dont know how marlin does this, if they change the hardware cycle time wich can be done.

1 Like

This is how I’ve configured it:

[output_pin BEEPER_pin]
pin: EXP1_1 # Beeper pin. This parameter must be provided.
pwm: True # A piezo beeper needs a PWM signal, a DC buzzer doesn't.
value: 0 # Silent at power on, set to 1 if active low.
shutdown_value: 0 # Disable at emergency shutdown (no PWM would be available anyway).
cycle_time: 0.001 # Default PWM frequency : 0.001 = 1ms will give a tone of 1kHz (not pitch perfect).

Should I just add hardware_pwm: False after pwm: True?

Did you ever get this figured out? I have the same problem with the same pin and m300

@iCach0 and @exo316 you could record the sounds produced and post it here and/or measure the signal at the beeper, if you have access to an oscilloscope.

Same problem here.
My beeper pin is the gpio17 from raspberry pi connected to the beeper pin in the MKS TS35 screen

[mcu rpi]
serial: /tmp/klipper_host_mcu

[output_pin BEEPER_Pin]
pin: rpi:gpio17
pwm: True

@iCach0 @exo316 have you figured out how to solve it?

Hello @thiagosalles !

From: Configuration reference - Klipper documentation

#pwm: False
#   Set if the output pin should be capable of pulse-width-modulation.
#   If this is true, the value fields should be between 0 and 1; if it
#   is false the value fields should be either 0 or 1. The default is
#   False.

Thanks @EddyMI3D

You mean my problem is that the pin I’m using doesn’t support PWM, right?

From the little I’m understanding, the raspberry pins that support PWM are the GPIO12 and GPIO13 pins.

Do you think that if I just change the connection from GPIO17 to one of those I can solve my problem?

I mean you have to tell the pin what to do.
This is my beep macro:

[output_pin BEEPER_pin]
pin: PC0
pwm: True
value: 0
shutdown_value: 0
cycle_time: 0.001
scale: 2000

Edit:

Forgot to attach this:

[gcode_macro M300]
gcode:
  {% set S = params.S|default(1000)|int %}
   #default_parameter_S=1000
  {% set P = params.P|default(100)|int %}
   #default_parameter_P=100
  SET_PIN PIN=BEEPER_pin VALUE={S}
  G4 P{P}
  SET_PIN PIN=BEEPER_pin VALUE=0

Thanks, @EddyMI3D

I had already configured both the pin and the macro, but it didn’t work.
I tried with the same configuration you provided, but it still don’t work.

this is the gcode I’m trying to play:

[gcode_macro TREASURE_CHEST]
gcode:
    M300 P123 S196
    M300 P123 S220
    M300 P123 S247
    M300 P123 S277
    M300 P123 S196
    M300 P123 S220
    M300 P123 S247
    M300 P123 S277
    M300 P123 S208
    M300 P123 S233
    M300 P123 S262
    M300 P123 S294
    M300 P123 S208
    M300 P123 S233
    M300 P123 S262
    M300 P123 S294
    M300 P123 S220
    M300 P123 S247
    M300 P123 S277
    M300 P123 S311
    M300 P123 S220
    M300 P123 S247
    M300 P123 S277
    M300 P123 S311
    M300 P123 S233
    M300 P123 S262
    M300 P123 S294
    M300 P123 S330
    M300 P123 S233
    M300 P123 S262
    M300 P123 S294
    M300 P123 S330
    M300 P123 S247
    M300 P123 S277
    M300 P123 S311
    M300 P123 S349
    M300 P123 S262
    M300 P123 S294
    M300 P123 S330
    M300 P123 S370
    M300 P123 S277
    M300 P123 S311
    M300 P123 S349
    M300 P123 S392
    M300 P123 S294
    M300 P123 S330
    M300 P123 S370
    M300 P123 S415
    M300 P492 S0
    M300 P246 S880
    M300 P246 S932
    M300 P246 S988
    M300 P738 S1047

It’s the same gcode used in the video provided by the developer of the tool, liked by @iCach0 in the main posting.

Here is how it sounds on my machine:

The main issue is the timing. Marlin uses 260hz at 1ms. All the macros I found are only 2khz by default. You would have to modify the freq and duration. I’m working on matching it. If I get it right I will share.

[gcode_macro M300]
gcode:
       # Use a default 1kHz tone if S is omitted.
       {% set S = params.S|default(260)|int %}
       # Use a 10ms duration is P is omitted.
       {% set P = params.P|default(100)|int %}
      SET_PIN PIN=BEEPER VALUE=0.5 CYCLE_TIME={ 1.0/S if S > 0 else 1 }
       G4 P{P}
      SET_PIN PIN=BEEPER VALUE=0

Matches Marlin in speed and tone.

2 Likes

If one day I stop my quest to mechanical precision and print quality I might add a beeper to my printer

But honestly: I applaud your commitment to hunt for the “perfect beeper” :slight_smile:

The community got me this far, I will continue to help the community the best I can.

Here we go my 50 cents. I’ve made some tones and we can select each one with parameters

[gcode_macro PLAY_TONE]
gcode:
     {% set l = params.L|default(0)|int %}

   {% if l == 1 %} ; play first tone #Here we go
     M300 P184 S392
     M300 P184 S523
     M300 P187 S659
     M300 P417 S784
     M300 P139 S659
     M300 P400 S784  

   {% elif l == 2 %} #play second tone #Mario Death
     M300 P146 S494
     M300 P97 S698
     M300 P157 S0
     M300 P132 S698
     M300 P174 S698
     M300 P168 S659
     M300 P176 S587
     M300 P134 S523
     M300 P95 S330
     M300 P31 S0
   
  {% elif l == 3 %} #play second tone #MarioWorld start theme
    M300 P100 S659
    M300 P200 S659
    M300 P99 S659
    M300 P101 S0
    M300 P100 S523
    M300 P99 S659
    M300 P101 S0
    M300 P199 S784
    M300 P201 S0
    M300 P199 S392

   {% elif l == 4 %} #play third tone #Ode to joy
    M300 P353 S330
    M300 P353 S330
    M300 P353 S349
    M300 P353 S392
    M300 P353 S392
    M300 P353 S349
    M300 P353 S330
    M300 P353 S294
    M300 P353 S262
    M300 P353 S262
    M300 P353 S294
    M300 P353 S330
    M300 P529 S330
    M300 P176 S294
    M300 P706 S294

   {% else %}
     M300 P100 S0 #play nothing
   {% endif %} 

wellerman_1.gcode (12.6 KB)
Try this one… it plays ok, on mine… the key was to add the G4 in the converter… happy music. (oh by the way, I also found with calling aplay you can play .wav files on the host) instead of using the beeper

pin: PB15
pwm: True
value: 0
shutdown_value: 0
cycle_time: 0.001
[gcode_macro M300]
gcode:
    # Use a default 1kHz tone if S is omitted.
    {% set S = params.S|default(1000)|int %}
    # Use a 10ms duration is P is omitted.
    {% set P = params.P|default(100)|int %}
#    SET_PIN PIN=Case_Light VALUE=0
#    SET_PIN PIN=LCD_Light VALUE=0
    SET_PIN PIN=_BEEPER_pin VALUE=0.5 CYCLE_TIME={ 1.0/S if S > 0 else 1 }
#    SET_PIN PIN=Case_Light VALUE=0.5 CYCLE_TIME={ 1.0/S if S > 0 else 1 }
#    SET_PIN PIN=LCD_Light VALUE=0.5 CYCLE_TIME={ 1.0/S if S > 0 else 1 }
    G4 P{P}
    SET_PIN PIN=_BEEPER_pin VALUE=0
#    SET_PIN PIN=Case_Light VALUE=1
#    SET_PIN PIN=LCD_Light VALUE=1
# End Macro M300

here is my config… fyi, I had set it to blink the lights too but I found fancier ways of doing the lights, so are commented out at them moment.

1 Like

Thank you DaVinci10, I made a change to the code to take out the extra beeps I was hearing on my machine. You can’t have a cycle time of 0, which would be silent anyway, so anytime S is 0 I just have it do the dwell time for the pause.

Here is the updated code:

[gcode_macro M300]
gcode:
    # Use a default 1kHz tone if S is omitted.
    {% set S = params.S|default(1000)|int %}
    # Use a 10ms duration is P is omitted.
    {% set P = params.P|default(100)|int %}
      #SET_PIN PIN=Case_Light VALUE=0
      #SET_PIN PIN=LCD_Light VALUE=0
    {% if S > 0 %}
      SET_PIN PIN=BEEPER_Pin VALUE=0.5 CYCLE_TIME={ 1.0/S }
      #SET_PIN PIN=Case_Light VALUE=0.5 CYCLE_TIME={ 1.0/S }
      #SET_PIN PIN=LCD_Light VALUE=0.5 CYCLE_TIME={ 1.0/S }
      G4 P{P}
    {% else %}
      G4 P{P}
    {% endif %}
      SET_PIN PIN=BEEPER_Pin VALUE=0
      #SET_PIN PIN=Case_Light VALUE=1
      #SET_PIN PIN=LCD_Light VALUE=1
# End Macro M300
1 Like

nitpick:

you don’t need the else here right? just put G4 outside

{% if S > 0 %}
    SET_PIN PIN=BEEPER_Pin VALUE=0.5 CYCLE_TIME={ 1.0/S }
{% endif %}
G4 P{P}
1 Like