Open Everlanders opened 6 years ago
Last night I built 2 variations of these sensors, one using IR and one using a modified flow meter.
https://photos.app.goo.gl/Oumt1j2d1gzG0ZQC2
The flow meter just has it's paddles clipped off and replaced with a rubber grommet that acts as a pulley, grabbing the filament on 3 sides. The IR is better because it has more pulses per revolution - the flow meter only has 2.
The Arduino counts the pulses every 30 seconds and if less than 1, opens the relay which is wired to the stock filament sensor. This is less than ideal because you need to jumper the relay to get it started. Would be better if the plugin could watch for it only while printing.
I feel like using an encoder and checking if it is sniping is the best choice. right now I don't have the time for anything really on this plugin, I'll put on the road map, but what you can defenetlly do, is create a sensor, with an arduino pro mini, or just a bare ATtiny and program the sensor logic on it, if it stop sensing it would set a pin high or low, and one input pin to enable or disable the sensor. On the plugin side, you configure the output of the sensor as a regular filament sensor, and on the enable / disable pin configure it as an output on the plugin and to start it when the print starts.
Version 3:
https://photos.app.goo.gl/L3ogR4uD734MpQl22
I've got a small Arduino dealing with it, but I thought it would be a useful thing for others, more plug and play.
Thanks again!
Are you using the ir sensor? have a link for the parts?
You bet! eBay Link
In case that listing/link doesn't work in the future, search for Slot Type IR Optocoupler Speed Sensor Module LM393 for Arduino
How about the wheel? We would need to make a instruction on how to create the sensor, and document parts etc... I have access to a laser cutter and can create a wheel, but not everyone has...
I salvaged it from a Roomba, but it could easily be 3D printed. I can make a video if the plugin supports it. ;-)
I'll put together some files tonight.
These are even nicer...
The MK4duo firmware has this option already installed (for up to 6 extruders) called Extruder Encoder Control. We have not tested it, but they say it works.
I'm working on the same type of enhancement, and have purchased a couple of small magnetic encoder sets: https://www.pololu.com/product/3081 They're intended for small motors, but I think I can build a small enclosure that could be used like a typical filament sensor, or perhaps contact the spool itself to detect motion there. Monitoring the spool would put the detection farther from the extruder, which is often a good thing.
There has to be a configurable delay before activating the sensor when the print starts, because the filament won't move during things like homing, bed leveling, etc. that typically occur at the beginning of a print. So (as you noted above) this new input type would also need a "startup delay" option like the outputs already have.
Another option might be to add an input type that is able to monitor either the output of a shell script, or the presence of a particular file. That would enable us to use the Pi's IO capabilities for this sort of thing, instead of having to set up another control system.
Probably the best to implement is not a delay, because you would need to tweak the time to get it just right, I think the best implementation is "after the first change" on the encoder the filament sensor is activated, and a timeout of some minutes if it does change at all to catch you starting a print with a jammed extruder. BUT don't have a nice setup to test and implement and I have been spending a lot of money on other projects that I'm working, so I don't plan to buy new encoders / sensors to implement this, if someone works a decent prototype for a filament sensor with encoders and ship it to me I'll gladly take the time to implement, but if not we will have to wait until I finish current projects....
I bought extra encoder sets. If I come up with something interesting, I'll send you one.
Here's a shell script that can be run on the Raspberry Pi, and triggered by an Enclosure Plugin action if desired. Working on a couple of different hardware solutions, one that tracks the filament itself (like a traditional switch-based filament sensor) and another that monitors spool movement. Will post details later. Both are Hall effect rigs, but any Pi-compatible pulsing output (optical, mechanical, etc.) could be used with this script.
Update 7/25: I discovered that the "inotifywait" command is unreliable for monitoring RPi GPIO status. Long story, but I rewrote the script using a subroutine that does the job without incurring much CPU overhead at all. Still need to convert it to python.
Update 7/31: Added a pre-pause check to query OctoPrint for the tool0 set point. If that is 0.0, the script assumes the print is finished and in cool-down mode, so it exits. Still need to convert it to Python...
Update 8/29: Modified the script to accept a timeout value on the command line, so you can specify the timeout in the Enclosure Plugin script action. Also added a wrapper script, which starts the main script in the background and returns info to EP.
Main script:
#!/bin/bash # # /home/pi/FilamentMonitor.sh -- Jon L. Gardner, jon@brazoslink.net # # Monitors a Raspberry Pi GPIO input for pulses from a filament motion sensor. # Triggers a print pause via OctoPrint API, and optionally notifies via IFTTT. # select RPi input pin to monitor for motion sensing GPI=5 # OctoPrint API key apikey=YOUR_OCTOPRINT_API_KEY # IFTTT API key and event name (from Enclosure Plugin settings) ifttt_key=YOUR_IFTTT_API_KEY ifttt_event=YOUR_IFTTT_EVENT_NAME # should not need to change anything below this line, unless you want a different default timeout # set timeout in seconds timeout=$1 if [[ ! $timeout ]]; then /bin/echo "Warning: No timeout specified, defaulting to 30s." timeout=30 else /bin/echo "Timeout set to ${timeout} seconds." fi # prepare the pins IO=/sys/class/gpio if [[ $GPI ]]; then /bin/echo "Configuring input on BCM ${GPI}." if [ ! -d $IO/gpio${GPI} ]; then /bin/echo "${GPI}" > $IO/export fi /bin/echo "in" > $IO/gpio${GPI}/direction else /bin/echo "Error: No GPIO pin specified!" exit 1 fi function trap_ctrlc () { /usr/bin/printf "\nLongest pulse time was $maxtime seconds.\n" exit 2 } function monitor_gpio () { ok=0 exp=0 val1=$(/bin/cat $IO/gpio${GPI}/value) while [[ $ok = 0 ]]; do val2=$(/bin/cat $IO/gpio${GPI}/value) if [[ $val1 != $val2 ]]; then val1=$val2 ok=1 exp=0 fi if [ $init == 0 ]; then ctime=`/bin/date +%s` etime=`/usr/bin/expr $ctime - $stime` if [ $etime -gt $timeout ]; then ok=1 exp=1 fi fi sleep 0.2 done } function check_print_status () { # query OctoPrint for the main tool setpoint done=0 setpoint=`/usr/bin/curl -s -H "X-Api-Key: "$apikey"" http://localhost/api/printer | /bin/grep -A3 tool0 | /bin/grep target | /usr/bin/cut -f2 -d:` # if 0.0, assume the print is done if [ $setpoint = 0.0 ]; then done=1 fi } trap "trap_ctrlc" 2 init=1 maxtime=0 while : do if [ $init == 1 ]; then # wait for the first change before starting the timer /bin/echo "Monitoring BCM ${GPI} for initial filament movement..." monitor_gpio /bin/echo "Initial pulse detected." /bin/echo "Monitoring with timeout of $timeout s..." init=0 fi # once things are moving, detect if things stop moving for longer than the timeout stime=`/bin/date +%s` monitor_gpio if [ $exp == 1 ]; then /bin/echo "Filament has stopped moving." check_print_status if [ $done == 0 ]; then # pause the print via OctoPrint API (assumes localhost) /bin/echo '{"command": "pause" , "action": "pause"}' | /usr/bin/curl -s -X POST -d @- -H "X-Api-Key: "$apikey"" -H "Content-Type: application/json" http://localhost/api/job > /dev/null # notify via IFTTT if [[ $ifttt_key ]]; then /bin/echo '{"value1": "Printer paused by filament motion sensor." , "value2": "Longest pulse delay '$maxtime' s."}' | /usr/bin/curl -s -X POST -d @- -H "Content-Type: application/json" https://maker.ifttt.com/trigger/$ifttt_event/with/key/$ifttt_key > /dev/null fi # wait for the timeout period, then start over /bin/echo "Pausing $timeout s for reset..." /bin/sleep $timeout init=1 else # assume the print is finished, and exit echo "Print appears to be finished." trap_ctrlc fi else # maintain record of longest pulse time ftime=`/bin/date +%s` ttime=`/usr/bin/expr $ftime - $stime` /usr/bin/printf "." if [ $ttime -gt $maxtime ]; then maxtime=$ttime fi fi done
Wrapper script:
#!/bin/bash # # /home/pi/startFM - wrapper script for FilamentMonitor.sh # # set log file path to whatever you want LOG=/home/pi/fm.log # kill any running FilamentMonitor processes while : do pid=`ps ax|grep -v grep|grep FilamentMonitor|cut -c1-5` if [[ $pid ]]; then sudo kill $pid else break fi done # set timeout from command line timeout=$1 if [[ ! $timeout ]]; then timeout=30 fi cd /home/pi # to monitor progress, ssh to the OctoPi and "tail -f" your log file nohup ./FilamentMonitor.sh $timeout > $LOG & echo "FilamentMonitor started (PID $!) with ${timeout}s timeout." echo "Logging to $LOG"
Example Enclosure Plugin output config:
@jlg89 thanks for the script, despite is helpful as a general guide on how to implement, if you can convert it to python it would be much more helpful, because it would be easier to port.
Also, python has some nice features for the GPIO, like interrupts for the pins, making easy to get exact time that the GPIO change status.
@vitormhenrique if you can give me a shipping address, I'll send you one of the pulse-generating filament sensors I built.
Here's a PDF writeup on a couple of filament motion sensors I've put together.
@jlg89 send me an email on the email linked to my profile and I'll give you my address....
@jlg89 Thanks for that writeup, you should make a new repo for it! I just bought a few of the https://www.pololu.com/product/3081 sets to try to use your enclosure with a Duet board.
OK...finally, here's my first shot at a Python version of the script. This is incomplete, missing the printer pause & notification actions, but the basic pulse input detection is there.
#!/usr/bin/env python2.7 import sys import time import urllib2 import json from collections import namedtuple import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) CHAN=5 TIMEOUT=30 OCAPIKEY='your_OctoPrint_API_key' GPIO.setup(CHAN, GPIO.IN, pull_up_down=GPIO.PUD_UP) global MOV MOV=0 RUN=0 DONE=0 # increment MOV at every state change of the monitored channel def my_callback(channel): global MOV MOV += 1 GPIO.add_event_detect(CHAN, GPIO.BOTH, callback=my_callback, bouncetime=300) def PrintDone(apikey): # check OctoPrint API for main tool set temp, if 0.0 assume job finished url="http://localhost/api/printer/tool?apikey={0}".format(apikey) response = urllib2.urlopen(url) html = response.read() x =json.loads(html, object_hook=lambda d: namedtuple('X', d.keys())(*d.values())) tempt=x.tool0.target if tempt==0.0: return 1 else: return 0 try: while DONE==0: MOV=0 RUN=0 print('Waiting for initial pulse.') # GPIO event detect will increment MOV while RUN==MOV: # wait for initial pulse time.sleep(.1) print('Pulse detected.') # monitor I/O for state changes while True: start_time = time.time() MOV=0 RUN=0 # output a dot at each state change sys.stdout.write('.') sys.stdout.flush() while RUN==MOV: if time.time() - start_time > TIMEOUT: print('Filament has stopped moving.') if PrintDone(OCAPIKEY): print('Print appears to be finished.') DONE=1 break # timeout actions go here -- pause print, notify via IFTTT etc. break except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit
Really nice, are there any more progress? Will be available into the plugin soon?
Hi. I'm going to play with the script @jlg89 posted (thanks!), but wondering what the status of this functionality is in the main plugin? Thanks!
The status is really really low priority, I started masters on computer science and have been busy with other projects, I plan to re-write the entire base Conde of the plugin to make it easier to understand and expand, so maybe more people would be able to push commits. I wanna re-write the code with a better objected oriented mentality and add some of the features that are more commonly requested. Unfortunately it's not the case of this. One day I might get to this and figure a way to implemented, but honestly is not on a close road map.
I have a CR10s that I got to print some large ABS parts and really love this plugin, thanks.
I am however having problems with the filament jamming for unknown reasons, it's not tangled, it's just not moving, the gear has chewed a hole in the filament halfway through the night and it's air-printing. Frustrating because it had been printing fine for 20 - 30 hours. I have 11 failed prints like this and I have an idea that I think will be simple to implement.
There are many ways to sense filament movement, the easiest being a cheap hall effect sensor on a wheel or a IR sensor on a pinwheel - I intend to modify a flow meter for water once I finish typing this message, but they mostly all use pulse output.
It would be very helpful if there was an option to monitor a pin for these pulses and when they stop, pause the print just like the loss of filament detection. Just one option, How long to wait after last state change.
Thank you.