Raspberry Pi - Artnet Projector Shutter

Part 1: General setup

  • run raspbian-ua-netinst on SD card (default install - server packages of debian jessie)
  • SSH in as root…
passwd
> /etc/motd
echo rpi-shutter > /etc/hostname
sed -i s/pi/rpi-shutter/g /etc/hosts
echo "America/Chicago" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
sed -i -e 's/^# en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
dpkg-reconfigure -f noninteractive locales
apt-get update
apt-get --no-install-recommends install aptitude
# the rpi foundation version is less buggy, although distributed in a more annoying way
# however, the installer pins the non-foundation version, so we have to get rid of that
# commenting out lines in apt preferences files seems to be problematic, so we just delete it
rm /etc/apt/preferences.d/01vcgencmd.pref
aptitude install raspberrypi-bootloader
** when it asks about conflict resolution, tell it you want to upgrade libraspberrypi-bin and libraspberrypi0 (not remove them) -- removing raspberrypi-bootloader-nokernel is normal -- this is the second option
sed -i -e 's/^snd-bcm2835/#snd-bcm2835/g' /etc/modules
# echo 'vm.min_free_kbytes = 4096' > /etc/sysctl.d/raspi-eth0_fix.conf # probably not needed anymore -- see http://wiki.gentoo.org/wiki/Raspberry_Pi#Troubleshooting
aptitude install raspi-copies-and-fills
aptitude install libraspberrypi-bin fbset
echo >> /boot/config.txt
echo 'boot_delay=0' >> /boot/config.txt
aptitude install netcat-traditional screen rsync psmisc file patch ethtool strace tcpdump vim bzip2 xz-utils
aptitude --without-recommends install dnsutils
aptitude install dosfstools

aptitude --without-recommends install kbd

adduser tdobes
adduser tdobes adm
adduser tdobes systemd-journal

echo '[Unit]' > /etc/systemd/system/ntp.service
echo 'Description=Network Time Protocol daemon' >> /etc/systemd/system/ntp.service
echo 'After=network.target' >> /etc/systemd/system/ntp.service
echo >> /etc/systemd/system/ntp.service
echo '[Service]' >> /etc/systemd/system/ntp.service
echo 'ExecStart=/usr/sbin/ntpd -n -g -u ntp:ntp' >> /etc/systemd/system/ntp.service
echo >> /etc/systemd/system/ntp.service
echo '[Install]' >> /etc/systemd/system/ntp.service
echo 'WantedBy=multi-user.target' >> /etc/systemd/system/ntp.service
systemctl enable ntp.service

mkdir -p /etc/systemd/system/ssh.socket.d
echo '[Socket]' > /etc/systemd/system/ssh.socket.d/port-2222.conf
echo 'ListenStream=2222' >> /etc/systemd/system/ssh.socket.d/port-2222.conf
systemctl disable ssh.service && systemctl enable ssh.socket

mkdir -p /etc/systemd/system/getty\@tty1.service.d
echo '[Service]' > /etc/systemd/system/getty\@tty1.service.d/noclear.conf
echo 'TTYVTDisallocate=no' >> /etc/systemd/system/getty\@tty1.service.d/noclear.conf

systemctl mask networking.service # we use ifplugd instead
echo 'D /run/network 0755 root root' > /etc/tmpfiles.d/debian-networking.conf
echo 'F /run/network/ifstate 0644 root root - lo=lo' >> /etc/tmpfiles.d/debian-networking.conf

systemctl mask kbd.service # this doesn't seem to work anyway

systemctl mask rc-local.service
systemctl disable rsyslog.service # disable to reduce writes to sd card
systemctl disable wpa_supplicant.service # unnecessary; started automatically

systemctl stop rsyslog.service
rm /var/log/auth.log* /var/log/daemon.log* /var/log/debug /var/log/kern.log* /var/log/messages /var/log/user.log*

Part 6: Overclock

