Klipper3d / klipper

Klipper is a 3d-printer firmware
GNU General Public License v3.0
9.46k stars 5.31k forks source link

Request: Option to modulate PWM frequency with a static duty cycle instead. #2631

Closed emodeca closed 4 years ago

emodeca commented 4 years ago

I'd like to be able to control the frequency of a PWM signal rather than the duty cycle. This is for a piezo beeper, and from my limited understanding, you control volume with duty cycle and pitch with frequency (who'd have thunk Hz=>Hz). But with Klipper, I don't see a documented way to do this.

It's probably a limited use-case and should be a pretty low priority, but I don't see why it shouldn't be an option at some point. PWM can be used for all kinds of useful things, and giving klipper that extra flexibility may lead to some pretty interesting options.

klipper-gitissuebot commented 4 years ago

Hi @emodeca,

It did not look like there was a Klipper log file attached to this ticket. The log file has been engineered to answer common questions the Klipper developers have about the software and its environment (software version, hardware type, configuration, event timing, and hundreds of other questions).

Unfortunately, too many people have opened tickets without providing the log. That consumes developer time; time that would be better spent enhancing the software. If this ticket references an event that has occurred while running the software then the Klipper log must be attached to this ticket. Otherwise, this ticket will be automatically closed in a few days.

For information on obtaining the Klipper log file see: https://github.com/KevinOConnor/klipper/blob/master/docs/Contact.md

The log can still be attached to this ticket - just add a comment and attach the log to that comment.

Best regards, ~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

emodeca commented 4 years ago

klippy.log

Shhh, bot.

ld3300 commented 4 years ago

Did you try this? sample-macros.cfg

FHeilmann commented 4 years ago

the frequency can be adjusted by using the cycle_time configuration parameter, while the value you send to the pin corrresponds to the duty cycle.

emodeca commented 4 years ago

the frequency can be adjusted by using the cycle_time configuration parameter, while the value you send to the pin corrresponds to the duty cycle.

I understand that, but there doesn't appear to be a way with GCODE macros to alter the cycle_time that's set in the pin config.

Basically I would like to create a real M300, where S is the frequency and P is duration.

Currently, we can send an output "value" to the pin, which only affects the duty cycle. If instead we were able to adjust the cycle time from a gcode macro, we could send 50/50 duty cycle for maximum volume, and modulate the frequency to adjust the pitch of the beep.

emodeca commented 4 years ago

This could be resolved by adding letting CYCLE_TIME be declared in the macro. Then you could use a macro like this:

[gcode_macro M300]
default_parameter_S: 1000
default_parameter_P: 100
gcode:
    SET_PIN PIN=BEEPER VALUE=1 CYCLE_TIME=1/{S}
    G4 P{P} 
    SET_PIN PIN=BEEPER VALUE=0
ld3300 commented 4 years ago

How does that differ from the current implementation? If you want a 1k tone you would have:

[gcode_macro M300]
default_parameter_S: 1000    # frequency
default_parameter_P: 10        # duration
gcode:
    SET_PIN PIN=beeper VALUE={S}
    G4 P{P}
    SET_PIN PIN=beeper VALUE=0

What do you want the result of cycle_time to do?

KevinOConnor commented 4 years ago

It is not currently possible to perform constant duty PWM. An interested developer would need to implement it. It would require both micro-controller and host software development.

-Kevin

emodeca commented 4 years ago

How does that differ from the current implementation? If you want a 1k tone you would have:

[gcode_macro M300]
default_parameter_S: 1000    # frequency
default_parameter_P: 10        # duration
gcode:
    SET_PIN PIN=beeper VALUE={S}
    G4 P{P}
    SET_PIN PIN=beeper VALUE=0

What do you want the result of cycle_time to do?

That definitely does not work as intended. Modulating the duty cycle does not create a different frequency tone. It's creating a square wave with asymmetrical spacing between the peaks and valleys. This has the effect of "kinda" changing the pitch of the noise, with duty cycles below 50%, but anything above 50% will be nearly exactly the same pitch with a difference in distortion.

A true solution to modifying the pitch would be to use a constant 50% duty cycle and modulate the cycle time to create a different frequency square wave. This currently isn't possible.

I'm no developer, but I looked through the code a bit and it seems like klipper sets the cycle time at the time the output_pin is initialized. I hacked my way through klippy/extras/output_pin.py and was able to test a bit.

Seems like calling mcu_pin.setup_cycle_time() a second time causes an internal error of some sort. I have not dug farther than that, and although I have python experience, C is not something I have any familiarity with. If anyone more familiar with the codebase has an idea of how much C knowledge would be required for this, I'd much appreciate even a very ambiguous, "Eh, not much" or "more than you can handle."

Thanks!

ld3300 commented 4 years ago

Ahh,I see, thanks. Wish I had the ability to help out.

emodeca commented 4 years ago

When I have time, I'll look into this and hopefully be submitting a PR at some point down the road.

Thanks for your help, everyone.