Difference between revisions of "Cerealbot/rpi"
m (→Set up a Toolchain: added compiling/uploading) |
m (→Compiling Stuff: typo) |
||
Line 496: | Line 496: | ||
make | make | ||
make raw_upload | make raw_upload | ||
− | <pre> | + | </pre> |
Output from ''make raw_upload'' should be like: | Output from ''make raw_upload'' should be like: |
Revision as of 04:21, 9 June 2015
I'm using an RPi 2 model B for this project. Here are my notes.
Pi <-> RPi <-> Raspberry Pi
Cerealbot Code
This is the most important section on this page. Everything below is just config and notes for setting up my RPi server.
How it works:
Shell script hooks bound to Octoprint's "printStart" and "printDone" events. These handle setting the flag which indicates a part is being printed/removed. Once a part is being removed, its corresponding gcode is deleted from the queue.
A cron job checks the printer status and queue for a match of "free printer + file to print" and then kicks off the print job.
A C program acts as a buffer to the arduino and allows the shell scripts to control hardware in a easy to use but complicated to setup manner.
Prerequisites
- Octoprint
- Webcam (if you want it)
- Arduino/ATmel that you can flash code to
API
Curl is great for testing around with both Octoprint and RedQueen's api, but I've switched the shell scripts to use resty for ease of maintenance.
Curl Examples To RedQueen: curl --data "{\"message\":\"${MSG}\", \"channel\":\"##rqtest\", \"isaction\":false, \"key\":\"${APIKEY}\"}" https://crump.space/rq/relay -H "Content-Type:application/json" To Octoprint: curl -H "X-Api-Key:$OCTO_API_KEY" http://bns-daedalus.256.makerslocal.org/api/printer -o /tmp/printr_status.json
OS
Install
I'm just using Rasbian from the foundation's download page. I find Debian derivatives to be comfortable for projects such as this. You're welcome to use whatever distro you like.
I strongly recommend you follow some official guide for installing the OS if you're at all uncertain. The notes here are sparse and meant to make it faster for me to recover from a broken system.
Get the archive, extract the file. Should be along the lines of '2015-05-05-rasbian-wheezy.img'.
Flash it to the SD card: 'sudo dd if=2015...img of=/dev/sdX bs=4M'.
Configure things with the raspi tool that loads on first boot, then install your favorite packages. Mine are:
htop vim emacs byobu tmux build-essential bash-completion haproxy authbind
Set the time/zone
http://aryo.lecture.ub.ac.id/configure-timezone-settings-on-raspberry-pi-raspbian-wheezy/
By default, Rasbian has an ntp daemon running, but you may still need to select a timezone. Use tzselect to set the timezone, then echo the returned line into .profile.
for me, this means:
echo "TZ='America/Chicago'; export TZ" >> ~/.profile
Setup SSH
I really recommend setting up SSH keys. There are many good guides for this elsewhere.
Setup Git
There's really no need to do this, but I like having git handle passwords for me.
https://help.github.com/articles/caching-your-github-password-in-git/
git config --global credential.helper 'cache --timeout=3600'
Setup Byobu
- F1 allows you to set "log into byobu" to save some time while logging in.
- 'C-a a' will send C-a to /usr/bin/screen, so you can use screen within byobu to debug serial connections.
Recover SD Filesystem
Hypothetically, in a strictly theoretical sense, with no basis whatsoever to the real world and real people:
Say someone at your hackerspace is horsing around and trips the breaker that your Pi is powered from. Well if you're lucky, then you just walk over and reboot the sucker. Sometimes that doesn't work though, and the computer's little SD card has become corrupt. Rather than break out the backup that you totally have, let's try a quick recovery first.
First, remove the SD card and insert it into your computer. Make sure it is unmounted.
Test recovery:
sudo dd if=/dev/sdX2 of=pi_bkup.img cp pi_bkup.img pi_bkup_recv.img sudo e2fsck -fy pi_bkup_recv.img
You may have to run that last command twice, idk why. If the program successfully recovers the test image, you have two options:
- Flash this cured image file back to the partition it came from
- Try to directly recover the SD card, since you know it has a chance of working.
The second option is faster:
sudo e2fsck -ft /dev/sdX2
Good luck!
Octoprint
Install
There are good guides elsewhere for installing Octoprint. I really don't see a need for repeating the instructions.
- Install Octoprint
- Have it start on boot
- Configure your account
- Generate an API key
Authbind to Port 80
If your network supports it, go ahead and use HAProxy. Ours didn't work initially, so I gave up and instead used Authbind.
https://mutelight.org/authbind
sudo apt-get install authbind sudo touch /etc/authbind/byport/80 sudo chown pi /etc/authbind/byport/80 sudo chmod 500 /etc/authbind/byport/80
Adjust a few lines in /etc/default/octoprint to match:
... PORT=80 ... DAEMON_ARGS="--port=$PORT" ...
In /etc/init.d/octoprint you need to add a line for authbind in the variable declaration area:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="Octoprint Daemon" NAME="Octoprint" DAEMON=/usr/local/bin/octoprint AUTHBIND=/usr/bin/authbind ...
In the same file, you then need to find the line which starts octoprint and insert authbind:
start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile \ --exec $DAEMON --chuid $OCTOPRINT_USER --user $OCTOPRINT_USER --umask $UMASK -- $DAEMON_ARGS
To:
start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile \ --exec $AUTHBIND $DAEMON --chuid $OCTOPRINT_USER --user $OCTOPRINT_USER --umask $UMASK -- $DAEMON_ARGS
MJPG-Streamer
This is the current go-to tool for webcam streaming with octoprint. If you have a webcam set up, then you can totes ignore this section. It's also worth browsing around to see if you find a process you like better than mine.
First, you may want to collect some information on your webcam:
To list available formats:
v4l2-ctl --list-formats
or
v4l2-ctl -d /dev/videoX --list-formats-ext | less
Install
There are general instructions for installing mjpg-streamer on octoprint's wiki. I've detailed some changes to incorporate a different version and setup a daemon.
mjpg-streamer is by far my favorite solution for webcam streaming from the RPi. A recent update brought immense relief for CPU overhead.
Install some dependancies:
sudo apt-get install libjpeg62-dev cmake subversion imagemagick libav-tools
Git the project:
git clone https://github.com/jacksonliam/mjpg-streamer.git cd mjpg-streamer/mjpg-streamer-experimental/ make clean make all
The base command to run mjpg-streamer. Don't worry about this, its handled by an init.d script.
mjpg_streamer -b -i "./input_uvc.so -d /dev/video0 -n -f 5 -r 1280x720" -o "./output_http.so -p 8080 -w ./www"
Previously I've used the -y flag for compatibility, which totally crushed the little CPU, but the most recent build of mjpg-streamer-experimental appears to work quite well with my Logitech webcam using the default MJPG codec.
Setup Init Script
Go to foosel's mjpg init page and copy-pasta the two files into /etc/init.d/mjpg-streamer and /etc/default/mjpg-streamer respectively.
Don't forget to edit /etc/default/mjpg-streamer to your liking, and make /etc/init.d/mjpg-streamer executable!
sudo chmod +x /etc/init.d/mjpg-streamer sudo update-rc.d mjpg-streamer defaults
If you have troubles, make sure to sudo update-rc.d mjpg-streamer remove and then reboot each time while working on it manually.
I've modified the init scripts while facerolling to try and get this junk working.
/etc/init.d/mjpg-streamer:
#!/bin/sh ### BEGIN INIT INFO # Provides: mjpg-streamer # Required-Start: $local_fs networking # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: mjpg-streamer daemon # Description: Starts the mjpg-streamer daemon with the user specified in # /etc/default/mjpg-streamer. ### END INIT INFO # Author: Sami Olmari PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="mjpg-streamer Daemon" NAME="mjpg-streamer" DAEMON=mjpg-streamer PIDFILE=/var/run/$NAME.pid PKGNAME=mjpg-streamer SCRIPTNAME=/etc/init.d/$PKGNAME # Read configuration variable file if it is present [ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME # Exit if the mjpg-streamer is not installed [ -x "$DAEMON_HOME/$DAEMON" ] || exit 0 # Load the VERBOSE setting and other rcS variables [ -f /etc/default/rcS ] && . /etc/default/rcS # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions if [ -z "$RUN_AT_STARTUP" -o "$RUN_AT_STARTUP" != "YES" ] then log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it." exit 0 fi if [ -z "$MJPG_STREAMER_USER" ] then log_warning_msg "Not starting $PKGNAME, MJPG_STREAMER_USER not set in /etc/default/$PKGNAME." exit 0 fi # # Function to verify if a pid is alive # is_alive() { pid=`cat $1` > /dev/null 2>&1 kill -0 $pid > /dev/null 2>&1 return $? } # # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started is_alive $PIDFILE RETVAL="$?" if [ $RETVAL != 0 ]; then start-stop-daemon --start --pidfile $PIDFILE --make-pidfile --chuid $MJPG_STREAMER_USER --user $MJPG_STREAMER_USER --umask $UMASK \ --exec $DAEMON_HOME/$DAEMON RETVAL="$?" echo "\nRetval: $RETVAL" fi } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $MJPG_STREAMER_USER --pidfile $PIDFILE RETVAL="$?" [ "$RETVAL" = "2" ] && return 2 rm -f $PIDFILE [ "$RETVAL" = "0" ] && return 0 || return 1 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; restart) log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2 exit 3 ;; esac :
/etc/default/mjpg-streamer:
# Configuration for /etc/init.d/mjpg-streamer # The init.d script will only run if this variable non-empty. MJPG_STREAMER_USER="pi" # Where mjpg-streamer is installed, this is important! DAEMON_HOME=/home/pi/mjpg-streamer/mjpg-streamer-experimental DAEMON=start.sh # What arguments to pass to mjpg-streamer, here is few examples; You can change them by commenting one and # uncommenting another: export LD_LIBRARY_PATH=$DAEMON_HOME #DAEMON_ARGS='-i "$DAEMON_HOME/input_uvc.so -r SXGA -f 15" -o "$DAEMON_HOME/output_http.so"' # UVC-mode #DAEMON_ARGS='-i "$DAEMON_HOME/input_uvc.so -y" -o "$DAEMON_HOME/output_http.so"' # YUV-mode # Umask of files mjpg-streamer generates, Change this to 000 if running mjpg-streamer as its own, separate user UMASK=022 # Should we run at startup? RUN_AT_STARTUP="YES"
Octoprint Protip
To use an http stream with octoprint, the URL has to be formatted correctly.
At first glance, I tried: cerealbox.256.makerslocal.org:8081, which didn't work.
Turns out Octoprint blindly appends a GET variable to the URL, which turns the above into: cerealbox.256.makerslocal.org:8081?2354jk345 which isn't a valid URL anymore.
So, you have to set up the webcam URL like: http://cerealbox.256.makerslocal.org:8081/
Here the trailing slash lands the GET variable. It took Hunter Fuller to figure all that out.
UV4L
uv4l is a promising tool to replace mjpg-streamer with faster performance on the RPi 2. Right now it just crashes my pi though.
http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14
Arduino/ATmega/AVR
To make the Cerealbot code work, you have to have some sort of AVR microcontroller. This can range anywhere from a full-fledge Arduino, to a somewhat cheaper Diavolino, to a bare breadboarded ATmega328.
I'm using a Diavolino wired to the RPi via GPIO headers. Again, there are good resources out there, no need to copy me exactly.
Wiring to GPIO
On the Pi's headers, there's a default serial Rx/Tx associated with TTY. We're going to yank it away from the OS and use it to speak with and program the ATmega on our Diavolino.
I'm using a high-low logic level converter to protect the Pi. This is crucial; the arduino is capable of burning out the headers on the Pi without some sort of voltage divider.
The following table uses the HARDWARE (aka "Board") GPIO mappings! You can reference this image, and use the numbers in the circles, not by the labels!
Arduino Pin | RPi GPIO |
---|---|
Rx (0) | UART0_TXD (8) |
Tx (1) | UART0_RXD (10) |
GND | GND (6) |
RST/RTS | GPIO (11) |
Connect Vcc and GND pins from the Arduino to an external source, I don't suggest wiring them to the GPIO pins even though seemingly appropriate pins exist.
Free UART0 from TTY
We need to kick Rasbian off of the header GPIO:
At the end of /etc/inittab, change
#Spawn a getty on Raspberry Pi Serial line T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
To:
#Spawn a getty on Raspberry Pi Serial line #T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
In /boot/cmdline.txt, remove any of console=ttyAMA0,115200 or kgdboc=ttyAMA0,115200
Create /etc/udev/rules.d/80-gpio.rules, and add:
KERNEL=="ttyAMA0", SYMLINK+="ttyS0",GROUP="dialout",MODE:=0666
Set up a Toolchain
Since I'm making use of the Arduino Bootloader to flash programs to the ATmega without ICSP, we're going to stick with regular "sketches" for now, not real microcontroller firmware. I do intend to mess with that later though.
Compiling sketches without a graphical X server has apparently been an issue for some time with Arduino folk. Even though the official IDE touts CLI building, it fails without a X screen for me.
Install packages:
sudo apt-get install arduino-mk arduino-core avrdude avr-libc gcc-avr
Setup the GPIO reset workaround:
git clone https://github.com/deanmao/avrdude-rpi cd avrdude-rpi sudo mv /usr/bin/avrdude /usr/bin/avrdude-original sudo ln -s /home/pi/avrdude-rpi/avrdude-autoreset /usr/bin/avrdude sudo ln -s /home/pi/avrdude-rpi/autoreset /usr/bin/autoreset
That should do it! Pretty straightforward really.
Compiling Stuff
Go into a source folder with a .ino file:
cd ~/cerealbox/avr/src make clean make make raw_upload
Output from make raw_upload should be like:
pi@bns-daedalus ~/cerealbox/avr/src $ sudo make raw_upload /usr/bin/avrdude -q -V -p atmega328p -C /etc/avrdude.conf -c arduino -b 57600 -P /dev/ttyAMA0 \ -U flash:w:build-cli/printr_avr.hex:i done with autoreset avrdude-original: AVR device initialized and ready to accept instructions avrdude-original: Device signature = 0x1e950f avrdude-original: NOTE: FLASH memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude-original: erasing chip avrdude-original: reading input file "build-cli/printr_avr.hex" avrdude-original: writing flash (4902 bytes): avrdude-original: 4902 bytes of flash written avrdude-original: safemode: Fuses OK
Links
AMT1001
http://davidegironi.blogspot.com/2013/07/amt1001-humidity-and-temperature-sensor.html#.VXOzO5Tve00
SURE Electronics 3208
http://store.sure-electronics.com/led/de-dp13119
http://forum.arduino.cc/index.php?topic=167753.0
http://playground.arduino.cc/Main/HT1632C
https://github.com/gauravmm/HT1632-for-Arduino <- Awesome
http://bailey.st/blog/2011/07/12/how-to-connect-sure-electronics-8x32-led-matrix-display-to-arduino/ <- Wiring
GPIO To Arduino
http://www.evilmadscientist.com/2010/diavolino/
http://www.atmel.com/Images/doc8161.pdf
http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/
https://github.com/deanmao/avrdude-rpi
http://www.deanmao.com/2012/08/10/uploading-sketches-to-the-arduino-on-the-pi/
http://spellfoundry.com/sleepy-pi/setting-arduino-ide-raspbian/