# Medium overclocking
echo 'arm_freq=900' >> /boot/config.txt
echo 'core_freq=333' >> /boot/config.txt
echo 'sdram_freq=450' >> /boot/config.txt
echo 'over_voltage=2' >> /boot/config.txt

aptitude install sysfsutils
echo 'devices/system/cpu/cpu0/cpufreq/scaling_governor = ondemand' >> /etc/sysfs.conf
echo 'devices/system/cpu/cpufreq/ondemand/up_threshold = 60' >> /etc/sysfs.conf

Part 2: Wireless

aptitude --without-recommends install ifplugd wpasupplicant
aptitude install ifmetric iw wireless-tools resolvconf
systemctl enable resolvconf
systemctl start resolvconf
sed -i -e 's/raspbian jessie main firmware$/raspbian wheezy main firmware non-free/g' /etc/apt/sources.list
aptitude update && aptitude forget-new
aptitude install firmware-ralink firmware-atheros
sed -i -e 's/^REGDOMAIN=$/REGDOMAIN=US/g' /etc/default/crda
sed -i -e 's/^INTERFACES=""/INTERFACES="eth0"/g' /etc/default/ifplugd
sed -i -e 's/^auto eth0/#allow-hotplug eth0/g' /etc/network/interfaces
/etc/init.d/ifplugd restart

echo >> /etc/network/interfaces
echo 'allow-hotplug wlan0' >> /etc/network/interfaces
echo 'iface wlan0 inet manual' >> /etc/network/interfaces
echo '  wpa-driver nl80211,wext' >> /etc/network/interfaces
echo '  wpa-roam /etc/wpa_supplicant/tom.conf' >> /etc/network/interfaces
echo '  # not supported on realtek dongle:' >> /etc/network/interfaces
echo '  #pre-up iwconfig $IFACE power off' >> /etc/network/interfaces
echo >> /etc/network/interfaces
echo 'iface tom inet dhcp' >> /etc/network/interfaces
echo '  metric 1' >> /etc/network/interfaces
cat > /etc/wpa_supplicant/tom.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
  ssid="tom-2.4"
  psk="***PASSWORD***"
  priority="9"
  id_str="tom"
}

network={
  ssid="tom-5.8"
  psk="***PASSWORD***"
  priority="10"
  id_str="tom"
}
^D
aptitude install watchdog
sed -i -e 's/^watchdog_module="none"/watchdog_module="bcm2835_wdt"/g' /etc/default/watchdog
sed -i -e 's/^#watchdog-device/watchdog-device/g' /etc/watchdog.conf
sed -i -e 's/^#max-load-1\t/max-load-1\t/g' /etc/watchdog.conf
echo "# Raspberry Pi doesn't work with the default timeout of 60; set it to 10 instead" >> /etc/watchdog.conf
echo $'watchdog-timeout\t= 10' >> /etc/watchdog.conf
ln -s /lib/systemd/system/watchdog.service /etc/systemd/system/multi-user.target.wants/
echo '[Unit]' > /etc/systemd/system/led_heartbeat.service
echo 'Description=Inverse Heartbeat Pattern on Power LED' >> /etc/systemd/system/led_heartbeat.service
echo 'After=multi-user.target' >> /etc/systemd/system/led_heartbeat.service
echo >> /etc/systemd/system/led_heartbeat.service
echo '[Service]' >> /etc/systemd/system/led_heartbeat.service
echo 'Type=oneshot' >> /etc/systemd/system/led_heartbeat.service
echo 'RemainAfterExit=yes' >> /etc/systemd/system/led_heartbeat.service
echo "ExecStart=/bin/sh -c 'echo heartbeat > /sys/class/leds/led1/trigger && echo 1 > /sys/class/leds/led1/invert'" >> /etc/systemd/system/led_heartbeat.service
echo "ExecStop=/bin/sh -c 'echo input > /sys/class/leds/led1/trigger'" >> /etc/systemd/system/led_heartbeat.service
echo >> /etc/systemd/system/led_heartbeat.service
echo '[Install]' >> /etc/systemd/system/led_heartbeat.service
echo 'WantedBy=multi-user.target' >> /etc/systemd/system/led_heartbeat.service
systemctl enable led_heartbeat.service && systemctl start led_heartbeat.service

