xblax / flashforge_ad5m_klipper_mod

Unoffical mod for Flashforge Adventurer 5M (Pro) 3D printers to run Moonraker, custom Klipper, Mainsail & Fluidd
GNU General Public License v3.0
92 stars 5 forks source link

Buzzer support #20

Closed xblax closed 2 months ago

xblax commented 3 months ago

Discussed in https://github.com/xblax/flashforge_adm5_klipper_mod/discussions/15

The integrated buzzer should be usable for the mod, i.e. to notify print end or errors.

This could be done via a standalone executable or python script that is called from Macros as a G-Code shell command: https://github.com/dw-0/kiauh/blob/master/docs/gcode_shell_command.md

consp commented 3 months ago

Sample python code for single tone:

note: controller number and pwm device might differ. Mine is pwm6.

from time import sleep

fenable = open("/sys/class/pwm[controllerid]/pwm[0-6]/enable", "w")
fperiod = open("/sys/class/pwm[controllerid]/pwm[0-6]/period", "w")
fdc = open("sys/class/pwm[controllerid]/pwm[0-6]/duty_cycle", "w")

frequency = 1000

fperiod.write("%d" % (1000000000 // frequency))
fdc.write("%d" % ((1000000000// freqeuency) / 2))
fenable.write("1")
sleep(1.0)
fenable.write("0")
consp commented 3 months ago

Since I have to wait for input from others on the klipperscreen (it works for me, but n=1) I'll pick this one up.

xblax commented 3 months ago

Thanks, that's great! I think a standalone tool to play some simple tones would do. Could be a shell script, python or compiled. This can be called from Klipper via G-Code shell extension, eventually.

Or you can also go fancy and implement some jingles, but that's optional :grinning:

consp commented 3 months ago

I have some python code somewhere which converts midi notes to frequencies, should be adaptable to add some time duration in there, hopefully it will not overload the pwm device.

I'll stick with python, that way if anyone writes a script they can include it and it's mostly compatible with everything available (klipper/klipperscreen/moonraker).

xblax commented 3 months ago

Yes that's a good idea. Maybe you can try to play the jingles compiled into Flashforge play to see what the device is capable of.

consp commented 3 months ago

Yes that's a good idea. Maybe you can try to play the jingles compiled into Flashforge play to see what the device is capable of.

Those are int32[count][2] frequency / duration lists of about max 48 entries (for the beethoven version). Nothing too special. They are "slow" though as normal music is a bit faster. I think the limitation of the pwm driver will determine the final outcome.

I already tried higher frequency modification but it chokes after about a second. And that was at about 10 samples/s (wave converted to very simple frequency/duration list). My guess would be one frequency change/s, which would be ok for a single tone midi file.

If it turns out to be a gpio port or a timer who knows what is possible.

On another note, the device tree description file says the i2s ports are disabled, guess they aren't planning on adding real audio. Also the pwm7 looks match the backlight unless I got lost in the dts file, but I'm not sure it's controllable. Makes sense since it's configurable to be next to the lcd[x] output pins.

KaruroChori commented 3 months ago

Also the pwm7 looks match the backlight unless I got lost in the dts file, but I'm not sure it's controllable.

Good! I tried earlier to use the more standard black, but it was not configured to affect the backlight. With that channel I guess I can finally fully turn off the screen :D

consp commented 3 months ago

No guarantees though that it works. The dts file does not say if it is blocked by the lcd driver or not (simply that it uses pwm channel 7 and the PD22 pin is muxed next to the LCD pins) .

consp commented 3 months ago

https://github.com/xblax/flashforge_adm5_klipper_mod/assets/6802998/77d5d7a0-1426-4506-bbe5-5e83e7d84bda

Well that was a fun excersize. No polytones of course.

Will be something like:

audio.py [midifile] [midi track] [midi instrument]
or 
audio.py [frequency] [duration]

Don't use excessive midi files, they get loaded into memory and explode easilly. Midi files must be oldschool and no fancy tempo changes (as in tempo is determined by time index like it used to be). Modern midi files contain bloat on track 0 so usually track 1 is the one you want (or even higher ones). Needs a bit of work, it's a code mess now.

xblax commented 3 months ago

That's nice :D Can it run with the python in the host system too? We could include it with the install script to play some nerdy level up sound after installing the mod.

consp commented 3 months ago

That's nice :D Can it run with the python in the host system too? We could include it with the install script to play some nerdy level up sound after installing the mod.

"Funny" thing is that the midi on the host is way more complicated, especially on linux (alsa screws things up). So unfortunately no(t yet at least). It requires only a python-only midifile reader and some basic file code (kiss principle), doing proper audio is another thing though I would not be surprized if modules exist for it which make it easy.

xblax commented 3 months ago

"Funny" thing is that the midi on the host is way more complicated, especially on linux (alsa screws things up). So unfortunately no(t yet at least). It requires only a python-only midifile reader and some basic file code (kiss principle), doing proper audio is another thing though I would not be surprized if modules exist for it which make it easy.

Not sure you mean the same thing. With the host system I was thinking using it outside of the chroot, i.e. while the flashforge_init.sh runs. If the script only uses /sys/class/pwm that should work, right? But the flashforge linux has an holder python version.

consp commented 3 months ago

"Funny" thing is that the midi on the host is way more complicated, especially on linux (alsa screws things up). So unfortunately no(t yet at least). It requires only a python-only midifile reader and some basic file code (kiss principle), doing proper audio is another thing though I would not be surprized if modules exist for it which make it easy.

Not sure you mean the same thing. With the host system I was thinking using it outside of the chroot, i.e. while the flashforge_init.sh runs. If the script only uses /sys/class/pwm that should work, right? But the flashforge linux has an holder python version.

Ah, I was thinking host as in buildroot host dir (so build). Then yes, as long as python is available and the two wheels will be installed (midifile and audio). It only needs python basics. Might need to expose the pwm driver first, will add that check later.

https://github.com/consp/flashforge_adm5_audio repo for now. We can build the wheel from there. Note: requires pip >= 22 (no setup.py yet) to build wheels.

Anything over python 3.6 might work but 3.8 and up is prefered and set as requirement.

xblax commented 3 months ago

Maybe we can just add the dependencies to the buildroot pyhton as a buildroot package and add the audio.py in the overlay. Could be easier.

consp commented 3 months ago

The wheel will install it as "audio" command if I set it up correctly. But it's trail and error for now. Could be put into buildroot as well, doesn't really matter as long as it ends up somewhere on the system.

xblax commented 3 months ago

I did a short test of that tool yesterday, seems to work great! Do you want to integrate it directly on the master branches? Then we can have it in for public beta, which would be nice.

I think the dependencies could be added just like the other python packages that are available in buildroot. Example: https://github.com/buildroot/buildroot/tree/master/package/python-midiutil

I had some troubles finding monophonic midis. Do you have a good resource for that? I tried merging the tracks of a few midi-files automatically, but that did not really work well.

consp commented 3 months ago

Do you want to integrate it directly on the master branches? Then we can have it in for public beta, which would be nice.

That's the plan, I'll create a new feature branch which is based of master. Should work in the next few days.

consp commented 3 months ago

Do you have a good resource for that?

not really, used this one (level1.mid, track 0, channel 1). It's hit or miss unfortunately. Might implement some more automation into it to get a bit more compatability. If you have a song and can find the main instrument, it's -usually- instrument number - 1 as channel.

consp commented 3 months ago

It's been improved, now only requires the channel to play (looks for the right track to play from) and also does pitch changes, disabled the pwm channel on error (otherwise it's reaaaaaaaly annoying) and checks if the device is exposed in sysfs.

since it can only play one voice, you sometimes have longish starting rests for instruments (example file has this below). Check if you can find the piano or accordion channel which usually have to most tone.

use --verbose if you want to see what's going on. Note: rest is a 'message rest' not necessarily a tone rest.

python3 audio.py midi -m kkrikwnd.mid  -p 6 -c 2
Loading kkrikwnd.mid ...
Copyright  MIDI Sequence ©2005 Neo Chaotikal. Original music is property of Nintendo.
Track:  The Legend of Zelda - Ocarina of Time: Kakariko Windmill
Track:  Tremolo Whistle

switched to mido for midi file reading, as mido is a bit bloatier in code but more memory efficient and a lot easier to work with

https://github.com/consp/flashforge_ad5m_audio added it to pypi: https://pypi.org/project/ff-ad5m-audio/

Should be easier to use then

consp commented 3 months ago

I had some troubles finding monophonic midis

e.g. https://www.midi-karaoke.info/2161d46d.html or https://www.khinsider.com/midi/nes/super-mario-bros. (e.g. overworld)

In practice most quartet or duet classic music will work if the viola or piano is the leading instrument. Simpeler is better so 'classic' 8 bit music might do.

I'll release a fix later which solves the "long wait at start" problem in some tracks.

consp commented 3 months ago

The v00.02 klipperscreen pre-release package includes the library and can be tested.

I'm thinking of making a script wrapper to avoid having to start python on a simple frequency buzzer.

xblax commented 2 months ago

I added the python modules for audio to the build root master branch. I think it's ok to start python for the buzzer, it should not be needed anyway during critical phases. Probably at print end / pause, maybe on printer startup.

consp commented 2 months ago

Should be a bit better in the next version as well. I shifted some stuff around and some parts are lazy loaded now which will speed the simple functions up.

consp commented 2 months ago

I'll have a look into adding some sound like with post-printing.

consp commented 2 months ago

added branch feature/m300 contains the m300 macro and play_midi macro and added a beep on cancel_print and completion sound on end_print.

xblax commented 2 months ago

Will test it this evening! But I noticed two things by looking at the commit:

Macro CANCEL_PRINT is already defined in client.cfg (Generic Macros from Mainsail/Fluidd). It should not be redefined, but you could change variable_user_cancel_macro to add something to _COMMON_END_PRINT that is specific to cancellation.

Is it a good idea if audio (especially) Midi is run in sync with the command execution? I made the LCD Macros I added yesterday run in background. But I think I have to refactor them, because now Gcode can run arbitrary shell functions, which isn't that great ...

consp commented 2 months ago

Ah, yes that is a better idea. Probably should run them as background processes, I'll have a look.

consp commented 2 months ago

will use setsid to create a background task like this: command: setsid audio. This will avoid random program execution while still getting a background task, and as a bonus not needing the ampersand.

the M300 command is synchronous as it is like that on other machines as well (afaik)

Converted the CANCEL print as well.

consp commented 2 months ago

Since the macro's have been added to master I guess the issue is closed.

xblax commented 2 months ago

I had to move the Midi files folder to /usr/share The /root/printer_software folder is removed by the post build script, before installing the components, therefore anything in the overlay at that location did not end up in the chroot.

https://github.com/xblax/flashforge_adm5_klipper_mod/commit/91f891fc97687798ed10a64ca2a40b7cb446cd0f

consp commented 2 months ago

The /root/printer_software folder is removed by the post build script

:facepalm: That explains the issues I had yesterday but it was late and thought I made a different mistake.

xblax commented 2 months ago

@consp That latest commit you did today is not correct: https://github.com/xblax/flashforge_adm5_klipper_mod/commit/d56e065ee7d3b6991722b5924ab57747933eeaa1

I enabled the -f switch intentionally and enabled the setsid from utils-linux in buildroot: https://github.com/xblax/flashforge_adm5_buildroot_chroot/commit/6e7073cbcbb39dabb95161331d187b014f447db8

Reason for this that busybox setsid seems to not fork into background.

consp commented 2 months ago

Hmm, revert is then in order (sorry). But the bigger problem is then why a clean rebuild did not build the buildroot (yes I also merged that master and redid the config) correctly. Could be I did something wrong but I'm pretty sure I rebased everything from master, will check tonight what went wrong since it might also be wrong in the klipperscreen build. Good reason to look into the method for building/patching buildroot to keep it more centralized.

Reason for this that busybox setsid seems to not fork into background.

I had no issues with it and it. Afaik it always forks if you are not the group leader (which the process most likely is not).


fixed by ignoring the commit.