A 3D printer was obtained and built. Printing however required either a laptop tethered to the machine, or printing from SD card which is difficult to supervise. The panel control is also annoying.
Some functionality also requires running scripts directly communicating with the printer controller. Additional sensors and tools also may have to be attached, and easy changes of tools are needed.
A standalone server, capable of feeding G-code to the printer, and also running all sorts of scripts directly communicating with the controller, was desired.
A Raspberry Pi board was sacrificed to the 3D printing gods. Minibian distro was used as the basis of the system, with OctoPrint as the printer control software.
The Minibian image was downloaded and written to a 8GB SD card (4GB would be enough, though). The board with the card was attached to the Ethernet network and powered up. Default password "raspberry" was used to log in as root.
The card was repartitioned to this result:
Device Boot Start End Blocks Id System /dev/mmcblk0p1 16 97727 48856 b W95 FAT32 /dev/mmcblk0p2 97728 14900000 7401136+ 83 Linux /dev/mmcblk0p3 14900001 15759359 429679+ 82 Linux swap / Solaris
fdisk /dev/mmcblk0
...and then issue commands
d 2
n
<cr>
2
<cr>
14900000
n
<cr>
3
<cr>
<cr>
t
3
82
w
q
The computer was rebooted with the new partition table, and the filesystem was resized to its full size:
resize2fs /dev/mmcblk0p2
The SSH key was added to the card.
mkdir .ssh
cd .ssh;wget http://<wherever_they_are>/authorized_keys; chmod 600 authorized_keys;cd
Now set up the basics:
apt-get update
apt-get install mc strace usbutils sudo lsof psmisc raspi-gpio wiringpi mlocate setserial apt-file tcpdump tshark
apt-get install python git
install pip: https://pip.pypa.io/en/latest/installing/
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
(Newer systems do not require installing pip separately.)
got:
/tmp/tmpTgcbsP/pip.zip/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
pip install requests[security]
got failure after a while with gcc not available, so...
apt-get install gcc
tried again,
pip install requests[security]
and got
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -DUSE__THREAD -I/usr/include/ffi -I/usr/include/libffi -I/usr/include/python2.7 -c c/_cffi_backend.c -o build/temp.linux-armv6l-2.7/c/_cffi_backend.o
c/_cffi_backend.c:2:20: fatal error: Python.h: No such file or directory
compilation terminated.
error: command 'gcc' failed with exit status 1
so did
apt-get install python-dev
pip install requests[security]
...aaaand got
building '_cffi_backend' extension
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -DUSE__THREAD -I/usr/include/ffi -I/usr/include/libffi -I/usr/include/python2.7 -c c/_cffi_backend.c -o build/temp.linux-armv6l-2.7/c/_cffi_backend.o
c/_cffi_backend.c:13:17: fatal error: ffi.h: No such file or directory
compilation terminated.
error: command 'gcc' failed with exit status 1
...soooo,
apt-get install libffi-dev
...and, again...
pip install requests[security]
apt-get install python git gcc python-dev libffi-dev
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
pip install requests[security]
We have to set the user for the OctoPrint; it doesn't like to run as root.
mkdir /home/pi
useradd -d /home/pi -m -s /bin/bash -U pi
chown pi:pi /home/pi
Set the user to the groups for devices access.
usermod -a -G tty pi
usermod -a -G dialout pi
usermod -a -G video pi
Prepare the tools we will need in a moment.
apt-get install python-pip python-setuptools python-virtualenv git libyaml-dev build-essential
https://github.com/foosel/OctoPrint/wiki/Setup-on-a-Raspberry-Pi-running-Raspbian
su pi
cd
git clone https://github.com/foosel/OctoPrint.git
cd OctoPrint
virtualenv --system-site-packages venv
./venv/bin/python setup.py install
...and OctoPrint is installed. Now, let's run it...
~/OctoPrint/venv/bin/octoprint
...and it works. So,
exit
Now, to allow supervising the printouts, install mjpg-streamer...
apt-get install subversion libjpeg8-dev imagemagick libav-tools cmake
and let's do this as the pi user, so...
su pi
cd
git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental
make
/home/pi/mjpg-streamer/mjpg-streamer-experimental/plugins/input_raspicam/input_raspicam.c:44:22: fatal error: bcm_host.h: No such file or directory
compilation terminated.
apt-get install libfreeimage-dev
apt-get install libraspberrypi-dev
apt-get install apt-file
apt-file update
apt-file search bcm_host
libraspberrypi-dev: /opt/vc/include/bcm_host.h
libraspberrypi0: /opt/vc/lib/libbcm_host.so
python-picamera: /usr/lib/python2.7/dist-packages/picamera/bcm_host.py
python-picamera: /usr/share/pyshared/picamera/bcm_host.py
python3-picamera: /usr/lib/python3/dist-packages/picamera/bcm_host.py
...so retrying...
apt-get install libraspberrypi-dev
make
apt-get install subversion libjpeg8-dev imagemagick libav-tools cmake libraspbrerrypi-dev
su pi
cd
git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental
make
So, as root:
make install
...and streamer works:
./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so"
So, to test the webcam, fswebcam was installed:
apt-get install fswebcam
fswebcam -v -r 640x480 -d /dev/video0 /tmp/output.jpeg
edited file plugins/input_uvc/input_uvc.c replaced line
int width = 640, height = 480, fps = -1, format = V4L2_PIX_FMT_MJPEG, i;
int width = 640, height = 480, fps = -1, format = V4L2_PIX_FMT_YUYV, i;
make clean
make
int width = 352, height = 288, fps = 4, format = V4L2_PIX_FMT_YUYV, i;
./mjpg_streamer -i ./input_uvc.so --resolution=QVGA -o ./output_http.so
These may be useful:
Installing Cura: https://github.com/foosel/OctoPrint/wiki/Cura-Integration
We need to upgrade stock gcc to version 4.8, from the v4.6:
edit /etc/apt/sources.list, add line
deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi
create file /etc/apt/preferences.d/0Jessie with content:
Package: * Pin: release n=wheezy Pin-Priority: 900Package: * Pin: release n=jessie Pin-Priority: 300
Package: * Pin: release o=Raspbian Pin-Priority: -10
...then...
apt-get update
apt-get install -t jessie gcc g++
...and decided against continuing as raspi slicer would take too long time, not worth it, better run it on a way stronger machine
If the hot-end fan fails, filament softens too early, then fold and jams in the upper part of the hot end, like a pushed rope.
Note: Running the workpiece cooling fan on full overcools the hot end and trips thermal runaway!
as root:
cp scripts/octoprint.init /etc/init.d/octoprint
chmod +x /etc/init.d/octoprint
cp scripts/octoprint.default /etc/default/octoprint
edit /etc/default/octoprint:
NICELEVEL=-2
NICELEVEL=-18
DAEMON=/home/pi/OctoPrint/venv/bin/octoprint
update-rc.d octoprint defaults
Set up mjpg streamer:
/home/pi/scripts/raspi_streamer
#!/bin/bash
# from here: https://github.com/foosel/OctoPrint/issues/441
RES=QVGA
PlugPath=/usr/local/lib
Daemon=mjpg_streamer
DaemonBase=/usr/local
DaemonArgs="-i \"./input_raspicam.so\" -o \"./output_http.so\""
case "$1" in
start)
mjpg_streamer -b -i "$PlugPath/input_uvc.so --resolution=QVGA" -o "$PlugPath/output_http.so"
echo "$0: started"
;;
stop)
pkill -x ${Daemon}
echo "$0: stopped"
;;
*)
echo "Usage: $0 {start|stop}" >&2
;;
esac
Shut down octoprint (or it would overwrite its configuration file we just edited):
service octoprint stop
and edit /home/pi/.octoprint/config.yaml:
system: {}
change to:
system:
actions:
- action: streamon
command: /home/pi/scripts/raspi_streamer start
confirm: false
name: Start video stream
- action: streamoff
command: /home/pi/scripts/raspi_streamer stop
confirm: false
name: Stop video stream
-action: divider
and
temperature: {}
change to:
temperature:
profiles:
- name: ABS
extruder: 210
bed: 100
- name: PLA
extruder: 180
bed: 60
Setting up Octocmd, octoprint commandline control: http://octocmd.readthedocs.org/en/latest/
pip install https://github.com/vishnubob/octocmd/archive/master.zip
So,
cd /home/pi
wget https://github.com/vishnubob/octocmd/archive/master.zip
unzip master.zip
rm master.zip
chmod 755 /home/pi/octocmd-master/scripts/octocmd
ln -s /home/pi/octocmd-master/scripts/octocmd /usr/bin/
initialize:
octocmd init
> Octorpint URL: http://127.0.0.1:5000/
> Octoprint API key: <key>
Uploaded gcode files are at /home/pi/.octoprint/uploads
It was decided to build a more functional API control. curl and bash were used instead of python the octocmd is written in, due to much faster start.
The whole project was move to its own page, sw_8control.
The controller needs to be reset by hardware. Examples are aborted print, tripped thermal protection, or upload of new firmware.
Install script for pulsing DTR to reset arduino, from https://github.com/brandonedens/jukebox/blob/master/bin/arduino-pulse-dtr
#!/usr/bin/python
"""
Script to pulse the DTR line prior to firmware upload.
"""
import serial
import time
import sys
ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)
ser.setDTR(1)
time.sleep(0.5)
ser.setDTR(0)
ser.close()
put it to /home/pi/scripts/ardureset, then
chmod 755 /home/pi/scripts/ardureset
ln -s /home/pi/scripts/ardureset /usr/bin/
...and it fails,
Traceback (most recent call last):
File "/usr/bin/ardureset", line 6, in <module>
import serial
ImportError: No module named serial
pip install pyserial
And because stty often does not support 250000 bps, here is a setup script, /home/pi/scripts/gsetport
#!/usr/bin/python
import serial
import sys
ser = serial.Serial('/dev/ttyACM0', 250000, timeout=1)
ser.close()
add symlinks...
ln -s /home/pi/scripts/gsetport /usr/bin/
According to https://github.com/foosel/OctoPrint/wiki/OctoPrint-support-for-250000-baud-rate-on-Raspbian there can be a problem with some older pyserial libraries with this speed.
The octoprint distro has a working version.
For other versions, there is a patch for the serialposix.py file, located at /usr/local/lib/python2.7/dist-packages/serial/serialposix.py and the patch is here: http://sourceforge.net/p/pyserial/patches/_discuss/thread/ed3fb0de/f4fd/attachment/pyserial.patch
add to /home/pi/.octoprint/config.yaml, to the System: section:
- action: divider
- action: ardureset
command: /home/pi/scripts/ardureset
confirm: "Are you sure you want to reset the controller?"
name: Reset controller board
created script for showing messages on the display via the M117 g-code: /home/pi/scripts/gmessage
#!/usr/bin/python
"""
Script to show messages on attached display via g-code
Do not use during active print jobs!
Todo: add checks.
"""
import serial
import time
import sys
if len(sys.argv) < 2 :
print 'Shows messages on display via g-code'
print 'Usage: ',sys.argv[0],' <message>'
exit()
ser = serial.Serial('/dev/ttyACM0', 250000, timeout=1)
ser.write('\nM117 '+sys.argv[1]+'\n')
ser.close()
and to beep via g-code: /home/pi/scripts/gbeep
#!/usr/bin/python
"""
Script to beep via g-code
Do not use during active print jobs!
Todo: add checks.
"""
import serial
import sys
ser = serial.Serial('/dev/ttyACM0', 250000, timeout=1)
ser.write('\nM300\n')
ser.close()
add symlinks...
ln -s /home/pi/scripts/gmessage /usr/bin/
ln -s /home/pi/scripts/gbeep /usr/bin/
octoprint API: http://docs.octoprint.org/en/master/api/index.html
export API=CAFEBABE....
export OCTOHOST=http://127.0.0.1:5000
connection:
get API version:
curl -H "X-Api-Key: $API" http://127.0.0.1:5000/api/version
get status:
curl -H "X-Api-Key: $API" http://127.0.0.1:5000/api/connection
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "connect" }' http://127.0.0.1:5000/api/connection
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "disconnect" }' http://127.0.0.1:5000/api/connection
execute arbitrary g-code command (here, a beep):
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "M300" }' http://127.0.0.1:5000/api/printer/command
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "commands": ["M300","M117 test","M300"] }' http://127.0.0.1:5000/api/printer/command
get print job status:
curl -H "X-Api-Key: $API" http://127.0.0.1:5000/api/job
start, restart, pause/unpause, cancel job: (also, it is /api/job, not /api/control/job)
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "start" }' http://127.0.0.1:5000/api/job
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "restart" }' http://127.0.0.1:5000/api/job
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "pause" }' http://127.0.0.1:5000/api/job
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "cancel" }' http://127.0.0.1:5000/api/job
home the tool head:
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "home" }' http://127.0.0.1:5000/api/printer/printhead
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "jog", "x": 10, "y": 20, "z": -30 }' http://127.0.0.1:5000/api/printer/printhead
set tool head temperature for tool 0 and 1 (here, 180 and 210 'C):
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "target", "targets": { "tool0": 180, "tool1": 210" } }' http://127.0.0.1:5000/api/printer/tool
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "select", "tool": "tool0" }' http://127.0.0.1:5000/api/printer/tool
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "extrude", "amount": 5 }' http://127.0.0.1:5000/api/printer/tool
curl -H "X-Api-Key: $API" -H "Content-Type: application/json" -X POST -d '{ "command": "target", "target": 60 }' http://127.0.0.1:5000/api/printer/bed
get bed temperature/status:
curl -H "X-Api-Key: $API" http://127.0.0.1:5000/api/printer/bed
curl -H "X-Api-Key: $API" http://127.0.0.1:5000/api/printer/tool
REVERSE-ENGINEERED:
run tshark -x port 5000|tee x.txt, run example commands; the justniffer tool is better here though
streaming on and off (streamon, streamoff)
curl -H "X-Api-Key: $API" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'action=streamon' http://127.0.0.1:5000/api/system
curl -H "X-Api-Key: $API" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'action=streamoff' http://127.0.0.1:5000/api/system
attempt to get interactive command: failed, will need to go through log files (monitored a parametric command)
- name: Reporting
type: section
children:
- command: M114
name: Get Position
type: feedback_command
regex: "X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:([0-9.]+)"
template: "Position: X={0}, Y={1}, Z={2}, E={3}"
result: a /api/printer/command request is done, with 204 no-data response. Apparently the response data are taken from logs streamed via websocket.
The printer can have several values of its status:
Installing arduino for development of firmware:
apt-get install arduino-core arduino-mk
installs stuff to /usr/share/arduino
Also, install picocom to test stuff directly over serial line:
apt-get install picocom
But this one does not work at 250000 bps speed, so maybe better use the sw_picocom-shad one.
Controller board runs on ATmega2560.
avrdude -p atmega2560 -P /dev/ttyACM0 -b 115200 -c arduino
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
So let's try something different:
ardureset; avrdude -p atmega2560 -P /dev/ttyACM0 -b 115200 -c avrispv2
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): found AVRISP programmer
avrdude: ser_recv(): programmer is not responding
Use lsof -n|grep ttyACM0 to find the culprit.
After killing the offending process it will start running smoothly.
(todo: automate this in arduread/arduwrite scripts; use killall to kill the processes, or an API call to disconnect the printer daemon)
Install arduino dev tools, namely ino:
apt-get install python-dev&&python-setuptools
cd /home/pi
git clone git://github.com/amperka/ino.git
cd ino
python setup.py install
Now where we have the arduino dev env installed, let's use it.
cd /home/pi
scp MarlinDev... directory from the other machine (or wget it from its site, or git clone the directory)
cd /home/pi/MarlinDev-dev-20150910-ShadConfig/Marlin
ino list-models: indicates we should use mega2560
ino build -m mega2560
No project found in this directory.
cd ..
ln -s Marlin src
ino build -m mega2560
.build/mega2560/src/Marlin.cpp:5:35: fatal error: LiquidCrystal_I2C.h: No such file or directory
compilation terminated.
.build/mega2560/Makefile:367: recipe for target '.build/mega2560/src/Marlin.o' failed
make: *** [.build/mega2560/src/Marlin.o] Error 1
Make failed with code 2
...so,
cd /usr/share/arduino/libraries/
git clone git://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
cd -
ino build -m mega2560
cd -
git clone git://github.com/kiyoshigawa/LiquidCrystal_I2C
cd -
ino build -m mega2560
strace -f -o /tmp/x ino build -m mega2560
grep LiquidCrystal_I2C.h /tmp/x
cd /usr/share/arduino/libraries/LiquidCrystal_I2C/LiquidCrystal_I2C
mv * ..
cd ..
rmdir LiquidCrystal_I2C
cd /home/pi/MarlinDev-dev-20150910-ShadConfig/
ino build -m mega2560
cp -av /usr/share/arduino/libraries/LiquidCrystal_I2C lib/
strace shows that it looks in the /usr/share/arduino/libraries/LiquidCrystal/ so let's put it there (don't actually do this, because the missing step is the ino clean step):
mv /usr/share/arduino/libraries/LiquidCrystal_I2C/* /usr/share/arduino/libraries/LiquidCrystal/
ino build -m mega2560
.build/mega2560/src/Marlin.cpp:7:28: fatal error: LiquidTWI2.h: No such file or directory
compilation terminated.
.build/mega2560/Makefile:373: recipe for target '.build/mega2560/src/Marlin.o' failed
make: *** [.build/mega2560/src/Marlin.o] Error 1
git clone git://github.com/lincomatic/LiquidTWI2
mv LiquidTWI2 /usr/share/arduino/libraries/
ino build -m mega2560
strace -f -o /tmp/x ino build -m mega2560
grep LiquidTWI2.h /tmp/x
ino clean
ino build -m mega2560
.build/mega2560/src/Marlin.cpp:8:101: fatal error: U8glib.h: No such file or directory
compilation terminated.
.build/mega2560/Makefile:396: recipe for target '.build/mega2560/src/Marlin.o' failed
make: *** [.build/mega2560/src/Marlin.o] Error 1
Make failed with code 2
cp -av ./ArduinoAddons/Arduino_1.6.x/hardware/marlin/avr/libraries/U8glib /usr/share/arduino/libraries/
ino clean
ino build -m mega2560
.build/mega2560/src/Marlin.cpp:13:29: fatal error: TMC26XStepper.h: No such file or directory
compilation terminated.
.build/mega2560/Makefile:1097: recipe for target '.build/mega2560/src/Marlin.o' failed
make: *** [.build/mega2560/src/Marlin.o] Error 1
Make failed with code 2
cp -av ./ArduinoAddons/Arduino_1.6.x/libraries/TMC26XStepper/ /usr/share/arduino/libraries/
cp -av ./ArduinoAddons/Arduino_1.6.x/libraries/L6470/ /usr/share/arduino/libraries/
ino clean
ino build -m mega2560
.....
arduino/Tone.cpp
arduino/HID.cpp
Linking libarduino.a
Linking firmware.elf
Converting to firmware.hex
find .|grep firmware.hex
So, let's try to flash it...
service octoprint stop
ardureset; avrdude -p atmega2560 -P /dev/ttyACM0 -b 115200 -c avrispv2 -U flash:w:./.build/mega2560/firmware.hex
avrdude: Device signature = 0x1e9801
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: stk500v2_command(): command failed
ardureset; avrdude -p atmega2560 -P /dev/ttyACM0 -b 115200 -c stk500 -D -U flash:w:./.build/mega2560/firmware.hex
service octoprint start
<edit file>
ino build -m mega2560
cd /home/pi
scp MarlinDev... directory from the other machine (or wget it from its site, or git clone the directory)
cd /home/pi/MarlinDev-dev-20150910-ShadConfig
ln -s Marlin src
git clone git://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
mv Arduino-LiquidCrystal-I2C-library /usr/share/arduino/libraries/
git clone git://github.com/lincomatic/LiquidTWI2
mv LiquidTWI2 /usr/share/arduino/libraries/
cp -av ./ArduinoAddons/Arduino_1.6.x/hardware/marlin/avr/libraries/U8glib /usr/share/arduino/libraries/
cp -av ./ArduinoAddons/Arduino_1.6.x/libraries/TMC26XStepper/ /usr/share/arduino/libraries/
cp -av ./ArduinoAddons/Arduino_1.6.x/libraries/L6470/ /usr/share/arduino/libraries/
ino build -m mega2560
Getting rid of an annoyance that appeared sometime along installing the packages.
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LANG = "en_GB.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
put this to /etc/default/locale:
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_ALL=en_US
...but doesn't work.
tried apt-get install locales, and failed:
Reading package lists... Done
Building dependency tree
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:
The following packages have unmet dependencies:
locales : Depends: glibc-2.13-1
Depends: debconf (>= 0.5) but it is not going to be installed or
debconf-2.0
E: Unable to correct problems, you have held broken packages.
Decided to not bother, put "C" as local language: /etc/default/locale:
LANG=C
Set up GPIOs on the Raspi board:
apt-get install wiringpi
create directory for scripts:
mkdir /home/pi/scripts/gpio
create pin list /home/pi/scripts/gpio/gpio_defs.sh, with content
PIN_ATXPWR=23
create script for setting the pins and setting output permissions for the pi user, /home/pi/scripts/gpio/setpins.sh:
#!/bin/bash
. /home/pi/scripts/gpio/gpio_defs.sh
setinput (){
echo $1 > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$1/direction
gpio -g mode $1 in
gpio -g mode $1 up
}
setoutput (){
echo $1 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio$1/direction
chown -R pi:pi /sys/class/gpio/gpio$1/value
}
setoutput $PIN_ATXPWR
Create script for powering up the ATX PSU, disabling reset on connect, and connecting controller to server, /home/pi/scripts/gpio/atx_on.sh:
#!/bin/bash
. /home/pi/scripts/gpio/gpio_defs.sh
setpin() {
echo $2 > /sys/class/gpio/gpio$1/value
}
setpin $PIN_ATXPWR 1
sleep 2
stty -F /dev/ttyACM0 hupcl-
8connect
Create script for powering down the ATX PSU, /home/pi/scripts/gpio/atx_on.sh:
#!/bin/bash
. /home/pi/scripts/gpio/gpio_defs.sh
setpin() {
echo $2 > /sys/class/gpio/gpio$1/value
}
8msg Disconnecting...
8disconnect
sleep 2
setpin $PIN_ATXPWR 0
name script to start with Kxx, put to /etc/rc6.d
as described here: http://ccm.net/faq/3348-ubuntu-executing-a-script-at-startup-and-shutdown
One of the GPIOs of the host computer board was connecte to the base of a NPN transistor. The transistor was connected between the power-control line of the ATX PSU connector (the green wire) and ground. High level on the GPIO now powers up the ATX PSU.
The controller and the webcam aren't needed when the printer is depowered. The host computer would however feed them via the USB. A USB hub was therefore used; its USB power wire was cut and attached instead to the non-standby 5V rail of the ATX PSU. This automatically powers and depowers the controller and all the auxiliary equipment when the printer is powered on or off..
A switch is added to allow selection between the standby and non-standby power, to facilitate development without having to power the whole machine.
This may be handier than using /dev/ttyACM0, for the cases when there are more than one Arduino-based serial controller attached to the machine.
In /etc/rc.local, add
ln -s /dev/serial/by-id/usb-Arduino__www.arduino.cc_<your-serial-number>-if00 /dev/3dprinter
apt-get install httpry
...and httpry works, but shows just the requests, but for debugging the API the whole requests and headers are needed. So...
So let's try justniffer, http://justniffer.sourceforge.net/
The way via apt repository using ppa:oreste-notelli/ppa repo did not work.
cd /usr/src
git clone git://github.com/onotelli/justniffer
cd justniffer
./configure
...and it failed, on inability to run config.sub
...which points to /usr/share/automake-1.14/config.sub
...but there's no such version, we have /usr/share/automake-1.11/config.sub, so relink for that and for config.guess
...and retry...
checking for Boost headers version >= 1.46.0... no
configure: error: cannot find Boost headers version >= 1.46.0
apt-get install libboost-iostreams1.49 libboost-iostreams1.49-dev
checking for boost/program_options.hpp... yes
checking for the Boost program_options library... no
configure: error: cannot find the flags to link with Boost program_options
apt-file find libboost-program-options
apt-get install libboost-program-options1.49.0 libboost-program-options1.49-dev
apt-get install libpcap0.8-dev
./configure
make
CDPATH="${ZSH_VERSION+.}:" && cd . && aclocal-1.14
/bin/bash: aclocal-1.14: command not found
make: *** [aclocal.m4] Error 127
In file included from /usr/include/boost/python/detail/prefix.hpp:13:0,
from /usr/include/boost/python/args.hpp:8,
from /usr/include/boost/python.hpp:11,
from python.h:15,
from formatter.cpp:19:
/usr/include/boost/python/detail/wrap_python.hpp:50:23: fatal error: pyconfig.h: No such file or directory
# include <pyconfig.h>
# include <python3.2/pyconfig.h>
#include <patchlevel.h>
#include <python3.2/patchlevel.h>
# include <Python.h>
# include <python3.2/Python.h>
apt-get install python3.2-dev
make
make[1]: Entering directory `/usr/src/justniffer/src'
/bin/bash ../libtool --tag=CXX --mode=link g++ -g -O2 -o justniffer justniffer-main.o justniffer-formatter.o justniffer-utilities.o justniffer-regex.o justniffer-prog_read_file.o -L../lib/libnids-1.21_patched/src -lnids2 -lpcap -lboost_regex-mt -lboost_program_options-mt -l
libtool: link: g++ -g -O2 -o justniffer justniffer-main.o justniffer-formatter.o justniffer-utilities.o justniffer-regex.o justniffer-prog_read_file.o -L../lib/libnids-1.21_patched/src -lnids2 -lpcap -lboost_regex-mt -lboost_program_options-mt -l
g++: error: missing argument to '-l'
make[1]: *** [justniffer] Error 1
make[1]: Leaving directory `/usr/src/justniffer/src'
make: *** [all-recursive] Error 1
PYTHON_LIB = python3.2mu
make
make install
cd /home/pi
git clone git://github.com/onotelli/justniffer
cd justniffer
apt-get install libboost-iostreams1.49 libboost-iostreams1.49-dev libboost-program-options1.49.0 libboost-program-options1.49-dev libpcap0.8-dev
apt-get install automake
./configure
...failed on config.sub symlinked to automake 1.14, replaced with 1.11:
rm config.sub config.guess;ln -s /usr/share/automake-1.11/config.sub .;ln -s /usr/share/automake-1.11/config.guess .
./configure
make
CDPATH="${ZSH_VERSION+.}:" && cd . && aclocal-1.14
/bin/bash: aclocal-1.14: command not found
Makefile:409: recipe for target 'aclocal.m4' failed
make: *** [aclocal.m4] Error 127
configure.ac:54: error: possibly undefined macro: AC_PROG_LIBTOOL
apt-get install libtool
make
...so for now just intercept the comm and analyze it elsewhere...
tcpdump -w /tmp/file.cap -s0 port 5000
...and let's continue...
./configure: line 5435: AC_PROG_LIBTOOL: command not found
cd ..
rm -rvf justniffer
git clone git://github.com/onotelli/justniffer
cd justniffer
rm config.sub config.guess;ln -s /usr/share/automake-1.11/config.sub .;ln -s /usr/share/automake-1.11/config.guess .
./configure
...and, we're successful, so...
make
make install
GET /api/plugin/status_line ==> {"status_line": "OctoPrint connected"}
GET /plugin/printhistory/history ==> {"history": {"0": {"filamentLength": 2004.615320000079, "filamentVolume": 4.821664896354753, "fileName": "RaspiB1frame.gcode", "note": ""}, "1446143472159": {"filamentLength"...
GET /api/timelapse ==> {"config": {"type": "off"}, "files": []}
GET /plugin/softwareupdate/check ==> {"information": {"customcontrol": {"check": {"current": "0.2.1", "displayName": "Custom Control Editor Plugin", "displayVersion": "0.2.1", "pip": "https://git..."
GET /api/logs ==> {"files": [{"date": 1446710839, "name": "octoprint.log", "refs":...
GET /api/plugin/pluginmanager ==> {"octoprint": "1.2.7", "os": "linux", "pip": {"additional_args": null, "available": true, "command": "/home/pi/OctoPrint/venv/bin/pip", "use_sudo": false, "version": "1.1"},...
POST /api/files/local/KosselXL-tubeholder.gcode
GET /api/printer/command/custom ==> {"controls": [{"children": [{"command": "M106 S%(speed)s", "input": [{"default": 255, "name": "Speed (0-255)", "parameter": "speed"}], "name": "Enable Fan", "type": "parametric_command"}, {"command": "M107", "name": "Disable Fan", "type": "command"}], "name": "Fan", "type": "section"}, {"children": [{"command": "M114", "key": "94e9bd395ef599fbe33e42c344ae9ced", "name": "Get Position", "regex": "X:([0-9.]+) Y:([0-9.]+) Z:([0-9.]+) E:([0-9.]+)", "template": "Position: X={0}, Y={1}, Z={2}, E={3}", "template_key": "5d54d9c91f6e9cf73978708bfa400d3c", "type": "feedback_command"}], "name": "Reporting", "type": "section"}]}
GET /api/settings ==> {"api": {"allowCrossOrigin": false, "enabled": true, "key":...
GET /api/printerprofiles ==> {"profiles": {"_default": {"axes": {"e": {"inverted": false, "speed": 300}, "x": ...
GET /sockjs/213/_3zjc4ry/websocket HTTP/1.1 Host: 10.0.0.110:5000 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: http://10.0.0.110:5000 Sec-WebSocket-Version: 13 DNT: 1 User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,cs;q=0.6,sk;q=0.4,fi;q=0.2,it;q=0.2,ru;q=0.2 Cookie: session=.eJyrVorPTFGyqlZSSFKyUvJ1ca2MDPct9zUKyvHLci2PyvU18s31rfALCTX2M_I1jArxyvFzcTSICg-1VarVUcpMSc0rySyp1EssLcmIL6ksSFWyyivNyUGSQTI9yiOsJCkiG6izFgDnTSbT.CRyisQ.mlVLY d27OMDgk127y171dY_VE6c Sec-WebSocket-Key: TA37E8MJqIDd6SrbQjLjZQ== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: xp/dciJo2gSfFoK5itfcmvRK1SU=
<81>^Ao<81>~^@a[{"connected":{"display_version":"1.2.7 (master branch)","apikey":"D567207981A64C368074EC43E9117E95","version":"1.2.7","branch":"master","plugin_hash":"3d63630e210bb671f2dc2e8e16fd0a1d"}}]<81>~7^Da[{"history":{"logs":["Connecting to: /dev/3dprinter","Changing monitoring state from 'Offline' to 'Opening serial port'","Connected to: Serial (port='/dev/3dprinter', baudrate=250000, bytesize=8, parity='N', stopbits=1, timeout=10.0, xonxoff=False, rtscts=False, dsrdtr=False), starting monitor","Changing monitoring state from 'Opening serial port' to 'Connecting'","Send: M110"
The octoprint user interface uses the websocket protocol. So tools for connecting to those are needed. There are several, the wssh one was chosen as it does not rely on a monstrous framework like node.js nor it does require some obscure language like go.
git clone git://github.com/progrium/wssh
cd wssh
python setup.py install
...and it fails on gcc not finding event.h, so we used...
apt-file find include/event.h
apt-get install libevent-dev
python setup.py install
Searching for ws4py==0.2.4
Reading https://pypi.python.org/simple/ws4py/
Reading http://www.defuze.org/oss/ws4py/
Reading https://github.com/Lawouach/WebSocket-for-Python
Reading https://pypi.python.org/pypi/ws4py
No local packages or download links found for ws4py==0.2.4
error: Could not find suitable distribution for Requirement.parse('ws4py==0.2.4')
pip install ws4py
install_requires=['ws4py==0.2.4','gevent==0.13.6'],
install_requires=['ws4py==0.3.4','gevent==0.13.6'],
Traceback (most recent call last):
File "/usr/local/bin/wssh", line 9, in <module>
load_entry_point('wssh==0.1.0', 'console_scripts', 'wssh')()
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 558, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2682, in load_entry_point
return ep.load()
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2355, in load
return self.resolve()
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2361, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "build/bdist.linux-armv6l/egg/wssh/__init__.py", line 9, in <module>
File "build/bdist.linux-armv6l/egg/wssh/server.py", line 6, in <module>
ImportError: cannot import name UpgradableWSGIHandler
...which is because that bloody ws4pi requiring the 0.2.4 version. fuck!
...so,
apt-get install python-ws4py=0.2.4
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Version '0.2.4' for 'python-ws4py' was not found
...no dice.
...so let's pip it right from the git, using the painfully found @version trick...
pip install git+git://github.com/Lawouach/WebSocket-for-Python/@v0.2.4
python setup.py install
apt-get install libevent-dev
pip install git+git://github.com/Lawouach/WebSocket-for-Python/@v0.2.4
git clone git://github.com/progrium/wssh
cd wssh
python setup.py install
so, run on two machines:
wssh -l 0.0.0.0:8888/websocket
wssh -v octo:8888/websocket
Now, how to connect to the octoprint...
wssh 127.0.0.1:5000/sockjs/x/y/websocket
System section in /home/pi/.octoprint/config.yaml:
system: actions: - action: stream command: /home/pi/scripts/raspi_streamer start confirm: false name: Start video stream 320x240 - action: streamvga command: /home/pi/scripts/raspi_streamer start VGA confirm: false name: Start video stream 640x480 - action: streamoff command: /home/pi/scripts/raspi_streamer stop confirm: false name: Stop video stream - action: divider - action: "on" command: /home/pi/scripts/gpio/atx_on.sh confirm: false name: Power ON the printer - action: "off" command: /home/pi/scripts/gpio/atx_off.sh confirm: Power off the printer - are you sure? name: Power OFF the printer - action: divider - action: reset command: /home/pi/scripts/ardureset confirm: Are you sure you want to reset the controller? name: Reset controller board
"on" and "off" have to be quoted, otherwise yaml parser converts them to true and false.
events: enabled: true subscriptions: - command: echo "OctoPrint disconnected" > /dev/3dprinter event: Disconnected type: system - command: - M117 OctoPrint connected event: Connected type: gcode - command: - M117 Upload:{file} event: Upload type: gcode - command: - M117 do:{filename} event: FileSelected type: gcode - command: - M117 Start:{filename} event: PrintStarted type: gcode - command: - M117 FAIL:{filename} event: PrintFailed type: gcode - command: - M117 Printing finished! event: PrintDone type: gcode - command: - M117 Cancelled event: PrintCancelled type: gcode - command: - M117 --PAUSED-- event: PrintPaused type: gcode - command: - M117 Resumed:{filename} event: PrintResumed type: gcode - command: - M117 --Waiting-- event: Waiting type: gcode