echo '[Unit]' > /etc/systemd/system/no_console_blank.service
echo 'Description=Disable Console Blanking' >> /etc/systemd/system/no_console_blank.service
echo >> /etc/systemd/system/no_console_blank.service
echo '[Service]' >> /etc/systemd/system/no_console_blank.service
echo 'Type=oneshot' >> /etc/systemd/system/no_console_blank.service
echo 'ExecStart=/usr/bin/setterm --term linux --blank 0 --powersave off' >> /etc/systemd/system/no_console_blank.service
echo 'StandardInput=tty-force' >> /etc/systemd/system/no_console_blank.service
echo 'StandardOutput=tty' >> /etc/systemd/system/no_console_blank.service
echo 'StandardError=journal' >> /etc/systemd/system/no_console_blank.service
echo 'TTYPath=/dev/tty1' >> /etc/systemd/system/no_console_blank.service
echo >> /etc/systemd/system/no_console_blank.service
echo '[Install]' >> /etc/systemd/system/no_console_blank.service
echo 'WantedBy=multi-user.target' >> /etc/systemd/system/no_console_blank.service
systemctl enable no_console_blank.service
aptitude install ola ola-python
shopt -s extglob
sed -i 's/enabled = true/enabled = false/g' /etc/ola/!(*artnet.conf)
shopt -u extglob
# sed -i 's/enabled = false/enabled = true/g' /etc/ola/ola-ftdidmx.conf
systemctl stop olad && killall olad

echo '[Unit]' > /etc/systemd/system/olad.service
echo 'Description=OLA daemon' >> /etc/systemd/system/olad.service
echo 'After=network.target' >> /etc/systemd/system/olad.service
echo >> /etc/systemd/system/olad.service
echo '[Service]' >> /etc/systemd/system/olad.service
echo 'ExecStart=/usr/bin/olad --syslog --log-level 3 --config-dir /etc/ola' >> /etc/systemd/system/olad.service
echo 'User=olad' >> /etc/systemd/system/olad.service
echo 'Restart=always' >> /etc/systemd/system/olad.service
echo 'RestartSec=2' >> /etc/systemd/system/olad.service
echo >> /etc/systemd/system/olad.service
echo '[Install]' >> /etc/systemd/system/olad.service
echo 'WantedBy=multi-user.target' >> /etc/systemd/system/olad.service
systemctl daemon-reload && systemctl enable olad.service

** setup files to copy artnet port 10 to ftdi and restore config in case of issues:
mkdir /root/ola-backup
echo '2-1-I-0 = 5' > /root/ola-backup/ola-port.conf
echo 'uni_5_merge = LTP' > /root/ola-backup/ola-universe.conf
echo 'uni_5_name = magicq' >> /root/ola-backup/ola-universe.conf
chown olad:olad /root/ola-backup/ola-port.conf /root/ola-backup/ola-universe.conf
chmod 664 /root/ola-backup/ola-port.conf /root/ola-backup/ola-universe.conf
echo '#!/bin/sh' > /root/ola-backup/restore.sh
echo 'cp -a `dirname $0`/*.conf /etc/ola/' >> /root/ola-backup/restore.sh
chmod +x /root/ola-backup/restore.sh

