pi-eyes.sh rewrite, allows Pi 4 use (corresponding code fixes in Pi_Eyes repo)

This commit is contained in:
Phillip Burgess 2022-01-11 09:02:03 -08:00
parent eb56a34456
commit d620d9bbcb

View file

@ -1,30 +1,9 @@
#!/bin/bash #!/bin/bash
if [ $(id -u) -ne 0 ]; then if [ $(id -u) -ne 0 ]; then
echo "Installer must be run as root." echo "Installer must be run as root."
echo "Try 'sudo bash $0'" echo "Try 'sudo bash $0'"
exit 1 exit 1
fi
clear
# smbus and ads1x15 Python libs are installed regardless whether ADC
echo "This script installs software for the Adafruit"
echo "Snake Eyes Bonnet for Raspberry Pi. Steps include:"
echo "- Update package index files (apt-get update)"
echo "- Install Python libraries: numpy, pi3d, svg.path,"
echo " rpi-gpio, python3-dev, python3-pil"
echo "- Install Adafruit eye code and data in /boot"
echo "- Enable SPI0 and SPI1 peripherals if needed"
echo "- Set HDMI resolution, disable overscan"
echo "Run time ~25 minutes. Reboot required."
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
echo
echo -n "CONTINUE? [y/N] "
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
exit 0
fi fi
# FEATURE PROMPTS ---------------------------------------------------------- # FEATURE PROMPTS ----------------------------------------------------------
@ -38,21 +17,60 @@ INSTALL_GADGET=0
# preceded by a number (1 to N), display a prompt, check input until # preceded by a number (1 to N), display a prompt, check input until
# a valid number within the selection range is entered. # a valid number within the selection range is entered.
selectN() { selectN() {
for ((i=1; i<=$#; i++)); do for ((i=1; i<=$#; i++)); do
echo $i. ${!i} echo $i. ${!i}
done done
echo echo
REPLY="" REPLY=""
while : while :
do do
echo -n "SELECT 1-$#: " echo -n "SELECT 1-$#: "
read read
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
return $REPLY return $REPLY
fi fi
done done
} }
clear
echo "This script installs Adafruit Snake Eyes Bonnet"
echo "software for Raspberry Pi. It's best to dedicate"
echo "a card to this, not for systems in regular use."
echo
echo "Target system (may be different than current host):"
selectN "Raspberry Pi 4, Pi 400, or Compute Module 4" "All other models"
#if [[ $? -eq "1" ]]; then
if [ $? -eq "1" ]; then
IS_PI4=1
fi
if [ $IS_PI4 ]; then
# Verify this is Raspbian Desktop OS (X11 should exist)
if [ ! -d "/usr/bin/X11" ]; then
echo "Target system is Pi 4/400/CM4 but this appears to"
echo "be a \"Lite\" OS. \"Desktop\" OS is required."
echo -n "Continue anyway? [y/N]"
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
exit 0
fi
fi
else
# Verify this is Raspbian Lite OS (X11 should NOT exist)
if [ -d "/usr/bin/X11" ]; then
echo "Target system is not Pi 4/400/CM4 yet this appears to"
echo "be a \"Desktop\" OS. \"Lite\" OS (Legacy) is required."
echo -n "Continue anyway? [y/N]"
read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled."
exit 0
fi
fi
fi
SCREEN_VALUES=(-o -t -i) SCREEN_VALUES=(-o -t -i)
SCREEN_NAMES=("OLED (128x128)" "TFT (128x128)" "IPS (240x240)" HDMI) SCREEN_NAMES=("OLED (128x128)" "TFT (128x128)" "IPS (240x240)" HDMI)
RADIUS_VALUES=(128 128 240) RADIUS_VALUES=(128 128 240)
@ -68,40 +86,56 @@ SCREEN_SELECT=$?
echo -n "Install GPIO-halt utility? [y/N] " echo -n "Install GPIO-halt utility? [y/N] "
read read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_HALT=1 INSTALL_HALT=1
echo -n "GPIO pin for halt: " echo -n "GPIO pin for halt: "
read read
HALT_PIN=$REPLY HALT_PIN=$REPLY
fi fi
echo -n "Install ADC support? [y/N] " echo -n "Install Bonnet ADC support? [y/N] "
read read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_ADC=1 INSTALL_ADC=1
fi fi
echo -n "Install USB Ethernet gadget support? (Pi Zero) [y/N] " echo -n "Install USB Ethernet gadget support? (Pi Zero) [y/N] "
read read
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
INSTALL_GADGET=1 INSTALL_GADGET=1
fi fi
echo echo
echo "Screen type: ${SCREEN_NAMES[$SCREEN_SELECT-1]}" echo "Screen type: ${SCREEN_NAMES[$SCREEN_SELECT-1]}"
if [ $INSTALL_HALT -eq 1 ]; then if [ $INSTALL_HALT -eq 1 ]; then
echo "Install GPIO-halt: YES (GPIO$HALT_PIN)" echo "Install GPIO-halt: YES (GPIO$HALT_PIN)"
else else
echo "Install GPIO-halt: NO" echo "Install GPIO-halt: NO"
fi fi
echo "ADC support: ${OPTION_NAMES[$INSTALL_ADC]}" echo "Bonnet ADC support: ${OPTION_NAMES[$INSTALL_ADC]}"
echo "Ethernet USB gadget support: ${OPTION_NAMES[$INSTALL_GADGET]}" echo "Ethernet USB gadget support: ${OPTION_NAMES[$INSTALL_GADGET]}"
if [ $SCREEN_SELECT -eq 3 ]; then if [ $SCREEN_SELECT -eq 3 ]; then
echo "Video resolution will be set to 1280x720, no overscan" echo "Video resolution will be set to 1280x720, no overscan"
else else
echo "Video resolution will be set to 640x480, no overscan" echo "Video resolution will be set to 640x480, no overscan"
fi fi
echo echo
echo -n "CONTINUE? [y/N] " echo "Installation steps include:"
echo "- Update package index files (apt-get update)"
echo "- Install Python libraries: numpy, pi3d, svg.path,"
echo " rpi-gpio, python3-dev, python3-pil"
echo "- Install Adafruit eye code and data in /boot"
echo "- Set HDMI resolution, GPU RAM, disable overscan"
if [ $IS_PI4 ]; then
echo "- Disable desktop, configure video driver"
fi
echo "- Enable SPI0 and SPI1 peripherals if needed"
echo
echo "THIS IS A ONE-WAY OPERATION, NO UNINSTALL PROVIDED."
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
echo "Run time ~10 minutes. Reboot required."
echo
echo -n "Do you understand and want to proceed? [y/N]"
read read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Canceled." echo "Canceled."
@ -115,26 +149,26 @@ fi
# perform replacement if found, else append replacement to end of file. # perform replacement if found, else append replacement to end of file.
# (# $1 = filename, $2 = pattern to match, $3 = replacement) # (# $1 = filename, $2 = pattern to match, $3 = replacement)
reconfig() { reconfig() {
grep $2 $1 >/dev/null grep $2 $1 >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# Pattern found; replace in file # Pattern found; replace in file
sed -i "s/$2/$3/g" $1 >/dev/null sed -i "s/$2/$3/g" $1 >/dev/null
else else
# Not found; append (silently) # Not found; append (silently)
echo $3 | sudo tee -a $1 >/dev/null echo $3 | sudo tee -a $1 >/dev/null
fi fi
} }
# Same as above, but appends to same line rather than new line # Same as above, but appends to same line rather than new line
reconfig2() { reconfig2() {
grep $2 $1 >/dev/null grep $2 $1 >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# Pattern found; replace in file # Pattern found; replace in file
sed -i "s/$2/$3/g" $1 >/dev/null sed -i "s/$2/$3/g" $1 >/dev/null
else else
# Not found; append to line (silently) # Not found; append to line (silently)
sed -i "s/$/ $3/g" $1 >/dev/null sed -i "s/$/ $3/g" $1 >/dev/null
fi fi
} }
echo echo
@ -145,8 +179,8 @@ apt-get update
echo "Installing Python libraries..." echo "Installing Python libraries..."
# WAS: apt-get install -y --force-yes python-pip python-dev python-imaging python-smbus # WAS: apt-get install -y --force-yes python-pip python-dev python-imaging python-smbus
apt-get install -y python3-pip python3-dev python3-pil python3-smbus libatlas-base-dev apt-get install -y python3-pip python3-dev python3-pil python3-smbus libatlas-base-dev
# WAS: pip3 install numpy pi3d svg.path rpi-gpio adafruit-ads1x15 # WAS: pip3 install numpy pi3d==2.34 svg.path rpi-gpio adafruit-ads1x15
pip3 install numpy pi3d==2.34 svg.path rpi-gpio adafruit-blinka adafruit-circuitpython-ads1x15 pip3 install numpy pi3d svg.path rpi-gpio adafruit-blinka adafruit-circuitpython-ads1x15
# smbus and Blinka+ADC libs are installed regardless whether ADC is # smbus and Blinka+ADC libs are installed regardless whether ADC is
# enabled; simplifies the Python code a little (no "uncomment this") # enabled; simplifies the Python code a little (no "uncomment this")
@ -158,110 +192,165 @@ unzip master.zip
cp -r Pi_Eyes-master /boot/Pi_Eyes cp -r Pi_Eyes-master /boot/Pi_Eyes
rm -rf master.zip Pi_Eyes-master rm -rf master.zip Pi_Eyes-master
if [ $INSTALL_HALT -ne 0 ]; then if [ $INSTALL_HALT -ne 0 ]; then
echo "Installing gpio-halt in /usr/local/bin..." echo "Installing gpio-halt in /usr/local/bin..."
curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
unzip master.zip unzip master.zip
cd Adafruit-GPIO-Halt-master cd Adafruit-GPIO-Halt-master
make make
mv gpio-halt /usr/local/bin mv gpio-halt /usr/local/bin
cd .. cd ..
rm -rf Adafruit-GPIO-Halt-master rm -rf Adafruit-GPIO-Halt-master
fi fi
# CONFIG ------------------------------------------------------------------- # CONFIG -------------------------------------------------------------------
echo "Configuring system..." echo "Configuring system..."
if [ $IS_PI4 ]; then
# Make desktop system to boot to console (from raspi-config script):
systemctl set-default multi-user.target
ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
# Pi3D requires "fake" KMS overlay to work. Check /boot/config.txt for
# vc4-fkms-v3d overlay present and active. If so, nothing to do here,
# module's already configured.
grep '^dtoverlay=vc4-fkms-v3d' /boot/config.txt >/dev/null
if [ $? -ne 0 ]; then
# fkms overlay not present, or is commented out. Check if vc4-kms-v3d
# (no 'f') is present and active. That's normally the default.
grep '^dtoverlay=vc4-kms-v3d' /boot/config.txt >/dev/null
if [ $? -eq 0 ]; then
# It IS present. Comment out that line for posterity, and insert the
# 'fkms' item on the next line.
sed -i "s/^dtoverlay=vc4-kms-v3d/#&\ndtoverlay=vc4-fkms-v3d/g" /boot/config.txt >/dev/null
else
# It's NOT present. Silently append 'fkms' overlay to end of file.
echo dtoverlay=vc4-fkms-v3d | sudo tee -a /boot/config.txt >/dev/null
fi
fi
# Disable screen blanking in X config
echo "Section \"ServerFlags\"
Option \"BlankTime\" \"0\"
Option \"StandbyTime\" \"0\"
Option \"SuspendTime\" \"0\"
Option \"OffTime\" \"0\"
Option \"dpms\" \"false\"
EndSection" > /etc/X11/xorg.conf
fi
# Disable overscan compensation (use full screen): # Disable overscan compensation (use full screen):
raspi-config nonint do_overscan 1 raspi-config nonint do_overscan 1
# Dedicate 128 MB to the GPU:
sudo raspi-config nonint do_memory_split 128
# HDMI settings for Pi eyes # HDMI settings for Pi eyes
reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1" reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2" reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87" reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
if [ $SCREEN_SELECT -eq 3 ]; then if [ $SCREEN_SELECT -eq 3 ]; then
# IPS display - set HDMI to 1280x720 # IPS display - set HDMI to 1280x720
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0" reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
else else
# All others - set HDMI to 640x480 # All others - set HDMI to 640x480
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0" reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
fi fi
# Enable I2C for ADC # Enable I2C for ADC
if [ $INSTALL_ADC -ne 0 ]; then if [ $INSTALL_ADC -ne 0 ]; then
raspi-config nonint do_i2c 0 raspi-config nonint do_i2c 0
fi fi
if [ $INSTALL_HALT -ne 0 ]; then if [ $INSTALL_HALT -ne 0 ]; then
# Add gpio-halt to /rc.local: # Add gpio-halt to /rc.local:
grep gpio-halt /etc/rc.local >/dev/null grep gpio-halt /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# gpio-halt already in rc.local, but make sure correct: # gpio-halt already in rc.local, but make sure correct:
sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
else else
# Insert gpio-halt into rc.local before final 'exit 0' # Insert gpio-halt into rc.local before final 'exit 0'
sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
fi fi
fi fi
# If using OLED, TFT or IPS, enable SPI and install fbx2 and eyes.py, # If using OLED, TFT or IPS, enable SPI and install fbx2 and eyes.py,
# else (HDMI) skip SPI, fbx2 and install cyclops.py (single eye) # else (HDMI) skip SPI, fbx2 and install cyclops.py (single eye)
if [ $SCREEN_SELECT -ne 4 ]; then if [ $SCREEN_SELECT -ne 4 ]; then
# Enable SPI0 using raspi-config # Enable SPI0 using raspi-config
raspi-config nonint do_spi 0 raspi-config nonint do_spi 0
# Enable SPI1 by adding overlay to /boot/config.txt # Enable SPI1 by adding overlay to /boot/config.txt
reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on" reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs" reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
# Adjust spidev buffer size to 8K (default is 4K) # Adjust spidev buffer size to 8K (default is 4K)
reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192" reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]} SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
# Auto-start fbx2 on boot # Auto-start fbx2 on boot
grep fbx2 /etc/rc.local >/dev/null grep fbx2 /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# fbx2 already in rc.local, but make sure correct: # fbx2 already in rc.local, but make sure correct:
sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
else else
# Insert fbx2 into rc.local before final 'exit 0' # Insert fbx2 into rc.local before final 'exit 0'
sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
fi fi
RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]} RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
# Auto-start eyes.py on boot # Auto-start eyes.py on boot
grep eyes.py /etc/rc.local >/dev/null grep eyes.py /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# eyes.py already in rc.local, but make sure correct: # eyes.py already in rc.local, but make sure correct:
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null if [ $IS_PI4 ]; then
else sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 eyes.py --radius $RADIUS \:0 \&/g" /etc/rc.local >/dev/null
# Insert eyes.py into rc.local before final 'exit 0' else
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
fi fi
else
# Insert eyes.py into rc.local before final 'exit 0'
if [ $IS_PI4 ]; then
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 eyes.py --radius $RADIUS \:0 \&\\nexit 0/g" /etc/rc.local >/dev/null
else
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
fi
else else
# Auto-start cyclops.py on boot # Auto-start cyclops.py on boot
grep cyclops.py /etc/rc.local >/dev/null grep cyclops.py /etc/rc.local >/dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# cyclops.py already in rc.local, but make sure correct: # cyclops.py already in rc.local, but make sure correct:
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python3 cyclops.py \&/g" /etc/rc.local >/dev/null if [ $IS_PI4 ]; then
else sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 cyclops.py \:0 \&/g" /etc/rc.local >/dev/null
# Insert cyclops.py into rc.local before final 'exit 0' else
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python3 cyclops.py \&/g" /etc/rc.local >/dev/null
fi fi
else
# Insert cyclops.py into rc.local before final 'exit 0'
if [ $IS_PI4 ]; then
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 cyclops.py \:0 \&\\nexit 0/g" /etc/rc.local >/dev/null
else
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
fi
fi
fi fi
if [ $INSTALL_GADGET -ne 0 ]; then if [ $INSTALL_GADGET -ne 0 ]; then
reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2" reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
# Insert ethernet gadget into config.txt after 'rootwait' # Insert ethernet gadget into config.txt after 'rootwait'
sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
fi fi
fi fi
# PROMPT FOR REBOOT -------------------------------------------------------- # PROMPT FOR REBOOT --------------------------------------------------------
@ -273,8 +362,8 @@ echo
echo -n "REBOOT NOW? [y/N] " echo -n "REBOOT NOW? [y/N] "
read read
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
echo "Exiting without reboot." echo "Exiting without reboot."
exit 0 exit 0
fi fi
echo "Reboot started..." echo "Reboot started..."
reboot reboot