echo '[Unit]' > /etc/systemd/system/restore_ola_backup.service
echo 'Description=Restore OLA backup' >> /etc/systemd/system/restore_ola_backup.service
echo 'Before=olad.service' >> /etc/systemd/system/restore_ola_backup.service
echo >> /etc/systemd/system/restore_ola_backup.service
echo '[Service]' >> /etc/systemd/system/restore_ola_backup.service
echo 'Type=oneshot' >> /etc/systemd/system/restore_ola_backup.service
echo 'ExecStart=/root/ola-backup/restore.sh' >> /etc/systemd/system/restore_ola_backup.service
echo >> /etc/systemd/system/restore_ola_backup.service
echo '[Install]' >> /etc/systemd/system/restore_ola_backup.service
echo 'WantedBy=multi-user.target' >> /etc/systemd/system/restore_ola_backup.service
systemctl enable restore_ola_backup.service

systemctl start restore_ola_backup && systemctl start olad
aptitude install python-pigpio

mkdir -p /etc/systemd/system/pigpiod.service.d
echo '[Service]' > /etc/systemd/system/pigpiod.service.d/restart.conf
echo 'Restart=always' >> /etc/systemd/system/pigpiod.service.d/restart.conf
echo 'RestartSec=2' >> /etc/systemd/system/pigpiod.service.d/restart.conf

systemctl enable pigpiod && systemctl start pigpiod

/usr/local/bin/artnet_servo.py

#!/usr/bin/python

import atexit
import pigpio
from ola.ClientWrapper import ClientWrapper

ARTNET_UNIVERSE = 5
ARTNET_CHANNEL = 1

# see http://elinux.org/RPi_BCM2835_GPIOs and http://elinux.org/RPi_Low-level_peripherals
SERVO1_GPIO = 22 # pin 15
SERVO2_GPIO = 23 # pin 16

# range: 500-2500
SERVO1_MIN = 1800
SERVO1_MAX = 700
SERVO2_MIN = 1000
SERVO2_MAX = 2000

# range: 0-255
DMX_MIN = int(255 * 0.25) # 0
DMX_MAX = int(255 * 0.75) # 255

DEBUG = False

pi = pigpio.pi()
if not pi.connected:
  print 'ERROR: Not connected to pigpiod'
  exit(1)

_DMX_RANGE = DMX_MAX - DMX_MIN
_SERVO1_RANGE = SERVO1_MAX - SERVO1_MIN
_SERVO2_RANGE = SERVO2_MAX - SERVO2_MIN

def handle_dmx(data):
  dmx_val = data[ARTNET_CHANNEL - 1]
  if dmx_val < DMX_MIN:
    val = DMX_MIN
  elif dmx_val > DMX_MAX:
    val = DMX_MAX
  else:
    val = dmx_val
  servo1 = ((val - DMX_MIN) * _SERVO1_RANGE / _DMX_RANGE) + SERVO1_MIN
  servo2 = ((val - DMX_MIN) * _SERVO2_RANGE / _DMX_RANGE) + SERVO2_MIN
  if DEBUG: print 'DMX: %03d\tServo1: %4d\tServo2: %4d' % (dmx_val, servo1, servo2)
  try:
    pi.set_servo_pulsewidth(SERVO1_GPIO, servo1)
  except:
    print 'ERROR: Cannot set servo 1 pulse width!'
    exit(1)
  try:
    pi.set_servo_pulsewidth(SERVO2_GPIO, servo2)
  except:
    print 'ERROR: Cannot set servo 2 pulse width!'
    exit(1)

def dmx_listen():
  wrapper = ClientWrapper()
  client = wrapper.Client()
  client.RegisterUniverse(ARTNET_UNIVERSE, client.REGISTER, handle_dmx)
  pi.set_mode(SERVO1_GPIO, pigpio.OUTPUT)
  pi.set_mode(SERVO2_GPIO, pigpio.OUTPUT)
  wrapper.Run()

def servos_off():
  pi.set_servo_pulsewidth(SERVO1_GPIO, 0)
  pi.set_servo_pulsewidth(SERVO2_GPIO, 0)

if __name__ == '__main__':
  atexit.register(servos_off)
  dmx_listen()

/usr/local/bin/set_servo1.py

#!/usr/bin/python

import pigpio
import sys

# see http://elinux.org/RPi_BCM2835_GPIOs and http://elinux.org/RPi_Low-level_peripherals
SERVO_GPIO = 22 # pin 15
#SERVO_GPIO = 23 # pin 16

pi = pigpio.pi()
if not pi.connected:
  print 'ERROR: Not connected to pigpiod'
  exit()

def set_servo(val):
  pi.set_mode(SERVO_GPIO, pigpio.OUTPUT)
  pi.set_servo_pulsewidth(SERVO_GPIO, val)

if __name__ == '__main__':
  if len(sys.argv) == 2:
    set_servo(sys.argv[1])
  else:
    print 'usage: python %s value ... where:' % sys.argv[0]
    print '  500 <= value <= 2500'
    print '  or value = 0 (servo off)'

/usr/local/bin/get_servo1.py

#!/usr/bin/python

import pigpio
import sys

# see http://elinux.org/RPi_BCM2835_GPIOs and http://elinux.org/RPi_Low-level_peripherals
SERVO_GPIO = 22 # pin 15
#SERVO_GPIO = 23 # pin 16

pi = pigpio.pi()
if not pi.connected:
  print 'ERROR: Not connected to pigpiod'
  exit()

def get_servo():
  print int(pi.get_servo_pulsewidth(SERVO_GPIO))

if __name__ == '__main__':
  if len(sys.argv) == 1:
    get_servo()
  else:
    print 'usage: python %s' % sys.argv[0]
adduser --system --home /nonexistent --no-create-home servo

echo '[Unit]' > /etc/systemd/system/artnet_servo.service
echo 'Description=Artnet Servo Control' >> /etc/systemd/system/artnet_servo.service
echo 'Requires=olad.service' >> /etc/systemd/system/artnet_servo.service
echo 'Requires=pigpiod.service' >> /etc/systemd/system/artnet_servo.service
echo 'After=olad.service' >> /etc/systemd/system/artnet_servo.service
echo 'After=pigpiod.service' >> /etc/systemd/system/artnet_servo.service
echo >> /etc/systemd/system/artnet_servo.service
echo '[Service]' >> /etc/systemd/system/artnet_servo.service
echo 'ExecStart=/usr/local/bin/artnet_servo.py' >> /etc/systemd/system/artnet_servo.service
echo 'User=servo' >> /etc/systemd/system/artnet_servo.service
echo 'Environment=PYTHONUNBUFFERED=1' >> /etc/systemd/system/artnet_servo.service
echo >> /etc/systemd/system/artnet_servo.service
echo 'Restart=always' >> /etc/systemd/system/artnet_servo.service
echo 'RestartSec=1' >> /etc/systemd/system/artnet_servo.service
echo >> /etc/systemd/system/artnet_servo.service
echo '[Install]' >> /etc/systemd/system/artnet_servo.service
echo 'WantedBy=multi-user.target' >> /etc/systemd/system/artnet_servo.service
systemctl enable artnet_servo && systemctl start artnet_servo
echo '#!/bin/sh' > /usr/local/bin/ola-reload-plugins.sh
echo 'if ! pidof /usr/bin/olad > /dev/null; then' >> /usr/local/bin/ola-reload-plugins.sh
echo '  exit 0' >> /usr/local/bin/ola-reload-plugins.sh
echo 'fi' >> /usr/local/bin/ola-reload-plugins.sh
echo 'wget -q -O /dev/null --timeout=0.5 http://localhost:9090/reload &' >> /usr/local/bin/ola-reload-plugins.sh
echo 'exit 0' >> /usr/local/bin/ola-reload-plugins.sh
chmod +x /usr/local/bin/ola-reload-plugins.sh
** add /usr/local/bin/ola-reload-plugins.sh to post-up for eth0, tom in /etc/network/interfaces

TODO:

  • test olad behavior on network up/down (and down at boot) - maybe copy workaround for reloading plugins from artnet-dmx node
  • determine and test servo values
  • add ola_dmxmonitor – this is not in the package at the moment – see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=830508

Raspberry Pi Camera

  • echo >> /boot/config.txt
    echo 'start_x=1' >> /boot/config.txt # weird name for the variable that enables the camera
    echo 'gpu_mem=128' >> /boot/config.txt # needed for video
    reboot
  • wget -O- http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | apt-key add -
    echo 'deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ jessie main' > /etc/apt/sources.list.d/uv4l.list
    aptitude update
    aptitude install uv4l uv4l-raspicam uv4l-raspicam-extras uv4l-server
    sed -i -e 's/^# width = 640$/width = 1280/g' -e 's/^# height = 480$/height = 960/g' /etc/uv4l/uv4l-raspicam.conf
    
    echo '[Unit]' > /etc/systemd/system/uv4l_raspicam.service
    echo 'Description=Userspace Camera Driver' >> /etc/systemd/system/uv4l_raspicam.service
    echo >> /etc/systemd/system/uv4l_raspicam.service
    echo '[Service]' >> /etc/systemd/system/uv4l_raspicam.service
    echo 'ExecStart=/usr/bin/uv4l -f -k --sched-fifo --mem-lock --config-file=/etc/uv4l/uv4l-raspicam.conf --driver raspicam --driver-config-file=/etc/uv4l/uv4l-raspicam.conf --server-option=--editable-config-file=/etc/uv4l/uv4l-raspicam.conf' >> /etc/systemd/system/uv4l_raspicam.service
    echo 'Nice=5' >> /etc/systemd/system/uv4l_raspicam.service
    echo 'Restart=always' >> /etc/systemd/system/uv4l_raspicam.service
    echo 'RestartSec=2' >> /etc/systemd/system/uv4l_raspicam.service
    echo >> /etc/systemd/system/uv4l_raspicam.service
    echo '[Install]' >> /etc/systemd/system/uv4l_raspicam.service
    echo 'WantedBy=multi-user.target' >> /etc/systemd/system/uv4l_raspicam.service
    systemctl enable uv4l_raspicam.service && systemctl start uv4l_raspicam.service
  • Alternate: Direct command line commands:
    # This is way simpler, but doesn't seem to close properly when client disconnects.  Probably a systemd issue?
    
    raspistill -t 1 -n -o /tmp/cam.jpg
    
    # this closes properly iff running from terminal (not systemd)
    on rpi: raspivid -t 0 -o - | nc -l -p 8090
    on client: vlc tcp://rpi-shutter:8090 :demux=h264
    
    /etc/systemd/system/camera.socket:
    [Unit]
    Description=Camera socket
    
    [Socket]
    ListenStream=8090
    Accept=true
    MaxConnections=1
    RemoveOnStop=true
    
    [Install]
    WantedBy=sockets.target
    
    /etc/systemd/system/camera@.service:
    [Unit]
    Description=Camera per-connection server
    
    [Service]
    #ExecStart=/bin/sh -c '/bin/cat | /usr/bin/raspivid -t 0 -o -'
    ExecStart=/usr/bin/raspivid -t 0 -o -
    StandardInput=none
    StandardOutput=socket
    
    problem:  After client disconnects, raspivid still continues to stream video to closed socket, spewing tons of errors.  No new clients can connect.
  • Alternate 2: Video4Linux kernel module:
    echo bcm2835-v4l2 >> /etc/modules
    modprobe bcm2835-v4l2
    aptitude install v4l-utils
    v4l2-ctl # to set camera params -- see https://github.com/raspberrypi/linux/blob/rpi-4.4.y/Documentation/video4linux/bcm2835-v4l2.txt
    
    maybe: aptitude install dov4l
    maybe: aptitude install v4l-conf

See also:

Backup plan:

computer/raspberry_pi_artnet_shutter.txt · Last modified: 2016/07/12 00:46 by tdobes
Recent changes RSS feed Driven by DokuWiki Valid XHTML 1.0 Valid CSS